[读书笔记] Neural Networks and Deep Learning Chapter 2

这是我阅读在线书籍《Neural Networks and Deep Learning》第二章的笔记。

手残不小心把整个笔记的文件夹误删了,原来这种事是真的会发生的啊,还好对第一章笔记做了备份= =、

章节链接: http://neuralnetworksanddeeplearning.com/chap2.html

尽力恢复车祸现场。。

先给出一堆变量定义(图来自知乎https://zhuanlan.zhihu.com/p/26765585):

img


在”The four fundamental equations behind backpropagation”之前,主要介绍了一个化简前馈表示的方法:$a^{l} = \sigma(w^l a^{l-1}+b^l)$。

还有两个一个函数允许作为损失函数的两个条件:1. 必须是以网络输出作为参数;2. 损失函数必须写成多个独立样本的损失的和的形式。

以及介绍了哈达玛积(Hadamard product):$(s \odot t)_j = s_j t_j$,就是对应项相乘,例:
$$
\left[\begin{array}{c} 1 \ 2 \end{array}\right]
\odot \left[\begin{array}{c} 3 \ 4\end{array} \right]
= \left[ \begin{array}{c} 1 3 \ 2 4 \end{array} \right]
= \left[ \begin{array}{c} 3 \ 8 \end{array} \right]
$$


The four fundamental equations behind backpropagation

反向传播会计算出$\delta_j^l$,表示为第$l$层的第$j$个神经元的误差。

定义:$\delta^l_j = \frac{\partial C}{\partial z^l_j}$,$z_j^l$为第$l$层的第$j$个神经元的加权输入结果。反向传播的目标就是计算每一层的$\delta^l$,称之为measure of error。反向传播总的来说是4个方程。

words

  1. intermediate:中间的
  2. messes with:由于……而迷糊
  3. perturb:扰乱

首先看看最后一层的损失如何计算:
$$
\delta^L_j = \frac{\partial C}{\partial a^L_j} \sigma’(z^L_j)
$$
$\partial C/\partial a_j^L$用于描述作为第$j$个激活函数的输出变化有多快,如果$C$不依赖于这个神经元,那么$\delta_j^L$会比较小(接近收敛)。后面的$\sigma$的导数表示激活函数在这个点的变化有多快。

这个式子的计算瓶颈在于这个偏导数,于是转换成了下面的形式:
$$
\delta^L = (a^L-y) \odot \sigma’(z^L)
$$
$a^L-y$是$C$的变化率,就是个$\Delta$,拆开后就写成上面哈达玛积的形式了。

再次重申,$\delta^L$表示的是第$L$层(也就是最后一层)的传播误差。for the error in the output layer

接着看看隐层的传播如何计算:
$$
\delta^l = ((w^{l+1})^T \delta^{l+1}) \odot \sigma’(z^l)
$$
式子中很明显,$l$层的误差就是由下一层($l+1$层)反传回去的。

关于对$w^{l+1}$参数矩阵求转置:我是这么理解的,因为输出的时候$l$层用的是$n \times m$的矩阵,想要传回去的话,下层的size就不能是$n\times m$了,而是$m\times n$。转置和下一层的误差相乘,可以把误差传回对应的神经元。

网络中偏差(bias)的损失的计算:
$$
\frac{\partial C}{\partial b^l_j} = \delta^l_j
$$
模型直接可以用该层的损失来更新某个神经元的bias,于是可以简写:$\partial C / \partial b=\delta$。

网络中权重的损失的计算:
$$
\frac{\partial C}{\partial w^l_{jk}} = a^{l-1}_k \delta^l_j
$$
某层某个神经元的输入乘以该神经元的偏差可以认为是这个神经元对于最终损失的影响值。简写为:$\frac{\partial
​ C}{\partial w} = a_{\rm in} \delta_{\rm out}$。

总结四个BP的关键等式:

img

下面对每一个等式进行证明,加深理解。


证明主要分两个部分:

第一部分是推导出反向传播损失函数和输出之间的关系(BP1 BP2)

第二部分是推导出损失函数与权重weight和偏差bias的关系(BP3 BP4)

BP1:
$$
\delta^L = \nabla_aC \odot \sigma’(z^L)
$$
证:对于第$j$个激活函数,有定义:
$$
\delta^L_j = \frac{\partial C}{\partial z^L_j}
$$
展开:
$$
\delta^L_j = \frac{\partial C}{\partial a^L_j} \sigma’(z^L_j)=\dfrac{\part C}{\part a_j^L}\dfrac{\part a_j^L}{\part z_j^L}
$$
由于$a_j^L=\sigma(z_j^L)$,那么$\sigma’(z_j^L)=\dfrac{\partial a_j^L}{\partial z_j^L}$,即:$\delta^L_j = \frac{\partial C}{\partial a^L_j} \sigma’(z^L_j)$

推广至$L$层,公式可简写为:
$$
\delta^L = \frac{\partial C}{\partial a^L} \sigma’(z^L)
$$

BP2:
$$
\delta^l = ((w^{l+1})^T \delta^{l+1}) \odot \sigma’(z^l)
$$
证:由定义展开$\delta^l$:
$$
\delta^l = \frac{\partial C}{\partial z^l}
$$
利用导数的链式法则,对拆成对$z^{l+1}$求导的形式:
$$
\delta^l = \dfrac{\partial C}{\partial z^{l+1}}\dfrac{\part z^{l+1}}{\part z^{l}}=\dfrac{\partial z^{l+1}}{\partial z^{l}}\delta^{l+1}
$$
由于$z^{l+1}=\sum_jw_{j}^{l+1}\delta^l(z_{j}^{l+1})+b^{l+1}$,带入上式即证。

BP3:
$$
\frac{\partial C}{\partial b^l_j} = \delta^l_j
$$
证:
$$
\frac{\partial C}{\partial b^l_j} = \frac{\part C}{\part z^{l+1}_j}\frac{\part z^{l+1}_j}{\part b_j^l}=\delta_j^l\frac{\part(w^l_jz^l+b^l_j)}{\part b_j^l}=\delta_j^l
$$
BP4:

和上面一样,把$b$换成$w$就行。


The backpropagation algorithm

利用上面证明过的4个结论,就可以推导出反向传播算法,算法可以递归形式地定义成这样:

  1. 输入$x$
  2. 前馈:$z^l=w^la^{l-1}+b^l,夏日难a^l=\sigma(z^l)$
  3. 输出误差:$\delta^L = \nabla_aC \odot \sigma’(z^L)$
  4. 反向传播误差:对于每一层$l,l=L-1,L-2…,2$,于是$\delta^l=((w^{l+1})^T\delta^{l+1})\odot \sigma’(z^l)$
  5. 输出:$w,b$的损失函数定义为$\frac{\partial C}{\partial w^l_{jk}} = a^{l-1}_k \delta^l_j$和$\frac{\partial C}{\partial b^l_j} = \delta^l_j$。
  6. $\frac{\partial C}{\partial b^l_j} = \delta^l_j$。

The code for backpropagation

这章实现了用SGD训练的的BP:每次叠小批量的训练集,再计算损失后反传。

介绍了一个可以同时计算多个mini-batch的trick:把多个mini-batch放到一个矩阵里,利用矩阵计算库对矩阵计算的优化来加速训练。


In what sense is backpropagation a fast algorithm?

想在求偏导这一步加速梯度下降的计算,考虑利用$\dfrac{\partial C}{\partial w_j}\approx \dfrac{C(w+\epsilon e_j)-C(w)}{\epsilon}$这样近的似来代替计算偏导,当$\epsilon$很小的时候,起码GD方向是不会变的($\epsilon$很小的话,多叠几次就可以近似等价于梯度方向走步长步)。但是实际上这样做的计算开销仍然会非常大。

而反向传播可以DP地把损失传回去。


Backpropagation: the big picture

img

对于每层输出产生的误差$\Delta a_j^l$,可以用下式做近似:
$$
\Delta a^l_j \approx \frac{\partial a^l_j}{\partial w^l_{jk}} \Delta w^l_{jk}
$$
那么对于这层而言其中一条由输出反传回来的结果则是:
$$
\Delta C \approx \frac{\partial C}{\partial a^L_m}
\frac{\partial a^L_m}{\partial a^{L-1}_n}
\frac{\partial a^{L-1}_n}{\partial a^{L-2}_p} \ldots
\frac{\partial a^{l+1}_q}{\partial a^l_j}
\frac{\partial a^l_j}{\partial w^l_{jk}} \Delta w^l_{jk}
$$
于是考虑所有连通的情况:
$$
\Delta C \approx \sum_{mnp\ldots q} \frac{\partial C}{\partial a^L_m}
\frac{\partial a^L_m}{\partial a^{L-1}_n}
\frac{\partial a^{L-1}_n}{\partial a^{L-2}_p} \ldots
\frac{\partial a^{l+1}_q}{\partial a^l_j}
\frac{\partial a^l_j}{\partial w^l_{jk}} \Delta w^l_{jk}
$$
这就是反向传播对于某一条边更新时需要的计算:
$$
\frac{\partial C}{\partial w^l_{jk}} = \sum_{mnp\ldots q} \frac{\partial C}{\partial a^L_m}
\frac{\partial a^L_m}{\partial a^{L-1}_n}
\frac{\partial a^{L-1}_n}{\partial a^{L-2}_p} \ldots
\frac{\partial a^{l+1}_q}{\partial a^l_j}
\frac{\partial a^l_j}{\partial w^l_{jk}}
$$