改进神经网络的方法(学习缓慢,过拟合,梯度消失)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/login_sonata/article/details/76777595

本文内容来自:Michael Nielsen的《Neural Networks and Deep Learning》中文翻译

学习缓慢问题

产生原因

我们之前用的代价函数都是二次代价函数:
这里写图片描述
a是神经元的输出,假设训练输入x=1,输出y=0,求权重和偏置的偏导数有:
这里写图片描述
偏导数受激活函数的变化率的影响,假设我们激活函数为sigmoid函数,我们看一下函数图像:
这里写图片描述
当神经元的输出接近1的时候,曲线非常平缓,求导的值(变化率)会很小,上边式子所求的权重和偏置也会很小,学习速度就会很缓慢(也称作神经元饱和了)。

更换代价函数

为了改进这个问题,引入交叉熵代价函数
这里写图片描述
其中n是训练数据总数。这和使用最大似然来训练是等价的,而最大似然的代价函数是负的对数似然,这和交叉熵代价函数等价。交叉熵能作为代价函数有两个原因,第一,交叉熵是非负的;第二,如果神经元的实际输出接近目标值,那么交叉熵接近0。相比于二次代价函数,还避免了学习速度下降的问题,原因如下,先求偏导:
这里写图片描述
化简:
这里写图片描述
其中分母就是sigmoid函数求导之后的形式,约去,化简得最终形式:
这里写图片描述
这个式子说明权重学习速度受输出中的误差控制,同时这个式子约去了激活函数变化率f’(z),不用再关心它的大小了。求偏置的偏导数也是同理。

能化成这种形式的代价函数还有很多,交叉熵只是其一,只是说如果激活函数是sigmoid函数时,交叉熵代价函数可能比二次代价函数更好。刚才只是一个神经元的交叉熵,现在把它推广到多神经元:
这里写图片描述

softmax

另一种解决学习缓慢问题的方法是柔性最大值(softmax),它为神经网络定义一种新的输出层。在输出层输出时,不再使用sigmoid函数,而是使用柔性最大值函数。比如输出层的第j个神经元的输出为:
这里写图片描述
其中,分母的求和是在所有的输出神经元上进行的。所以可知,每个输出神经元的值相加等于1,所以输出可以看做是一个概率分布(可看作是sigmoid的多分类版)。

softmax是如何解决学习缓慢问题的呢?我们需要定义一个对数似然代价函数:
这里写图片描述
推导一下可得:
这里写图片描述
这个方程其实和我们前边对交叉熵得到的方程类似,事实上,把一个具有对数似然代价的柔性最大值输出层,看作与一个具有交叉熵代价的S型输出层非常相似,所以它可以解决学习缓慢问题。

初始化权重

创建了神经网络后我们需要初始化权重和偏置,目前为止我们都是用正态分布来初始化的,均值为0,标准差为1。现在假设我们输入1000个样本,一半是1,一半是0,简单起见只考虑隐层只有1个神经元的情况,现在这个神经元的输入z=wx+b,其中500项消去了因为输入是0,所以z是遍历501个符合正态分布的变量的和,包含500个权重项和一个偏置项,因此z本身是一个均值为0,标准差为根号下501(约22.4)的高斯分布,因为0消去了现在只有1,1减去均值0之后平方,再累加,再开根号,得到标准差。这是一个很宽的高斯分布:
这里写图片描述
此时可以看到z取值范围很大,所以经过sigmoid函数f(z)后,输出接近0或者1,这种情况下,权重的改变对输出的影响很小,导致学习很缓慢。

解决办法是优化权重的初始化,假设有n个输入,我们采用均值为0,标准差为 1/根号n 的高斯分布去初始化权重。也就是说我们会使高斯分布的图像看起来非常瘦高,使大部分输入非常接近0,这样的话经过sigmoid函数后,输出就不会非常接近1或0了。
这里写图片描述

过拟合问题

除了交叉验证,提前停止模型训练,或者增大数据量这些方法外,解决过拟合问题常用方法有以下几种。

