BP算法

前言

这里耽搁了很久,找时间对BP算法进行了一次重新的总结。并且写下来,以便在需要使用的时候能够及时的拿出来。
后面的部分主要是对BP算法的过程进行一个简单的描述,尤其是相关数学公式的对推导过程。对于神经网络的基础知识不做描述,如有需要参看资料[1]。主要推导过程来源于资料[2],并且对原文做了一些勘误
[1] UFLDL Tutorial - 神经网络
[2] UFLDL Tutorial - 反向传导算法

符号表示

符号表示参照了以下资料,并进行了一些修改:
[3] UFLDL Tutorial - 稀疏自编码器符号一览表

$N$:表示样本数量
$L$:表示网络的层数
$S_l$:表示第$l$层单元的数目
$\lambda$:表示衰减系数
$w_{ji}^{(l)}$:表示连接第$l$层单元$i$和第$l+1$层单元$j$的权重
$b_{i}^{(l)}$:表示连接第$l$层单元和第$l+1$层单元$i$的偏置
$a_i^{(l)}$:表示第$l$层单元$i$的激活值
$z_i^{(l)}$:表示第$l$层单元$i$的所有输入的加权和
$\delta_i^{(l)}$:表示第$l$层单元$i$的残差
$f(z)$:表示激活函数,一般是sigmoid函数
$(x^{(n)},y^{(n)})$:表示第$n$个样本

BP算法的推导

问题描述

样本训练集
$$Data={(x^{(1)},y^{(1)}),…,(x^{(N)},y^{(N)})}$$

代价函数
$$J(w,b)=\frac{1}{2N} \sum_{n=1}^N | h_{w,b}(x^{(n)})-y^{(n)} |^2 + \frac{\lambda}{2} \sum_{l=1}^{L-1} \sum_{i=1}^{S_l} \sum_{j=1}^{S_{l+1}} (w_{ji}^{(l)})^2$$

参数的更新

参数$w,b$的更新
\begin{align}
w_{ij}^{(l)} &=w_{ij}^{(l)}-\alpha \frac{\partial J(w,b)}{\partial w_{ij}^{(l)}} \\
b_{i}^{(l)} &=b_{i}^{(l)}-\alpha \frac{\partial J(w,b)}{\partial b_{i}^{(l)}}
\end{align}

这里可以将求偏微分的部分展开
\begin{align}
\frac{\partial J(w,b)}{\partial w_{ij}^{(l)}} &= \frac{1}{N} \sum_{n=1}^N \frac{\partial J(w,b;x^{(n)},y^{(n)})}{\partial w_{ij}^{(l)}} + \lambda w_{ij}^{(l)} \\
\frac{\partial J(w,b)}{\partial b_{i}^{(l)}} &= \frac{1}{N} \sum_{n=1}^N \frac{\partial J(w,b;x^{(n)},y^{(n)})}{\partial b_{i}^{(l)}}
\end{align}

残差的计算

针对第$l$层的单元$i$,计算其残差$\delta_i^{(l)}$,它表明了该节点对最终输出值的残差产生了多少影响。

首先,对于第$L$层(输出层)的每个单元$i$计算其残差
\begin{align}
\delta_i^{(L)} &=\frac{\partial J(w,b;x,y)}{\partial z_{i}^{(L)}} = \frac{1}{2} \frac{\partial}{\partial z_i^{(L)}} | y-h_{w,b}(x) |^2 \\
&= \frac{1}{2} \frac{\partial}{\partial z_i^{(L)}} \sum_{j=1}^{S_L} (y_j-a_j^{(L)})^2= \frac{1}{2} \frac{\partial}{\partial z_i^{(L)}} \sum_{j=1}^{S_L} \left( y_j-f(z_j^{(L)}) \right)^2 \\
&= -\left( y_i-f(z_j^{(L)}) \right)f’(z_j^{(L)})
\end{align}

