Tensorflow实现BP神经网络

摘要:深度学习中基本模型为BP深度神经网络,其包括输入层、隐含层和输出层。输入层的神经元个数取决于数据集属性特征的个数,输出层神经元个数取决于划分类标的个数。BP神经网络通过梯度下降法不断调整权重矩阵和偏向进行调参,实现神经网络的训练。
  本人为初学者,自己尝试编写了tensorflow实现BP神经网络,输入层为三个神经元。隐含层为四个神经元、输出层为两个神经元,权重矩阵和偏向均为正态分布随机数。
  本人对神经网络进行的剖析,深度神经网络的详细解读:深度神经网络
1、main函数:

#code by WangJianing
#email:851019059@qq.com or lygwjn@126.com
#time:2018.11.24

import tensorflow as tf
import numpy as np
from neural_network import NN
#从文件中读取数据
def readFile(filename):
        """
        read file from txt
        """
        input_x = []
        input_y = []
        with open(filename,'r') as f:
            while True:
                line = f.readline()
                if line == '':
                    break
                else:
                    line = line.replace('\n','')
                    sample = line.split(' ')                    
                    x = sample[0:3]
                    x = list(map(np.float32, x))
                    y = sample[3]
                    y = list(map(np.int32, y))
                    input_x.append(x)
                    input_y.append(y)
        return input_x,input_y
        
#main函数
if __name__ == '__main__':
    config = tf.ConfigProto()
    config.gpu_options.allow_growth = True
    config.gpu_options.per_process_gpu_memory_fraction = 0.2  # need ~700MB GPU memory
    train_x,train_y = readFile('./data.txt')
    test_x,test_y = readFile('./data_test.txt')
    sample_size = [len(train_y),len(test_y)]
    print(sample_size)
    train_x = np.transpose(train_x)
    input_y = np.zeros([2,sample_size[0]])
    test_x = np.transpose(test_x)
    test_y = np.transpose(test_y)
    for ei,i in enumerate(train_y):
        input_y[i[0]][ei]=1
        # print(ei,i)
    #build neural network
    n = NN(train_x, input_y, test_x, test_y, 'GradientDescentOptimizer', sample_size, config, learning_rate=0.05)
    #train
    n.train1()
    #test
    n.test()

2、神经网络类:

#code by WangJianing
#email:851019059@qq.com or lygwjn@126.com
#time:2018.11.24

import tensorflow as tf
import numpy as np

