有了深度学习框架自动求导、自动更新权值的功能,算法设计者几乎不需要对反向传播算法有深入的了解也可以搭建复杂的模型和网络,通过优化工具方便地训练网络模型。但是反向传播算法和梯度下降算法是神经网络的核心算法,深刻理解其工作原理十分重要。本章先回顾导数、梯度等数学概念,然后推导常用激活函数、损失函数的梯度形式,并开始逐渐推导感知机、多层神经网络的梯度传播方式。
1. 导数与梯度
导数被定义为自变量x在处产生一个微小扰动△x后,函数的输出值的增量△y与自变量增量△x的比值在△x趋于0时的极限a,如果存在,a即为在处的导数:
从几何角度来看,一元函数在某处的导数就是函数的切线在此处的斜率,函数值沿着x方向的变化率。
实际上,(方向)导数是一个非常宽泛的概念,只是因为我们以前接触到的函数大多是一元函数,自变量△x只有2个方向:。当函数的自变量大于一个时,函数的导数拓展为函数值沿着任意△x方向的变化率。导数本身是标量,没有方向,但是导数表征了函数值在某个方向△x的变化率。在这些任意△x方向中,沿着坐标轴的几个方向比较特殊,此时的导数也叫做偏导数。
考虑为多元函数的神经网络模型,比如 shape 为[784,256]的权值矩阵 W,它包含了784*256 个连接权值,我们需要求出 784*256 个偏导数。需要注意的是,在数学公式中,我们一般要讨论的自变量是x,但是在神经网络中,x一般用来表示输入,比如图片,文本,语音数据等,网络的自变量是网络参数集,我们关心的也是误差对网络参数的偏导数等。它其实就是函数输出沿着某个自变量;变化方向上的导数,即偏导数。利用梯度下降算法优化网络时,需要求出网络的所有偏导数。我们把函数所有偏导数写成向量形式:
此时梯度下降算法可以按着向量形式进行更新:
梯度下降算法一般是寻找函数的最小值,有时希望求解函数的最大值,如增强学习中希望最大化奖励函数,则可按着梯度方向更新
这种方式的更新称为梯度上升算法。梯度的方向表示函数值上升最快的方向,梯度的反向表示函数值下降最快的方向。
通过梯度下降算法并不能保证得到全局最优解,这主要是目标函数的非凸性造成的。如下图。深蓝色区域为极小值区域,不同的优化轨迹可能得到不同的最优数值解。
2. 导数常见性质
2.1 基本函数的导数
2.2 常用导数性质
3. 激活函数导数
3.1 Sigmoid函数导数
表达式:
导数表达式:
3.2 ReLU函数导数
表达式:
导数表达式:
3.3 LeakyReLU函数导数
表达式:
导数表达式:
3.4 Tanh函数梯度
表达式:
导数表达式:
4. 损失函数梯度
4.1 均方差函数梯度
均方差损失函数表达式为:
则它的偏导数可以展开为
利用链式法则分解为
即
均方差的导数可以推导为:
4.2 交叉熵函数梯度
在计算交叉熵损失函数时,一般将Softmax函数与交叉熵函数统一实现。先给出Softmax函数的梯度,再给出交叉熵函数的梯度。
Softmax梯度
Softmax表达式:
梯度:
交叉熵梯度
表达式
梯度
5. 全连接层梯度
以全连接层,激活函数采用Sigmoid函数,误差函数为softmax+MSE损失函数的神经网络为例,推导其梯度传播方式。
5.1 单个神经元梯度
对于采用Sigmoid激活函数的神经元模型,它的数学模型可以写为
其中变量的上标表示层数,x表示网络的输入,以权值w的偏导数推导为例。神经元模型如下图所示,图中未画出偏置b,输入节点数为J。其中输入第j个节点到输出的权值连接记为,上标表示权重属于的层数,下标表示当前连接的起始节点号和终止节点号。经过激活函数之前的变量叫做,经过激活函数之后的变量叫,由于只有一个输出节点,。输出与真实标签之间计算误差,误差记为。
如果采用均方差误差函数,考虑到单个神经元只有一个输出,那么损失可以表达为
其中t为真实标签值,添加系数并不影响梯度的方向,计算更简便。以权值连接的第j∈[1,J]号节点的权值为例,考虑损失函数对其的偏导数:
将分解,考虑到Sigmoid函数的导数:
写成,继续推导:
考虑,可得:
从上式可以看到,误差值对权值的偏导数只与输出值、真实值t以及当前权值连接的输入有关。
5.2 全连接层梯度
把单个神经元模型推广到单层全连接层的网络上,如下图所示。输入层通过一个全连接层得到输出向量,与真实标签向量t计算均方差。输入节点数为J,输出节点数为K。
多输出的全连接网络层模型与单个神经元模型的不同之处在于,它多了很多的输出节点,同样的每个输出节点分别对应到真实标签。均方差的误差可以表达为
由于只与节点有关联,上式中的求和符号可以去掉,即i=k:
将代入
考虑Sigmoid函数的导数:
将记为:
最终可得
由此可以看到,某条连接上面的连接,只与当前连接的输出节点,对应的真实值节点的标签,以及对应的输入节点有关。
令,则可以表达为
其中变量表征连接线的终止节点的梯度传播的某种特性,使用表示后,偏导数只与当前连接的起始节点,终止节点处有关,理解起来比较直观。
6. 链式法则
考虑复合函数y=f(u), u=g(x),则可由和推导出:
神经网络的损失函数来自于各个输出节点,其中输出节点又与隐藏层的输出节点相关联,因此链式法则非常适合于神经网络的梯度推导。
前向传播时,数据经过传到倒数第二层的节点,再传播到输出层的节点。在每层只有一个节点时,可以利用链式法则,逐层分解为:
其中,可以由误差函数直接推导出,可以由全连接层公式推导出,的导数即为输入。可以看到,通过链式法则,不需要显示计算误差函数的具体数学表达式,直接可以将偏导数分解,层层迭代即可推导出。
7. 反向传播算法
现在来推导隐藏层的反向传播算法。回顾一下输出层的偏导数公式:
考虑网络倒数第二层的导数,如下图所示,输出层节点数为K,输出为;倒数第二层节点数为J,输出为;倒数第三层的节点数为I,输出为。
首先将均方差误差函数展开:
由于通过每个输出节点与相关联,故此处不能去掉求和符号,运用链式法则将均方差函数拆解:
将代入
利用Sigmoid函数的导数进一步分解
将写回形式,并利用链式法则分解
其中,因此
考虑到与k无关可提取公共项
进一步利用,并利用Sigmoid导数将拆分为
其中的导数可直接推导出为,上式可写为
表达式可简写为
仿照输出层的书写方式,将定义为
此时,可以写为当前连接的起始节点的输出值与终止节点j的梯度信息的简单相乘运算:
通过定义δ变量,每一层的梯度表达式变得更加清晰简洁,其中δ可以简单理解为当前连接对误差函数的贡献值。
小结一下每层的偏导数的计算公式。
输出层
倒数第二层
倒数第三层
其中为倒数第三层的输入,即倒数第四层的输出。
依照此规律,只需要循环迭代计算每一层每个节点的等值即可求得当前层的偏导数,从而得到每层权重矩阵W的梯度,在通过梯度下降算法迭代优化网络参数即可。
8. Himmelblau函数优化实战
step 19: x = [-2.805118 3.1313124], f(x) = 2.2737367544323206e-13 step 39: x = [-2.805118 3.1313124], f(x) = 2.2737367544323206e-13 step 59: x = [-2.805118 3.1313124], f(x) = 2.2737367544323206e-13 step 79: x = [-2.805118 3.1313124], f(x) = 2.2737367544323206e-13 step 99: x = [-2.805118 3.1313124], f(x) = 2.2737367544323206e-13 step 119: x = [-2.805118 3.1313124], f(x) = 2.2737367544323206e-13 step 139: x = [-2.805118 3.1313124], f(x) = 2.2737367544323206e-13 step 159: x = [-2.805118 3.1313124], f(x) = 2.2737367544323206e-13 step 179: x = [-2.805118 3.1313124], f(x) = 2.2737367544323206e-13 step 199: x = [-2.805118 3.1313124], f(x) = 2.2737367544323206e-13