其次,对于第$L-1$层($l=L-1,…,2$)的每个单元$i$计算其残差
\begin{align}
\delta_i^{(L-1)} &=\frac{\partial J(w,b;x,y)}{\partial z_{i}^{(L-1)}}= \frac{1}{2} \frac{\partial}{\partial z_i^{(L-1)}} \sum_{j=1}^{S_L} (y_j-a_j^{(L)})^2 \\
&= \frac{1}{2} \frac{\partial}{\partial z_i^{(L-1)}} \sum_{j=1}^{S_L} \left( y_j-f(z_j^{(L)}) \right)^2 = -\sum_{j=1}^{S_L} \left( y_i-f(z_j^{(L)}) \right)f’(z_j^{(L)}) \frac{\partial z_j^{(L)}}{\partial z_i^{(L-1)}} \\
&=\sum_{j=1}^{S_L} \delta_i^{(L)} \frac{\partial z_j^{(L)}}{\partial z_i^{(L-1)}} =\sum_{j=1}^{S_L} \delta_i^{(L)} \left[ \frac{\partial }{\partial z_i^{(L-1)}} \sum_{k=1}^{S_{L-1}} \left( f(z_k^{(L-1)})w_{jk}^{(L-1)}+b_j^{(L-1)} \right) \right] \\
&= \sum_{j=1}^{S_L} \delta_i^{(L)} w_{ji}^{(L-1)} f’(z_i^{(L-1)}) = \left( \sum_{j=1}^{S_L} \delta_i^{(L)} w_{ji}^{(L-1)} \right) f’(z_i^{(L-1)})
\end{align}

这一节为了表示方便,将每个样本$(x^{(n)},y^{(n)})$简写为$(x,y)$,对应的$y_i$分别表示样本$y$的第$i$个分量。
根据递推关系,可以得到
$$\delta_i^{(l)}=\left( \sum_{j=1}^{S_l} \delta_i^{(l+1)} w_{ji}^{(l)} \right) f’(z_i^{(l)})$$

又由于
$$z_i^{(l+1)} =\sum_{k=1}^{S_l} w_{ik}^{(l)}a_k^{(l)}+b_i^{(l)} $$

分别对$w_{ij}^{(l)}$和$b_i^{(l)}$进行求导得到:
\begin{align}
& \frac{\partial z_i^{(l+1)}}{\partial w_{ij}^{(l)}} =a_j^{(l)} \\
& \frac{\partial z_i^{(l+1)}}{\partial b_i^{(l)}} =1
\end{align}

那么我们最终想要的结果就是如下:
\begin{align}
& \frac{J(w,b;x,y)}{\partial w_{ij}^{(l)}} =\frac{J(w,b;x,y)}{\partial z_i^{(l+1)}} \frac{\partial z_i^{(l+1)}}{\partial w_{ij}^{(l)}} =a_j^{(l)}\delta_i^{(l+1)} \\
& \frac{\partial J(w,b;x,y)}{\partial b_i^{(l)}} =\frac{J(w,b;x,y)}{\partial z_i^{(l+1)}} \frac{\partial z_i^{(l+1)}}{\partial b_i^{(l)}} =\delta_i^{(l+1)}
\end{align}

反向传播的步骤

1.前馈传导
2.对输出层(第$L$层):
$$\delta^{(L)}=-(y-a^{(L)}) \cdot f’(z^{(L)})$$

3.对中间层(第$l$层):
$$\delta^{(l)}=\left( (w^{(l)})^T \delta^{(l+1)} \right) \cdot f’(z^{(L)})$$

4.参数的更新:
\begin{align}
\nabla_{w^{(l)}}J(w,b;x,y) &=\delta^{(l+1)}(a^{(l)})^T \\
\nabla_{b^{(l)}}J(w,b;x,y) &=\delta^{(l+1)}
\end{align}

参考资料

[4] UFLDL Tutorial