此处开始讲解一个算法来尝试优化神经网络结构的代价函数。
这是一个让代价函数最小化的算法——反向传播算法。
首先来看一下神经网络的代价函数:
要做的就是设法找到参数θ,使得J(θ)取到最小值,为了使用梯度下降法或者其他某种高级优化算法,需要做的就是写一段代码,这段代码获得输入参数θ,并计算J(θ)和这些偏导项:
神经网络里对应的参数Θ_ij^(l)∈R(都是实数)。
为了计算代价函数J(θ),用下面这个公式:
我们大部分时间要重点关注如何计算这些偏导项:
我们从只有一个训练样本的情况开始说起,假设整个训练集只包含一个训练样本,也就是实数对,把这一个训练样本记为(x, y),先粗略看一下,使用这一个训练样本来计算的顺序:
首先我们应用前向传播法:
以此来计算一下在给定输入的时候,假设函数是否会真的输出结果。
具体地说,这里的a^(1)就是第一层的激活值(所谓激活值是指由一个具体神经元计算并输出的值),也就是输入层在的地方,所以假设它为x,然后来计算
然后计算
这就会计算出第一个隐藏层(也就是神经网络的第二层)的激活值a^(2),同时我们增加一个偏置项:
接下来再用2次前向传播来计算出a ^(3)和最后的a ^(4),在这里a ^(4)就是假设函数h(x)的输出。
这里实现了把前向传播向量化,这使得我们可以计算神经网络结构里的每一个神经元的激活值。
接下来为了计算导数项,我们将采用一种叫做反向传播(Backpropagation)的算法:
反向传播算法从直观上说,就是对每一个结点,我们计算这样一项:
它代表第l层的第j个结点的误差。
前面说过a^(l)_j表示的是第l层第j个单元的激活值,所以这个δ项在某种程度上就捕捉到了我们在这个神经节点的激活值的误差,所以我们可能希望这个节点的激活值稍微不一样。
具体地讲,我们用上面那个有四层的神经网络结构做例子:
对于每一个输入单元,我们将计算δ项,所以第四层的第j个单元的δ就等于这个单元的激活值减去训练样本里的真实值:
a_j ^(4)项同样可以写成h_θ ^(x)_j。
所以δ这一项就是假设的输出值和训练集y值之间的差,这里的y_j就是训练集里向量y的第j个元素的值。
如果把δ、a和y都看做向量,那么你同样可以这样写:
并且得出一个向量化的表达式,也就是δ ^(4)=a ^(4) - y,这里δ ^(4)、a ^(4)、y都是一个向量,并且向量维数等于输出单元的数目。
现在我们计算出了网络结构的误差项δ^(4),下一步就是计算网络中前面几层的误差项δ:
点乘.*就是向量元素之间对应的乘法操作。
这里a ^(3)是激活向量,1是以1为元素的向量。
接下来应用一个相似的公式来计算δ^(2):
同样有:
此时已经结束了,这里没有δ^(1)项,因为第一次对应输入层,那是我们在训练集观察到的,所以不会存在误差。所以这个例子中,δ项就只有第2层、第3层和第4层。
反向传播法这个名字源于我们从输出层开始计算δ项,然后返回到上一层,计算第三层的δ项,接着再往前一步来计算δ^(2):
所以说,我们是类似于把输出层的误差反向传播给了第3层,然后是再传到第2层,这就是反向传播的意思。
反向传播算法的推导过程是复杂的,但是如果按照这样的步骤计算:
就有可能简单直接地完成复杂的数学证明(如果不是特别严谨的情况下),即我们要求的偏导数项恰好就等于激活值和这些δ项:
这里忽略了标准化项(即λ项等于0),之后会完善正则化细节。
通过反向传播,计算这些δ项,我们可以非常快速地计算出所有参数的偏导数项。
讲了很多细节,现在把所有内容整合在一起,分析一下如何实现反向传播算法来计算这些参数的偏导数。
假设我们有m个样本的训练集:
要做的第一件事就是固定这些带下标ij的Δ:
Δ就是大写的希腊字母δ
我们将设每一个i和j对应的Δ等于0。
实际上,这些Δij会被用来计算偏导项,对应J的上标(l)、下标ij的θ的偏导数:
所以,下面这些Δ,会被作为累加项,慢慢地增加,以算出这些偏导数,接下来遍历我们的训练集:
对于第i个循环而言,我们将取训练样本(x ^(i), y ^(i))。
于是我们要做的第一件事是设定a ^(1),也就是输入层的激活函数,设定它等于x ^(i):
x(i)是第i个训练样本的输入值。
接下来运用正向传播来计算第二层的激活值,然后是第三层、第四层,到最后一层L层:
然后用这个样本的输出值y(i),来计算这个输出值所对应的误差项δ(L):
所以δ(L)就是假设的输出值减去目标输出。
接下来,将运用反向传播算法来计算δ(L-1)、δ(L-2),直到δ(2)
(没有δ(1),因为不需要对输入层考虑误差项。)
最后将用这些大写的Δ,来累积我们在前面写好的偏导数项:
其中
观察一下这个式子
可以把它写成向量形式。
具体地说,如果把Δ_ij^(l)看作一个矩阵,ij代表矩阵中的位置,那么,Δ(l)就是一个矩阵,我们就可以写成:
这就是用向量化的形式,实现了对所有i和j的自动更新值。
对于j=0和j≠0,分两种情况讨论:
在j≠0的情况下,对应偏差项; 当j=0的时候,没有写额外的标准化项;(这就是为什么当时忽略额外的标准化项。)严格的证明太复杂,但现在可以知道的是,这些D项就是代价函数关于每个参数的偏导数:
然后可以使用梯度下降或者另一种高级优化算法。
这就是反向传播算法以及如何计算出神经网络中所有代价函数关于那些参数的偏导数。
参考资料:吴恩达机器学习系列课程