Neural Networks and Deep Learning(五)为什么深度神经网络难以训练

本章我们将分析一下为什么深度神经网络难以训练的问题。 首先来看问题:如果神经网络的层次不断加深,则在BP误差反向传播的过程中,网络前几层的梯度更新会非常慢,导致前几层的权重无法学习到比较好的值,这就是梯度消失问题(The vanishing gradient problem)。 以我们在第三章学习的network2.py为例(交叉熵损失函数+Sigmoid激活函数),我们可以计算每个神经元中误差对偏移量\(b\)的偏导\(\partial C/ \partial b\),根据第二章BP网络的知识,\(\partial C/ \partial b\)也是\(\partial C/ \partial w\)的一部分(BP3和BP4的关系),所以如果\(\partial C/ \partial b\)的绝对值大,则说明梯度大,在误差反向传播的时候,\(b\)和\(w\)更新就快。 假设network2的网络结构是[784,30,30,10],即有两个隐藏层,则我们可以画出在误差反向传播过程中,隐藏层每个神经元的\(\partial C/ \partial b\)的大小,用柱子长度表示。由下图可知,我们发现第二个隐藏层的梯度普遍大于第一个隐藏层的梯度,这会是一般现象吗,还是偶然现象? 既然梯度出现了层与层的差异,则可以定义第\(l\)层的梯度(如不加说明,则默认是误差\(C\)对偏移量\(b\)的梯度)向量的长度为\(\| \delta^l \|\),比如\(\| \delta^1 \|\)表示第一个隐藏层中每个神经元的\(\partial C/ \partial b\)的绝对值之和,就是一范数,如果\(\| \delta^l \|\)越大,则说明这一层权重的更新越快。 由此,我们可以画出当有两个隐藏层时,\(\| \delta^l \|\)随epoch的变化情况: 当有三个隐藏层时: 当有四个隐藏层时: 我们发现,规律是惊人的一致,即越靠近输出层的隐藏层,\(\| \delta^l \|\)越大,即梯度更新越快;越靠近输入层的隐藏层,\(\| \delta^l \|\)越小,即梯度更新越慢。 这就会导致梯度消失的问题(The vanishing gradient problem):即在误差反向传播过程中,刚开始权重更新比较快,越到后面(越靠近输入层),则权重更新变得很慢,无法搜索到比较优的值。 所以,对于同样的network2,其他参数都不变,只是单纯增加网络层数,验证集上的准确率反而会下降!按理说网络层数增加,验证集上的准确率会上升,或者不变,至少不应该下降啊,因为最不济增加的网络层什么都不做,准确率应该一样才对,为什么反而下降了呢。虽然层数增加了,但因为上述梯度消失问题,靠近输入层的权重反而没学好,因为权重是随机初始化的,所以验证集上的准确率反而下降了。 那么,为什么层数增加会导致梯度消失问题呢,我们可以从BP的更新公式中一探究竟。 为了简化问题,假设我们的网络每一层只有一个神经元: 则根据BP的更新公式,可以计算得到 $$\begin{eqnarray}\frac{\partial C}{\partial b_1} = \sigma'(z_1) \, w_2 \sigma'(z_2) \,w_3 \sigma'(z_3) \, w_4 \sigma'(z_4) \, \frac{\partial C}{\partial a_4}.\tag{1}\end{eqnarray}$$计算过程其实很简单,对照本博客开头的那张图,\(\sigma'(z_4) \, \frac{\partial C}{\partial a_4}\)就是(BP1),把(BP1)带入(BP2),就是不断乘以\(w^{l+1} \sigma'(z^l)\),然后就能得到下图的公式。 ...

April 14, 2019 · 1 min

Neural Networks and Deep Learning(三·一)梯度消失

