4.7 梯度下降法与误差反向传播算法
本节将对所使用的学习算法进行解释,并以此结束对机器学习基础的介绍。
梯度下降法是一种致力于找到函数极值点的算法。前面介绍过,所谓“学习”便是改进模型参数,以便通过大量训练步骤将损失最小化。有了这个概念,将梯度下降法应用于寻找损失函数的极值点便构成了依据输入数据的模型学习。
下面给出梯度的定义,以防读者对此缺乏了解。梯度是一种数学运算,通常以符号表示。它与导数类似,但也可应用于输入为一个向量、输出为一个标量的函数,损失函数也属于这种类型。
梯度的输出是一个由若干偏导数构成的向量,它的每个分量对应于函数对输入向量的相应分量的偏导:
如果函数接收的输入多于一个变量,则应考虑偏导数。在求偏导时,可将当前变量以外的所有变量视为常数,然后运用单变量求导法则。
偏导数所度量的是函数输出相对于某个特定输入变量的变化率,即当输入变量的值增长时,输出值的增长。
在继续下面的内容之前,有一点需要强调。当提及损失函数的输入变量时,指的是模型的权值,而非实际数据集的输入特征。一旦给定数据集和所要使用的特征类型,这些输入特征便固定下来,无法进行优化。我们所计算的偏导数是相对于推断模型中的每个权值而言的。
之所以关心梯度,是因为它的输出向量表明了在每个位置损失函数增长最快的方向,可将它视为表示了在函数的每个位置向哪个方向移动函数值可以增长。
假设上述曲线对应于损失函数。点表示权值的当前值,即现在所在的位置。梯度用箭头表示,表明为了增加损失,需要向右移动。此外,箭头的长度概念化地表示了如果在对应的方向移动,函数值能够增长多少。
如果向着梯度的反方向移动,则损失函数的值会相应减小。
在上述图表中,如果向梯度的反方向移动,则意味着将向着损失函数值减少的方向移动。
如果沿该方向移动,并再次计算梯度值,并重复上述过程,直至梯度的模为0,将到达损失函数的极小值点。这正是我们的目标,该过程的图形化表示可参考下图。
就是这样。可将梯度下降算法定义为:
请注意用对梯度进行缩放。该参数被称为学习速率(learning rate)。这个参数是必须要使用的,因为梯度向量的长度实际上是一个在“损失函数单元”中而非“权值单元”中度量的量,因此需要对梯度进行缩放,使其能够与权值相加。
学习速率并不是模型需要推断的值,它是一种超参数(hyperparameter),或对模型的一种手工可配置的设置,需要为它指定正确的值。如果学习速率太小,则找到损失函数极小值点时可能需要许多轮迭代;如果太大,则算法可能会“跳过”极小值点并且因周期性的“跳跃”而永远无法找到极小值点,这种现象被称为“超调”(overshooting),在损失函数图形中,它大致如下所示。
在具体实践中,无法绘制损失函数,因为通常它都有非常多的变量,因此要想了解是否发生“超调”,只能查看损失函数值随时间的变化曲线,可利用tf.scalar_summary函数在TensorBoard中得到该曲线。
下图展示了行为良好的损失函数随时间下降的过程,它表明学习速率的选取是合适的。
上图中的蓝色曲线是由TensorBoard绘制的,而红色曲线表示损失函数的下降趋势。
下图展示了当出现“超调”时,损失函数随时间的变化。
在调整学习速率时,既需要使其足够小,保证不至于发生超调,也要保证它足够大,以使损失函数能够尽快下降,从而可通过较少次数的迭代更快地完成学习。
除了学习速率,还有一些其他问题也会影响梯度下降算法的性能。例如,损失函数的局部极值点。我们再次回到之前的损失函数曲线示例,如果权值的初值靠近损失函数右侧的“谷底”,则该算法的工作过程如下。
该算法将找到谷底,并终止迭代,因为它认为自己找到了一个最佳位置。在所有的极值点,梯度的幅度都为0。梯度下降法无法区分迭代终止时到底是到达了全局最小点还是局部极小点,后者往往只在一个很小的邻域内为最优。
可通过将权值随机初始化来改善上述问题。请记住,权值的初值是手工指定的。通过使用随机值,可以增加从靠近全局最优点附近开始下降的机会。
在深度神经网络的语境(后续章节将介绍)中,局部极值点极为常见。一种简单的解释方法是考虑相同的输入如何通过多条不同路径到达输出,从而得到相同的结果。幸运的是,有一些文献已经表明,就损失函数而言,所有这些极值点都接近等价,与全局最小点相比,它们的劣势并不明显。
到目前为止,尚未显式计算过任何导数,因为这是不必要的。TensorFlow提供了tf.gradients方法,可通过符号计算推导出指定的流图步骤的梯度,并将其以张量形式输出。我们甚至不需要手工调用这个梯度计算函数,因为TensorFlow已经实现了大量优化方法,其中就包括梯度下降法。这就是为什么在介绍梯度下降法原理时只介绍高层公式,而不去深入探究该算法的具体实现和数学原理。
下面介绍反向传播算法,它是一种高效计算数据流图中梯度的技术。
以一个单输入、单输出的极简网络为例,该网络拥有两个隐含层,每个隐含层都只含单个神经元。隐含层和输出层神经元的激活函数都采用了sigmoid,而损失将通过交叉熵来计算。这样的网络结构如下所示。
应当注意到其中存在某种模式——每一层的导数都是后一层的导数与前一层输出之积,这正是链式法则的奇妙之处,误差反向传播算法利用的正是这一特点。
前馈时,从输入开始,逐一计算每个隐含层的输出,直到输出层。然后开始计算导数,并从输出层经各隐含层逐一反向传播。为了减少计算量,还需对所有已完成计算的元素进行复用。这便是反向传播算法名称的由来。
请注意,并未使用sigmoid或交叉熵导数的定义。完全可以在网络中采用不同的激活函数或损失函数,所得到的结果大致都是相同的。
这是一个非常简单的示例,但如果某个网络中需要计算损失相对上千个权值的导数,利用该算法将显著降低训练时间的数量级。
最后需要指出,TensorFlow中包含了少量不同的优化算法,它们都是基于计算梯度的梯度下降法。到底哪一种算法更有效,具体取决于输入数据的形状,以及所要求解的问题的特点。
后续章节将介绍在构建更为复杂的模型时,Sigmoid隐含层、softmax输出层以及带有反向传播的梯度下降法都是最为基础的构件。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论