利用TensorFlow的playground网站可以直观的查看一个神经网络的工作模式,样本数据集通过学习速率训练后,对结果逐步收敛,而后通过测试集以直观的方式展现学习成果,本文讲解神经网络的实现原理与演示;算法概述TensorFlow提供了一个网站:https://playground.tensorflow.org展现简单神经网络算法的实现原理,我对各个参数和需要理解的地方做了详细标注:
实现一个神经网络算法的步骤如下:
提取问题中的特性集,比如判断零件是否合格可以根据零件的质量和长度来决定,判断一个地区电力的负荷情况可以根据温度,电价,季节等来决定,特征集越多可能对结果越准确;
定义神经网络的“深度”和结构,如何通过输入(特性向量,其实就是一个矩阵,关于矩阵的定义点击查看前一篇文章)得到输出;
根据经验,对相关参数进行调整,比如迭代轮数,学习率等;
通过训练好的神经网络预测未知数据;
注:文章的代码在Win10+VS Code+tesorflow 1.8中运行通过;
前向传播算法与代码演示神经网络通过输入的特性向量经过层层推导到最后输出,并通过输出解决分类和回归问题,那么神经网络的输出怎么得到的呢?就是通过前向传播算法;
比如根据本文的截图定义的神经网络,零件是否合格通过长度和质量决定,比如以[0.7,0.9]作为输入,即长度定义为0.7,质量为0.9(来自样本数据),那么神经网络的第一层的第一个神经元我们定义为a1的值就为0.7w1+0.9w2,其中w1,w2为特征向量连接到该神经元边上的权限值,一般通过tensorflow的随机数得到,第2,3个神经元的值可以按此获取,得到a1,a2,a3三个神经元的值后,再根据这三个神经元连接到输出边上的权重就可以得到输出值,整个过程就是矩阵的乘法运算,如下:
OUTPUT = [0.7,0.9]*[[w1,w2,w3],[w11,w22,w33]]*[w1(2)+w2(2)+w3(2)]
以上过程就是矩阵的1*2矩阵乘上2*3矩阵乘上3*1矩阵,结果就是1*1的结果值,表示零件是否合格;
这个算法编写成tensorflow的代码如下(代码1):
1'''
2神经网络 - 前向传播算法
3'''
4import tensorflow as tf
5w1 = tf.Variable(tf.random_normal((2, 3), stddev=1, seed=1))
6w2 = tf.Variable(tf.random_normal((3, 1), stddev=1, seed=1))
7
8# 假设零件的长度和质量
9x = tf.constant([[0.7,0.9]])
10
11# 前向传播算法,计算第一层a1,a2,a3的值
12a = tf.matmul(x,w1)
13# 第一层输出后与边上权重运算得出零件的结果值
14y = tf.matmul(a,w2)
15
16with tf.Session() as sess:
17 # 利用initializer给变量赋值
18 sess.run(w1.initializer)
19 sess.run(w2.initializer)
20 print(sess.run(y))
21 #另一种写法:也可以使用tf.global_variables_initializer一次性对多个变量赋值
22 #init_op = tf.global_variables_initializer()
23 #sess.run(init_op)
24 #print(sess.run(y))
模型训练
在对模型训练时,一般有一批已经定义好的样本数据,即一批零件长度和质量告知零件是否合格的训练样本,而后可以根据监督学习的方式设置神经网络参数训练数据集,使得已知的样本集尽可能满足答案,而后模型就可以提供预测未知数据的能力;
在神经网络优化算法中,最常用的是反向传播算法,我们可将样本数据通过如下步骤迭代学习:
反向传播算法是一个迭代过程,根据已知的如零件的[0.7.0.9]特征向量可以得出他的输出结果是:3.957578,但[0.7,0.9]如果是已知样本数据,结果是已知的,反向传播算法通过优化更新变量,让预测结果与真实答案尽可能接近。
将代码1稍微改造下,让其接收一组数据(N*2矩阵)得出输出值(N*1矩阵),而后定义一个损失函数刻画预测值与实际答案的差距,而后通过反向传播算法调整神经网络参数使得这个差距可以被缩小,以上步骤通过tensorflow编写的python代码如下:
1import tensorflow as tf
2from numpy.random import RandomState
3
4#定义训练数据batch大小,即一次拿出多少个参与训练
5batch_size = 8
6
7w1 = tf.Variable(tf.random_normal((2, 3), stddev=1, seed=1))
8w2 = tf.Variable(tf.random_normal((3, 1), stddev=1, seed=1))
9
10# 在默认图的一个维度上使用None可以方便使用不同batch_size大小,在训练时需要把数据分成比较小的batch,但在测试时
11# 可一次性载入全部数据,因为数据集大时,将大量数据放入一个batch可能会导致内存溢出
12x = tf.placeholder(tf.float32,shape=(None,2),name="x-input")
13y_ = tf.placeholder(tf.float32,shape=(None,1),name="y-input")
14
15# 前向传播算法,计算第一层a1,a2,a3的值
16a = tf.matmul(x,w1)
17# 第一层输出后与边上权重运算得出零件的结果值
18y = tf.matmul(a,w2)
19
20# 使用sigmoid函数将y转换为0-1的数值,转换后y代表正样本的概率,1-y代表预测是负样本的概率
21y = tf.sigmoid(y)
22cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y,1e-10,1.0))
23+ (1-y)*tf.log(tf.clip_by_value(1-y,1e-10,1.0)))
24#定义学习率
25leaning_rate = 0.001
26#定义反向传播算法来优化神经网络参数
27train_step = tf.train.AdamOptimizer(leaning_rate).minimize(cross_entropy)
28#通过随机数生成一个模拟数据集
29rdm = RandomState(1)
30dataset_size=128
31X = rdm.rand(dataset_size,2)
32#定义规则给出样本标签,x1+x2<1被认为零件合格
33Y = [[int(x1+x2<1)] for (x1,x2) in X]
34
35with tf.Session() as sess:
36 init_op = tf.global_variables_initializer()
37 sess.run(init_op)
38
39 print(sess.run(w1))
40 print(sess.run(w2))
41
42 # 定义迭代数
43 STEP = 5000
44 for i in range(STEP):
45 start = (i*batch_size)%dataset_size
46 end = min(start+batch_size,dataset_size)
47
48 sess.run(train_step,feed_dict={x:X[start:end],y_:Y[start:end]})
49 if(i%1000==0):
50 total_cross_entropy=sess.run(cross_entropy,feed_dict={x:X,y_:Y})
51 print("After %d training steps,交叉嫡为:%g"%(i,total_cross_entropy))
52 print(sess.run(w1))
53 print(sess.run(w2))
从以上代码运行结果可以看到,初始给出的神经网络的权限w1和w2为:
通过反向传播算法优化迭代5000次后,交叉嫡越来越小,最终w1,w2的输出矩阵为:
交叉嫡变小的过程为:
以上程序实现了训练神经网络全过程,步骤如下:
定义神经网络结构和前向传播输出结果;
定义损失函数以及选择反向传播优化算法;
生成灰化并在样本数据上反复运行反向传播算法优化权重;