原文的第三章内容较多,本博客将分三个部分进行介绍:梯度消失、过拟合与正则化、权重初始化及其他,首先介绍梯度消失问题。 为简单起见,假设网络只包含一个输入和一个神经元,网络的损失是均方误差损失MSE,激活函数是Sigmoid函数。则该网络的参数只包含权重\(w\)和偏移量\(b\)。我们想训练这个网络,使得当输入为1时,输出0。 假设我们随机初始化\(w_0=0.6\),\(b_0=0.9\),则网络的损失随着训练的epoch变化曲线如下,看起来挺好的,一开始损失下降很快,随着epoch增加,损失下降逐渐平缓,直至收敛。 但是,如果随机初始化\(w_0=2.0\),\(b_0=2.0\),则网络的损失一开始下降得很缓慢,要训练到快200个epoch时,损失才快速下降。可以看到同样是300个epoch,由于初始化权重的差别,损失下降的趋势完全不一样,而且对于下面这种情况,到300个epoch时,损失还有下降的空间,所以期望的output不如上面的接近目标值0。 为什么同样的网络,只是因为初始化权重的差异,损失的变化曲线却相差这么多呢,这和我们选择的损失函数与激活函数有关。 回顾一下,我们在上一讲的末尾介绍到如果损失函数是MSE且激活函数是Sigmoid时,有\(\delta^L = (a^L-y) \odot \{\sigma(z^L)(1-\sigma(z^L))\}\),又因为网络只有一个神经元,所以梯度如下: $$\begin{eqnarray}\frac{\partial C}{\partial w} & = & (a-y)\sigma'(z) x = a \sigma'(z),\tag{1}\\\frac{\partial C}{\partial b} & = & (a-y)\sigma'(z) = a \sigma'(z)\tag{2}\end{eqnarray}$$其中第二个等号是把\(x=1\)和\(y=0\)带入得到的。由此可见,误差对两个参数\(w\)和\(b\)的梯度都和激活函数的导数有关,因为激活函数是Sigmoid,当神经元的输出接近0或1时,梯度几乎为0,误差反向传播就会非常慢,导致上图出现损失下降非常慢的现象。这就是梯度消失的原因。 为了解决这个问题,我们可以采取两种策略,一是替换损失函数,一是替换激活函数。 第一种方法是将MSE的损失函数替换为交叉熵损失函数,激活函数依然是Sigmoid。我们考虑一个比本文开头更复杂的网络,仍然是一个输出神经元,但包含多个输入神经元。 此时,交叉熵损失函数定义如下,其中的\(n\)表示训练样本数,\(\frac{1}{n}\sum_x\)表示对所有输入样本\(x\)的交叉熵损失求均值。 $$\begin{eqnarray}C = -\frac{1}{n} \sum_x \left[y \ln a + (1-y ) \ln (1-a) \right]\tag{3}\end{eqnarray}$$我们首先考察为什么(3)可以是一个损失函数,损失函数需要满足如下两个条件: 非负; 当网络输出和目标答案越接近,损失越小;反之损失越大。 简单代入几组不同的样本很容易验证交叉熵满足上述两个条件 ,所以交叉熵可以作为一个损失函数。 下面我们再考察一下为什么交叉熵损失函数+Sigmoid激活函数可以解决梯度消失的问题。首先推导交叉熵损失\(C\)对权重\(w_j\)和\(b\)的梯度: $$\begin{eqnarray}\frac{\partial C}{\partial w_j} & = & -\frac{1}{n} \sum_x \left(\frac{y }{\sigma(z)} -\frac{(1-y)}{1-\sigma(z)} \right)\frac{\partial \sigma}{\partial w_j} \tag{4}\\& = & -\frac{1}{n} \sum_x \left(\frac{y}{\sigma(z)}-\frac{(1-y)}{1-\sigma(z)} \right)\sigma'(z) x_j\tag{5}\\& = & \frac{1}{n}\sum_x \frac{\sigma'(z) x_j}{\sigma(z) (1-\sigma(z))}(\sigma(z)-y).\tag{6}\end{eqnarray}$$上式分子Sigmoid的导数正好可以和分母抵消,得到: ...

March 18, 2019 · 2 min