规范化

(1) L2规范化(又叫权重衰减),增加一个额外的项到代价函数,叫规范化项。如下:
这里写图片描述
最后一项是所有权重的平方的和,再用一个因子进行量化,λ为规范化参数,n是训练集大小。
直观来看,规范化的效果是尽量让网络学习到小一点的权重,大的权重只有能够使代价函数的第一项(原始代价函数)有足够的提升时才被允许。所以这可以看作是寻找小权重和最小化原始代价函数的折中,λ越小,越偏向于最小化原始代价函数,反之偏向小权重。小权重会降低模型复杂度,而且模型不会因为一个输入的改变而改变太大,这会降低噪声的影响
注意到我们并没有对偏置进行规范化,因为结果并不会改变太多,同时有一个大的偏置并不会像大的权重那样使神经元对输入太过敏感,反而会让神经元更加容易饱和(这种情况有时候是有用的)。

我们看一下具体是如何调整权重的,对上述规范化的代价函数求导:
这里写图片描述
权重的参数更新就变成了:
这里写图片描述
这和一般的参数更新很像,除了有一个参数重新调整了w。

(2) L1规范化:这个方法是在代价函数后加上一个权重绝对值的和:
这里写图片描述
凭直觉地看,这和L2规范化相似,惩罚大的权重,倾向于让网络优先选择小的权重。同样的我们先求导:
这里写图片描述
上式在w=0时不可导,所以约定sgn(0)=0。参数更新如下:
这里写图片描述

(3) L1和L2的区别:在L1规范化中,权重通过一个常量向0进行缩小。在L2规范化中,权重通过一个和w成比例的量进行缩小。所以,当一个特定的权重绝对值|w|很大时,L1规范化的权重缩小得远比L2规范化要小得多。相反,当一个特定的权重绝对值|w|很小时,L1规范化的权重缩小得要比L2规范化大得多。最终的结果就是:L1规范化会保留重要度较高的权重,而重要度较小的权重会被设置为0。

dropout

和L1、L2规范化不同,dropout并不修改代价函数,而是改变网络本身。具体的,我们会暂时随机删除一定比例的隐藏神经元,输入输出层的神经元不变,经过一次参数更新后恢复被删除的神经元,然后再重复这个过程。
为什么dropout能缓解过拟合?想象一下我们使用同一个训练集训练了好几个不同的网络,我们使用投票的方法产生最终输出,这样的话就算个别模型犯了错误也不影响最终结果,这是一种(代价极大)减轻过拟合的方法。而dropout类似这个过程,丢弃不同神经元类似于训练不同的网络。或者说,因为神经元不能过度依赖其他神经元,dropout可以减少复杂的互适应神经元,这种随机性使模型更健壮。

梯度消失

问题是这样的:随着隐藏层数目的增加,分类准确率反而下降了。具体来说,有很多隐藏层时,前面的隐藏层的参数学习速度要小于后面的隐藏层。这种梯度的不稳定是难以训练的原因。具体如下:
先看下面这个有三层隐藏层的网络,每层一个神经元:
这里写图片描述
w权重,b偏置,c代价函数。代价函数对偏置b1的偏导数如下,可由反向传播推出:
这里写图片描述
看一下sigmoid函数的导数的图像:
这里写图片描述
该导数在f’(0)=1/4时达到最高。如果我们使用标准方法来初始化网络中的权重,那么会使用一个均值为0标准差为1的高斯分布:
这里写图片描述
由上图可知,大部分权重w会满足绝对值小于1,所以wf’(z)<1/4,上边公式项越多,连乘时越小,这就是梯度消失问题。当然也可以把权重初始化大一点,同理可知多项连乘会发生梯度爆炸问题(连乘后很大)。

解决办法,放弃sigmoid激活函数,使用ReLU函数:
这里写图片描述
如此一来,隐层神经元的输入小于0时,梯度为0,大于0时,梯度为1。这样就解决了梯度消失问题。

猜你喜欢

转载自blog.csdn.net/login_sonata/article/details/76777595