本文结合维基百科http://en.wikipedia.org/wiki/Backpropagation的说明,对神经网络的后向传播算法做一个总结,并作简单的公式推导。
典型的只含有1个隐层的3层神经网络的后向传播算法流程如下:
initialize network weights (often small random values) do forEach training example ex prediction = neural-net-output(network, ex) // forward pass actual = teacher-output(ex) compute error (prediction - actual) at the output units compute $Delta$ $w_h$ for all weights from hidden layer to output layer // backward pass compute $Delta$ $w_i$ for all weights from input layer to hidden layer // backward pass continued update network weights // input layer not modified by error estimate until all examples classified correctly or another stopping criterion satisfied return the network
简单的说明,即当网络的预测结果出来之后,与真实结果相比,计算出错误率,然后对每个权重$w_{ij}$计算其对错误率的偏导数,然后根据偏导数(梯度)调整权重。
记号:
1、$net_j$记为第$j$个神经元的原始输出;
2、$o_j$记为第$j$个神经元的最终输出;
3、转换函数记为$varphi(mbox{net}_{j}) = varphileft(sum_{k=1}^{n}w_{kj}x_k ight)=o_{j} $;
4、$E$为整个网络的误差函数,一般为目标值$t$与预测值(输出值)$y$的函数$E=f(t,y)$;
5、$L_j$记为节点$j$的所有输出节点的集合,不引起歧义情况下会省略下标。
我们最终要求出的是$frac{partial E}{partial w_{ij}}$,根据链式法则有:
$$frac{partial E}{partial w_{ij}} = frac{partial E}{partial o_j} frac{partial o_j}{partialmathrm{net_j}} frac{partial mathrm{net_j}}{partial w_{ij}} $$
根据定义,$net_j$是$w_{ij}$的线性函数,因此右边最后一项:
$$frac{partial mathrm{net_j}}{partial w_{ij}} = frac{partial}{partial w_{ij}}left(sum_{k=1}^{n}w_{kj}x_k ight) = x_i$$
右边第二项为转换函数$varphi(z)$的导数,一般用的比较多的是logistic函数,$ varphi(z) = frac{1}{1+e^{-z}} $,其导数为
$$frac {partialvarphi}{partial z} = varphi(1-varphi)$$
主要推导的是右部第一项$frac{partial E}{partial o_j}$。
当$j$在输出层时,是比较好计算的,即为$E$对$y$的偏导数:$frac{partial E}{partial o_j} = frac{partial E}{partial y} $。
当$j$在隐层时,我们有以下关系:
$$ frac{partial E}{partial o_j} = sum_{l in L} left(frac{partial E}{partial mathrm{net}_l}frac{partial mathrm{net}_l}{partial o_j} ight) = sum_{l in L} left(frac{partial E}{partial o_{l}}frac{partial o_{l}}{partial mathrm{net}_l}w_{jl} ight) $$
这是一个递推公式,从后层逐渐往前层递推,而最后层即是输出层,由上面公式给出,综合起来,我们有:
$$dfrac{partial E}{partial w_{ij}} = delta_{j} x_{i}$$
where,
$$delta_{j} =frac{partial E}{partial net_j}= frac{partial E}{partial o_j} frac{partial o_j}{partialmathrm{net_j}} = egin{cases} frac{partial E}{partial y_j}varphi '(mbox{net}_{j}) & mbox{if } j mbox{ is an output neuron,}\ (sum_{lin L} delta_{l} w_{jl})varphi '(mbox{net}_{j}) & mbox{if } j mbox{ is an inner neuron.} end{cases} $$
$$$$
代表在节点$j$的净输出(非最终输出)对损失函数造成的影响。
给定学习率,我们可以得到权重的调整度为:
$$Delta w_{ij} = - alpha frac{partial E}{partial w_{ij}} $$
偏置的调整
偏置权重与普通权重只有一个不同之处,即它的输入永远为1,因此将$x_i=1$带入上述诸式,便得到偏置调整的公式。
调整input参数
有的场景,我们可能同时要调整输入。这时我们可以做个等价替换,在真实的输入层前再加一层作为实际输入层,新加的一层与真实输入层节点一一对应,只有对应节点相连。我们每次的实际输入都是全1向量,而实际的输入体现在第一层对应节点的连线的权重上,这样,我们把样本输入从输入等价转换到权重上。
第一层的权重矩阵为对角阵,对角线上的数据即为样本输入。第一层的转换函数为线性函数$varphi(x)=x$。这样安排,即可套入上面所说的后向传播算法中。此时在第一层,
$$varphi '(x)=1~~and~~x_i=1$$
$$dfrac{partial E}{partial w_{ij}} = delta_{j} x_{i}=(sum_{lin L} delta_{l} w_{jl})varphi '(mbox{net}_{j})x_i=sum_{lin L} delta_{l} w_{jl}$$
AutoEncoder调整input参数
AutoEncoder是特殊的三层bp网络,输出与输入相等,即是无监督的。对AutoEncoder网络,调整一般权重与上述推导一样,而调整input向量则有所不同。
我们看网络的误差函数$E=f(t,y)$,当是一般网络时$t$因为是目标输出,所以是不变的,当是AutoEncoder网络时,$t$即为input,是可变的,当调整input时,t也跟着调整。
设第$i$个输入为$v_i$,根据链式法则,我们得到:
$$frac{partial E}{partial v_i}=frac{partial E}{partial y}frac{partial y}{partial v_i}+frac{partial E}{partial t}=sum_{lin L} delta_{l} w_{jl}+frac{partial E}{partial t}$$
特别地,当$E=frac{1}{2}sum{(y-t)^2}$时,上式变为:
$$frac{partial E}{partial v_i}=sum_{lin L} delta_{l} w_{jl}+(v_i-O_i)$$
Norm规整
有时我们需要进一步的限制,在激活函数处理之后,还要求输入向量长度必须为1,隐层向量长度也必须为1。那么在规整化处理这一层,怎么求梯度呢?
设该层节点个数为$k$,输入向量为$x$,权重为$W$,激活函数为$varphi$,则归一化因子为$Z=||{varphi(net_1),varphi(net_2),...,varphi(net_k)}||=[sum_{i=1}^k varphi^2(net_i)]^{frac{1}{2}}$。
则$$o_i=frac{varphi(net_i)}{Z}$$
于是
$$frac{partial o_i}{partial net_i}=frac{varphi '(net_i)Z-varphi(net_i)frac{partial Z}{partial net_i}}{Z^2}$$
其中
$$frac{partial Z}{partial net_i}=frac{varphi (net_i) varphi '(net_i)}{Z}$$
带入得最终公式:
$$frac{partial o_i}{partial net_i}=frac{varphi '(net_i)}{Z}(1-o_i^2)$$
对比上述公式,有两点不同:1)梯度也被归一化因子$Z$归一化,归一化后减去了$o_i$的二次项。
若在输入层进行了规整化处理,那么在输入层,取$varphi '(net_i)=1$,得
$$frac{partial o_i}{partial net_i}=frac{1-o_i^2}{Z}$$
当一个节点的净输出$net_i$改变时,会影响整个$Z$值的改变,进而也会影响到其它节点的输出$o_j$的改变,下面计算$frac{partial o_j}{partial net_i},when i eq j$。
$$frac{partial o_j}{partial net_i}=frac{partial o_j}{partial Z}frac{partial Z}{partial net_i}=-frac{varphi(net_j)}{Z^2}o_i varphi '(net_i)=-frac{varphi '(net_i)}{Z}o_io_j$$
综合起来,对所有的节点,我们得到如下公式:
$$frac{partial o_j}{partial net_i}=frac{varphi '(net_i)}{Z}(delta_{ij}- o_io_j)$$
因此
$$frac{partial E}{partial net_i}=sum_j frac{partial E}{partial o_j}frac{partial o_j}{partial net_i}=frac{varphi '(net_i)}{Z}sum_j frac{partial E}{partial o_j}(delta_{ij}- o_io_j)$$
与L-BFGS算法的区别
L-BFGS是拟牛顿法,是针对目标函数求全局最优点的算法。而后向传播是神经网络优化算法,当然,其目标函数是$E$。神经网络优化,是基于样本的,有监督的,即$E$是样本和权重(==>待调整系数)的函数,每个样本给定,对应一个配置,样本值可看作超参数,权重是变量,等价于给定超参数的情况下求全局最优的变量。当一个样本优化完毕后,再优化下一个样本。
L-BFGS可以看为,超参数隐含已给定,因此是无监督的。
从广义上来讲,将全部样本囊括,然后可以写出一个广义的目标函数,对应批量优化。
狭义上来说,每个样本对应一个目标函数,对应增量优化。
不管增量优化批量优化,神经网络都有一个目标函数,样本给定后,这个目标函数是所有权重的函数$E=E(T,O(X,W))=E(W;X,T)$,$(X,T)$即是样本。对分层神经网络,O(W;X)是嵌套函数。
对于只有输入输出两层的网络:
$$O(W;X)=varphi(W imes X)$$
只要求出梯度向量$g_k= abla E(W)$和海森矩阵$H_k= abla^2E(W)$即可套(拟)牛顿法。
附录
softmax函数
$$h_j=frac{e^{z_j}}{sum e^{z_i}}$$
$$frac{partial h_i}{partial z_j}=h_i(delta_{ij}-h_j) $$
logistic函数
$$ varphi(z) = frac{1}{1+e^{-z}} $$
$$frac {partialvarphi}{partial z} = varphi(1-varphi)$$
hj=ez