class NN(object):
    """docstring for NN"""
    def __init__(self, train_x, train_y, test_x, test_y, optimize, sample_size, config, learning_rate=0.05):
        super(NN, self).__init__()
        self.train_x = tf.to_float(train_x, name='ToFloat1')
        self.train_y = tf.to_float(train_y, name='ToFloat2')
        self.test_x = tf.to_float(test_x, name='ToFloat3')
        self.test_y = tf.to_float(test_y, name='ToFloat4')
        self.learning_rate = learning_rate
        self.optimize = optimize
        self.sess = tf.Session()        
        self.sample_size = sample_size
        self.config = config
        self.para = [[],[],[],[],0]
        self.bildGraph()
        # self.train()

    #创建计算图(训练时)
    def bildGraph(self):
        self.parameter_op()
        self.towards_op()
        self.loss_op()
        self.backwords_op()
        # self.test_towords()
        self.init_op()
    #创建评估测试计算图
    def testBuildGraph(self):
        self.parameter_op()
        self.towards_op()
    
    #创建参数初始化结点
    def parameter_op(self):
        self.weight1 = tf.Variable(tf.random_normal([4, 3], stddev=0.03), dtype=tf.float32, name='weight1')
        self.bias1 = tf.Variable(tf.random_normal([4, 1]), dtype=tf.float32, name='bias1')
        self.weight2 = tf.Variable(tf.random_normal([2, 4], stddev=0.03), dtype=tf.float32, name='weight2')
        self.bias2 = tf.Variable(tf.random_normal([2, 1]), dtype=tf.float32, name='bias2')
        self.input_xx = tf.Variable(self.train_x,name='xx1')
        self.input_xx_test = tf.Variable(self.test_x,name='xx3')
        self.input_yy = tf.Variable(self.train_y,name='xx2')

    #该方法是将一个一维向量v复制size次并拼起来
    def appendVector(self, v, size, kind):
        _v = tf.transpose(v)[0]
        # print('_v=',_v)
        new_v = []
        if kind == 0:
            for i in range(size):
                new_v.append(_v)
            self.bias1_train = tf.Variable(new_v, dtype=tf.float32, name='bias1_train')
            self.bias1_train = tf.transpose(self.bias1_train)
        elif kind == 1:
            for i in range(size):
                new_v.append(_v)
            self.bias2_train = tf.Variable(new_v, dtype=tf.float32, name='bias2_train')
            self.bias2_train = tf.transpose(self.bias2_train) 
        elif kind == 2:
            for i in range(size):
                new_v.append(_v)
            self.bias1_test = tf.Variable(new_v, dtype=tf.float32, name='bias1_test')
            self.bias1_test = tf.transpose(self.bias1_test) 
        elif kind == 3:
            for i in range(size):
                new_v.append(_v)
            self.bias2_test = tf.Variable(new_v, dtype=tf.float32, name='bias2_test')
            self.bias2_test = tf.transpose(self.bias2_test)  

    #前向传播
    def towards_op(self):
        self.m1 = tf.matmul(self.weight1, self.input_xx, name='matmul1')
        # print('m1=',self.m1)
        self.appendVector(self.bias1, self.sample_size[0], 0)
        # print('self.bias1_train=',self.bias1_train)
        self.z1 = tf.add(self.m1 ,self.bias1_train, name='z1')
        self.a1 = tf.nn.sigmoid(self.z1,name='a1')
        self.appendVector(self.bias2, self.sample_size[0], 1)
        self.z2 = tf.add(tf.matmul(self.weight2, self.a1, name='matmul2'),self.bias2_train, name='z2')
        self.a2 = tf.transpose(tf.nn.softmax(tf.transpose(self.z2,[1,0]),name='a2'),[1,0])

    #测试时前向传播
    def test_towords(self):
        self.t_m1 = tf.matmul(self.para[0], self.input_xx_test, name='matmul3')
        self.appendVector(self.para[2], self.sample_size[1], 2)
        self.t_z1 = tf.add(self.t_m1 ,self.bias1_test, name='z1')
        self.t_a1 = tf.nn.sigmoid(self.t_z1,name='a1')
        self.appendVector(self.para[3], self.sample_size[1], 3)
        self.t_z2 = tf.add(tf.matmul(self.para[1], self.t_a1, name='matmul4'),self.bias2_test, name='z2')
        self.t_a2 = tf.transpose(tf.nn.softmax(tf.transpose(self.t_z2,[1,0]),name='a2'),[1,0])

    #损失函数
    def loss_op(self):
        self.loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(labels=self.train_y, logits=self.a2))
        self.optimizer = tf.train.GradientDescentOptimizer(self.learning_rate)

    #反向传播
    def backwords_op(self):
        self.train = self.optimizer.minimize(self.loss)

    #初始化所有全局变量
    def init_op(self):
        self.init_op = tf.global_variables_initializer()

    #训练
    def train1(self):
        with tf.Session(config=tf.ConfigProto(gpu_options=tf.GPUOptions(per_process_gpu_memory_fraction=0.333))) as sess:
            sess.run(self.init_op)
            for i in range(10):
                sess.run(self.train)
                self.para = [sess.run(self.weight1),sess.run(self.weight2),sess.run(self.bias1),sess.run(self.bias2),sess.run(self.loss)]
                print("==========step",i,"==========")
                print("weight1:\n",self.para[0],"\nb1:\n",self.para[2])
                print("\nweight2:\n",self.para[1],"\nb2:\n",self.para[3])
                print("\nloss=",self.para[4])

    #测试
    def test(self):
        self.test_towords()
        with tf.Session(config=tf.ConfigProto(gpu_options=tf.GPUOptions(per_process_gpu_memory_fraction=0.333))) as sess:
            sess.run(tf.global_variables_initializer())
            sess.run([self.bias1_test,self.bias2_test])
            #每个样本的每个类标取值的概率
            predict_proba = sess.run(self.t_a2)        	
            #预测每个样本的类标(0或1)
            predict_proba = np.transpose(predict_proba)
            print('\npredict_proba=',predict_proba)
            predict_value = np.argmax(predict_proba,axis=1)
            print('\npredic_value=',predict_value)
            #计算准确率:
            # accuracy = 0
            # # print(test_y[0][0])
            # for ei,i in enumerate(predict_value):
            #     if i == self.test_y[0][ei]:
            #         accuracy += 1
            # accuracy  /= sample_size
            # print('\naccuracy=',accuracy)   

  可以详细阅读程序,并尝试在自己的PC上运行。若使用自己的数据集,可修改程序中的相应超参数(学习率、神经网络各层的神经网络个数、train1函数中迭代次数、参数初始化方式、最优化策略、损失函数等)。

博客记录着学习的脚步,分享着最新的技术,非常感谢您的阅读,本博客将不断进行更新,希望能够给您在技术上带来帮助。

GitHub 加速计划 / te / tensorflow
184.55 K
74.12 K
下载
一个面向所有人的开源机器学习框架
最近提交(Master分支:2 个月前 )
a49e66f2 PiperOrigin-RevId: 663726708 2 个月前
91dac11a This test overrides disabled_backends, dropping the default value in the process. PiperOrigin-RevId: 663711155 2 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