本文将具体介绍如何通过反响传播算法(backpropagation)和梯度下降算法(gradient decent)调整神经网络中参数的取值。梯度下降算法主要用于优化单个参数的取值,而反向传播算法给出了一个高效的方式在所有参数上使用梯度下降算法,从而使神经网络模型在训练数据上的损失函数尽可能小。反向传播算法是训练神经网络的核心算法。

本文略去反向传播算法具体的实现细节和数学证明,默认为已知,在此前提下只关注TensorFlow中的实现和注意事项。需要注意的是,梯度下降算法并不能保证被优化的函数达到全局最优解,只有当损失函数为凸函数时,梯度下降算法才能保证达到全局最优解。

除了不一定能达到全局最优外,梯度下降算法的另一个问题是计算时间太长,因为在每一轮迭代中都要计算全部训练数据上的损失函数。为了加速训练过程,可以使用随机梯度下降的算法。这个算法优化的不是在全部训练数据上的损失函数,而是在每一轮迭代中,随机优化某条数据上的损失函数。但它的问题也很明显:在某一条数据上损失函数更小并不代表在全部数据上损失函数更小,于是使用随机梯度下降优化得到的神经网络甚至可能无法达到局部最优。

为了综合梯度下降算法和随机梯度下降算法的优缺点,在实际应用中一般采用这两个算法的折中——每次计算一小部分数据的损失函数。这一小部分数据被称之为一个batch。通过矩阵运算,每次在一个batch上优化神经网络的参数并不会比单个数据慢太多。另一方面,每次使用一个batch可以大大减小收敛所需要的迭代次数,同时可以使收敛到的结果更加接近梯度下降的效果。以下代码给出了在TensorFlow中如何实现神经网络的训练过程。

batch_size=n

#每次读取一小部分数据作为当前的训练数据来执行反向传播算法。
x=tf.placeholder(tf.float32,shape=(batch_size,2),name='x-input')
y_=tf.placeholder(tf.float32,shape=(batch_size,1),name='y-input')

#定义神经网络结构和优化算法。
loss=... 
train_step=tf.train.AdamOptimizer(0.001).minimize(loss)

#训练神经网络
with tf.Session() as sess:
	#参数初始化
	... 
	#迭代的更新参数
	for i in range(STEPS):
		#准备batch_size个训练数据。一般将所有训练数据随机打乱之后再选取可以得到
		#更好的优化效果
		current_X,current_Y=... 
		sess.run(train_step,feed_dict={x:current_X,y_:current_Y})