神经网络与深度学习(三)——反向传播算法
1. 基于矩阵计算网络输出
首先给出网络中权重的清晰定义。使用表示从层的个神经元到层的个神经元的链接上的权重。如下图所示,给出了第2个隐藏层的第4个神经元到第3个隐藏层的第2个神经元的链接上的权重。
对网络偏差和**值也使用类似的表示。显式地,使用表示在层个神经元的偏差,使用表示层个神经元的**值。如下图所示。
这样一来,层的个神经元的**值就与层的**值关联起来了,如下式所示。
我们引入向量化函数来按照矩阵形式重写上述公式,由于我们对权值矩阵索引下标做出了定义,于是上式就转化为下面这种整洁的形式,避免了对权值矩阵做转置运算。
利用上述方程计算时,我们称中间量为层的带权输入。则的每个元素是,即层个神经元的**函数的带权输入。
2. 关于代价函数的两个假设
反向传播的目标是计算代价函数 分别关于 和 的偏导数和。为了让反向传播可行,我们需要做出关于代价函数的两个主要假设。这里以二次代价函数为例。
其中n是训练样本的总数;求和是在所有的训练样本x上进行的;y=y(x)是对应的目标输出;L表示网络的层数;是当输入是x时的网络输出的**值向量。
第一个假设就是代价函数可以被写成一个在每个训练样本x上的代价函数的均值 。这是关于二次代价函数的例子, 其中对每个独立的训练样本其代价是。需要这个假设的原因是反向传播实际上是对一个独立的训练样本计算了和。然后我们通过在所有训练样本上进行平均化获得和。实际上,有了这个假设,我们会认为训练样本x已经被固定住了,丢掉了其下标,将代价函数看做。
第二个假设就是代价可以写成神经网络输出的函数:
例如,二次代价函数满足这个要求,因为对于一个单独的训练样本 其二次代价函数可以写作:
这是输出的**值的函数。当然,这个代价函数同样还依赖于目标输出。输入的训练样本x是固定的,所以输出同样是一个固定的参数。所以说,并不是可以随意改变权重和偏差的,也就是说,这不是神经网络学习的对象。所以,将看成仅有输出**值的函数才是合理的,而y仅仅是帮助定义函数的参数而已。
3. 反向传播的四个基本方程
1)Hadamard 乘积
反向传播基于一种叫做Hadamard 乘积的矩阵运算实现。特别地,假设s和t是两个同样维度的向量。那么我们使用来表示按元素的乘积。所以的元素就是。给个例子,
2)四个基本方程
反向传播其实是对权重和偏差变化影响代价函数过程的理解。 最终极的含义其实就是计算偏导数和。但是为了计算这些值,我们首先引入一个中间量,这个我们称为在层第个神经元上的误差(error)。反向传播将给出计算误差的流程,然后将其关联到计算和上。
为了理解误差是如何定义的,假设在神经网络上有一个小精灵:
这个小精灵在层的第个神经元上。小精灵通过增加很小的变化,使得神经元输出由变成。这个变化向网络后面的层传播,最终导致整个代价函数产生的改变。为降低代价函数,小精灵可以通过选择与相反符号的。相反,若接近于0,则小精灵不能通过扰动带权输入z来改变太多代价函数。在小精灵看来,这时神经元已经接近最优了。
按照上面描述,我们定义层的个神经元的误差为: 。
这里不加证明地给出反向传播的四个基本方程:
通过观察四个基本方程,可以得出以下结论:
(1)观察方程BP1,这里被定义成一个向量,其元素是偏导数。你可以将其看成关于输出**值的改变速度。举个例子,在二次代价函数时,我们有,所以BP1就变成
回忆sigmoid函数,当函数值接近1或0时,接近于0。所以如果输出神经元处于或者低**值或者高**值时,最终层的权重学习缓慢。这样的情形,我们常常称输出神经元已经饱和了,并且,权重学习也会终止(或者学习非常缓慢)。类似的结果对于输出神经元的偏差也是成立的。
(2)观察方程BP2,其中是权重矩阵的转置。这其实可以很直觉地看做是后在层的输出的误差的反向传播,给出了某种关于误差的度量方式。然后,我们进行Hadamard乘积运算。这会让误差通过层的**函数反向传递回来并给出在的带权输入的误差。
通过组合BP1和BP2,我们可以计算任何层的误差了。首先使用BP1计算,然后应用方程BP2来计算, 然后不断作用BP2,一步一步地反向传播完整个网络。特别地,当输出神经元已经接近饱和,很有可能变小,导致权重学习缓慢。
(3)观察方程BP4,来自很低的**值神经元的权重学习同样会非常缓慢。
4. 反向传播算法
4.1 算法流程
反向传播方程给出了一种计算代价函数梯度的方法。 让我们显式地用算法描述出来:
1. 输入x:为输入层设置对应的**值。
2. 前向传播:对每个l = 2, 3, …, L计算相应的和
3. 输出层误差:计算向量
4. 反向误差传播:对每个l = L-1, L-2, …, 2,计算
5. 输出:代价函数的梯度由和
4.2 反向传播快速的原因
如果仅仅把代价看作权重的函数即C=C(w),则计算某个权值关于C的导数:
其中是一个很小的正数,而是在第j个方向上的单位向量。换句话说,我们可以通过计算的两个接近相同的点的值来估计,然后应用上述公式。同样方法也可以用来计算。
然后,遗憾的是,当你实现了之后,运行起来这样的方法非常缓慢。为了理解原因,假设我们有1,000,000个权重。对每个不同的权重,我们需要计算来计算。这意味着为了计算梯度,我们需要计算代价函数 1,000,000次,需要1,000,000次前向传播(对每个样本) 。我们同样需要计算C(w), 总共是1,000,001次。反向传播聪明的地方就是它确保我们可以同时计算所有的偏导数使用一次前向传播,加上一次后向传播。粗略地说, 后向传播的计算代价和前向的一样。
4.3 反向传播大视野
回顾反向传播算法,可以发现关于代价函数梯度的计算均是基于链式法则进行的。假设某个做一点小小的变动:
那么这个改变逐渐向后面网络层产生影响,最终到达输出层,影响代价函数:
所以代价函数改变与按如下公式关联起来:
同时导致了层个神经元的**值的变化,即
继而影响到下一层的**值的变化,即
则综合前一层变化,有
最终,对于代价函数变化,有
对路径中所有可能的中间神经元选择进行求和。则有
而这个公式告诉我们的是:两个神经元之间的连接其实是关联于一个变化率因子,这仅仅是一个神经元的**值相对于其他神经元的**值的偏导数。从第一个权重到第一个神经元的变化率因子是。路径的变化率因子其实就是这条路径上的众多因子的乘积。而整个的变化率就是对于所有可能的从初始权重到最终输出的代价函数的路径的变化率因子的和。针对某一个路径,这个过程解释如下:
观察发现,可以将反向传播想象成一种计算所有可能的路径变化率的求和的方式。或者,换句话说,反向传播就是一种巧妙地追踪权重(和偏差)微小变化的传播,抵达输出层影响代价函数的技术。