上一遍文章我们用三个零件的输入前向传播获取到了输出值,我们可以把它当做我们训练数据的中的一个batch,我们的训练数据会有多个batch组成,我们会定义损失函数来计算当前神经网络的预测答案和真实答案之间的差距,正常零件的label为1,坏零件的label为0,我们要算的就是我们神经网络输出层的值和这个我们预先知道的输入层的label之间的差距。然后一个batch结束时,反向运用随机梯度下降SGD算法更新w和biases来生成新的w和biases供下一个batch使用,以此来缩小这个差距。直到训练数据的所有batch结束时也就是一个轮(epoch)完成,然后再把训练数据进行相同的多轮训练,继续缩小这个差距。也就是多轮的epach训练迭代。
tensorflow实现反向传播
接下来我们用tensorflow接着实现神经网络的反向传播
import tensorflowas tf
# 定义变量
w1 = tf.Variable(tf.random_normal([2,3],stddev=1),name="w1")
w2 = tf.Variable(tf.random_normal([3,1],stddev=1),name="w2")
biases1 = tf.Variable(tf.zeros([3]),name="b1")# 隐藏层的偏向bias
biases2 = tf.Variable(tf.zeros([1]),name="b1")# 输出层的偏向bias
# 使用placeholder
x = tf.placeholder(tf.float32,shape=[None,2],name="input")
a = tf.matmul(x,w1) + biases1
y = tf.matmul(a,w2) + biases2
上面的运算前面提到过可以理解为张量(tensor)结构的运算,只有sess.run()才是对数据的运算 我们此时得到了第一轮的输出y
此时我们运用交叉熵函数来计算我们的预测答案和真实答案之间的差距
假设我们想在的训练集如下:
X = [[0.7,0.9],
[0.1,0.4],
[0.5,0.8],
[0.6,0.9],
[0.2,0.4],
[0.6,0.8]]
Y = [[1.,0.,1.,1.,0.,1.]]
Y = np.array(Y).T #把行向量转为列向量
# 训练集数据的大小
date_size =len(X)
# 定义训练数据batch的大小
batch_size =3
以为我们的训练数据有6个零件,我现在设一个batch为3,以为一个epoch由多个batch组成,所以我们现在的epoch有两个batch,也就是说训练一轮我们更新了两次权重和偏向
cross entropy和优化器
cross_entropy cost function如下:
这是分类问题常用的损失函数,我们的目的就是最小化这个C,常用的最小化这个有三种tf.train.GradientDescentOptimizer,tf.AdamOptimizer,tf.train.MomentumOptimizer,tensorflow称它们为优化器。第一个就是我们熟悉的随机梯度下降算法
tensorflow实现如下:
# 定义损失函数来刻画预测值与真实值之间的差距
cross_entropy = -tf.reduce_mean(y_*tf.log(tf.clip_by_value(y,1e-10,1.0)))
learning_rate =0.1
train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(cross_entropy)
训练时我们是每一个batch正向传递结束都要都要调用cost function来计算与真实值得差距,并用优化器最小化这个值来反向更新权重和偏向,供下一个batch使用
with tf.Session()as sess:
init_op = tf.global_variables_initializer()
sess.run(init_op)
for k in xrange(0,date_size,batch_size):
mini_batch = X[k:k+batch_size]
train_y = Y[k:k+batch_size]
sess.run(train_step,feed_dict={x:mini_batch,y_:train_y})
print sess.run(w1,feed_dict={x:mini_batch,y_:train_y})
以上我们就完成了一个epoch的训练,并打印了每次更新后的w,偏向biases,cross entropy也可以这样获取,这时的feed_dict可以理解我指针指向当前数据时,我们设定的变量的值
深度学习主要就是迭代的过程,一个epoch显然不行,我们用相同的训练数据进行多轮的迭代更新
with tf.Session()as sess:
init_op = tf.global_variables_initializer()
sess.run(init_op)
for i in range(1000): # 进行1000个epoch运算
for k in xrange(0,date_size,batch_size):
mini_batch = X[k:k+batch_size]
train_y = Y[k:k+batch_size]
sess.run(train_step,feed_dict={x:mini_batch,y_:train_y})
print sess.run(w1,feed_dict={x:mini_batch,y_:train_y})
if i %10==0:
total_cross_entropy = sess.run(cross_entropy,feed_dict={x:X,y_:Y})
print "第i轮的cross_entropy:",total_cross_entropy
运行结果:
w初始: [[-2.55538154 -0.95418036 -0.37363622]
[-0.28107387 -0.77055448 -1.99585176]]
第0轮 cross_entropy:0.0753737
第1轮 cross_entropy:0.0647165
第2轮 cross_entropy:0.0557314
第3轮 cross_entropy:0.0486983
第4轮 cross_entropy:0.041998
第5轮 cross_entropy:0.0355824
第6轮 cross_entropy:0.0324344
第7轮 cross_entropy:0.0296029
第8轮 cross_entropy:0.0270144
第9轮 cross_entropy:0.0246159
第10轮 cross_entropy:0.0223683
第11轮 cross_entropy:0.0202418
第12轮 cross_entropy:0.0182138
第13轮 cross_entropy:0.0162667
第14轮 cross_entropy:0.0143864
第15轮 cross_entropy:0.0125622
第16轮 cross_entropy:0.0107853
第17轮 cross_entropy:0.00904879
第18轮 cross_entropy:0.00734704
第19轮 cross_entropy:0.00567571
第20轮 cross_entropy:0.0040312
第21轮 cross_entropy:0.00241068
第22轮 cross_entropy:0.000811872
第23轮 cross_entropy:-0
第24轮 cross_entropy:-0
第25轮 cross_entropy:-0
第26轮 cross_entropy:-0
第27轮 cross_entropy:-0
第28轮 cross_entropy:-0
第29轮 cross_entropy:-0
第30轮 cross_entropy:-0
第31轮 cross_entropy:-0
第32轮 cross_entropy:-0
第33轮 cross_entropy:-0
第34轮 cross_entropy:-0
第35轮 cross_entropy:-0
第36轮 cross_entropy:-0
第37轮 cross_entropy:-0
第38轮 cross_entropy:-0
第39轮 cross_entropy:-0
第40轮 cross_entropy:-0
第41轮 cross_entropy:-0
第42轮 cross_entropy:-0
第43轮 cross_entropy:-0
第44轮 cross_entropy:-0
第45轮 cross_entropy:-0
第46轮 cross_entropy:-0
第47轮 cross_entropy:-0
第48轮 cross_entropy:-0
第49轮 cross_entropy:-0
第50轮 cross_entropy:-0
第51轮 cross_entropy:-0
第52轮 cross_entropy:-0
第53轮 cross_entropy:-0
第54轮 cross_entropy:-0
......
更新后w1: [[-2.59262252 -0.99667609 -0.33713353]
[-0.31940967 -0.81404811 -1.95825446]]
我们发现最小化的交叉熵变成了0,这样显然是不行的,这会导致过拟合,就是我们训练的结果在训练集上表现很好,在测试集上表现却不好,下篇文章我们会接着用tensorflow 改进这个问题
完整代码:
import tensorflowas tf
import numpyas np
import matplotlib.pyplotas plt
# 训练集X和对应的label Y,也就是零件的次品为0,正常零件为1
X = [[0.7,0.9],
[0.1,0.4],
[0.5,0.8],
[0.6,0.9],
[0.2,0.4],
[0.6,0.8]]
# X = np.array(X)
Y = [[1.,0.,1.,1.,0.,1.]]
Y = np.array(Y).T
# 训练集数据的大小
date_size =len(X)
# 定义训练数据batch的大小
batch_size =3
# 定义变量
w1 = tf.Variable(tf.random_normal([2,3],stddev=1),name="w1")
w2 = tf.Variable(tf.random_normal([3,1],stddev=1),name="w2")
biases1 = tf.Variable(tf.constant(0.001,shape=[3]),name="b1")# 隐藏层的偏向bias
biases2 = tf.Variable(tf.constant(0.001,shape=[1]),name="b2")# 输出层的偏向bias
# 使用placeholder
x = tf.placeholder(tf.float32,shape=[None,2],name="x-input")
y_ = tf.placeholder(tf.float32,shape=[None,1],name="y-input")
a = tf.matmul(x,w1) + biases1
y = tf.matmul(a,w2) + biases2
cross_entropy = -tf.reduce_mean(y_*tf.log(tf.clip_by_value(y,1e-10,1.0)))
learning_rate =0.001
train_step = tf.train.AdamOptimizer(learning_rate).minimize(cross_entropy)
with tf.Session()as sess:
init_op = tf.global_variables_initializer()
sess.run(init_op)
print "w初始:",sess.run(w1)
# print sess.run(biases1)
for iin range(100):
for kin xrange(0, date_size, batch_size):
mini_batch = X[k:k + batch_size]
train_y = Y[k:k + batch_size]
sess.run(train_step,feed_dict={x: mini_batch, y_: train_y})
# print sess.run(w1, feed_dict={x: mini_batch, y_: train_y})
# print sess.rund(biases1, feed_dict={x: mini_batch, y_: train_y})
if i %1 ==0:
total_cross_entropy = sess.run(cross_entropy,feed_dict={x: X, y_: Y})
print "第%d轮 cross_entropy:%g" %(i,total_cross_entropy)
print "更新后w1:",sess.run(w1)