文章目录
0 前言
训练DNN模型一般会关注两个结果:第一是检查在训练数据上的结果,第二是检查在测试数据上的结果。面对坏结果,大家可能首先想到的是三种情况:
- 陷入了局部最优解?DNN的参数很多,很难有大部分参数都在同一个位置形成一个局部最优解,一般收敛了就是在最优解了,或者离的也不远。
- 欠拟合?欠拟合是因为参数不够多和样本不够多导致,但是对于DNN来说,参数和样本都是极大满足的,很难发生欠拟合的情况;
- 过拟合?如果不仅是在测试数据上差,在训练数据上也很差,那可能就不是过拟合的问题。
实际对于DNN训练来说以上三个并不是造成坏结果的主要原因,可能就是因为没有训练好。本文就介绍李宏毅老师针对DNN优化训练结果的一些Tips。
1 对于训练结果的优化
1.1 新的激励函数(New Activation Function)
1.1.1 梯度消失问题
一般激励函数会使用Sigmoid函数,但是随着层数增加效果不一定好,会出现一个叫做梯度消失的问题:层数很多的情况下,输入变化一点点,输出就变得很大,并且很快收敛了。
会有以下的情况:
这要涉及到sigmoid本身的性质了:
W变化很大,但是会被sigmoid函数“压”的很小,而且通过一层经过sigmoid函数,就会衰减一次,最后对输出结果影响很小。
1.1.2 ReLU函数
原来的做法是一层一层训练,每一层训练好了再训练下一层,可以解决部分消失梯度问题。但是为了根本解决这个问题,提出了ReLU激励函数:
将激励函数变为ReLU,可以得到以下的网络:
可见输出为0的结点对下一层是没有影响的,而大于0情况的就是线性变化的,就简化为了一个线性网络。
但问题是我们并不需要一个线性的网络,因为太简单了,我们需要一个复杂的网络。其实这个整体来说还是非线性的,当训练样本变化很小的时候,这个确实是线性网络,但是输入改变较大的时候,这个网络结构就改变了,最终的结果就是非线性的了。
但是不能微分?只需要分开算微分就行了。
1.1.3 ReLU - variant
为了解决ReLU在面对样本差异很小时会训练得到线性网络的问题,提出了带参数的变形:
这个>0部分的斜率可以固定为一个较小的值,也可以设置为一个可学习的参数。
1.1.3 Maxout函数
Maxout可以看做是在深度学习网络中加入一层激活函数层,包含一个参数k。这一层相比ReLU,sigmoid等,其特殊之处在于增加了k个神经元,然后输出激活值最大的值,将这个整体作为一个结点的输出:
与常规激活函数不同的是,它是一个可学习的分段线性函数。当只有两个输入时,可以有ReLU的效果:
当输入变化的时候,可以模仿带参数的ReLU - variant的激励函数:
然而任何一个凸函数,都可以由线性分段函数进行逼近近似,如果参数更多的话会有更多奇形怪状的激励函数:
但是怎么训练呢?给定单个样本x,我们可以知道哪个z是最大的,其实影响输出的就是最大的z。实际结果就是训练这个线性的网络。
那些没有被选择的连接上w不就没有被训练到吗?但是实际上会给很多输入样本,每个样本的输入后实际训练使用的w都是不一样的,最后每一个w最后会被训练到。
1.2 自适应的学习率(Adaptive Learning Rate)
对于梯度下降的优化有很多种方法,主流的深度学习优化方法有:SGD,SGDM,Adagrad,RMSProp,Adam等等,详细的介绍可以移步我的另外一篇博客:主流的深度学习优化方法
2 对于测试结果的优化
2.1 (早停法)Early Stopping
当我们训练深度学习神经网络的时候通常希望能获得最好的泛化性能(generalization performance,即可以很好地拟合数据)。但是所有的标准深度学习神经网络结构如全连接多层感知机确实存在过拟合的情况:当网络在训练集上表现越来越好,错误率越来越低的时候,实际上在某一刻,它在测试集的表现已经开始变差。所以我们期望在过拟合和欠拟合之间找到一个平衡点:
早停法是一种被广泛使用的方法,其基本含义是:当模型在验证集上的表现开始下降的时候,停止训练,这样就能避免继续训练导致过拟合的问题。其主要步骤如下:
- 将原始的训练数据集划分成训练集和验证集
- 只在训练集上进行训练,并每个一个周期计算模型在验证集上的误差,例如,每15次epoch(mini batch训练中的一个周期)
- 当模型在验证集上的误差比上一次训练结果差的时候停止训练
- 使用上一次迭代结果中的参数作为模型的最终参数
2.2 正则化(Regularization)
2.2.1 L2正则
L2 展开就是熟悉的欧几里得范数:
求梯度带入的话,等于在原式的基础上使得
w
w
w的系数从1变为
1
−
η
λ
1-\eta \lambda
1−ηλ,可以使得
w
w
w能更快的靠近0。使得权重下降加速,因此L2正则也称weight decay。
越来越小,但是有后面一项会使得最后达到平衡。
2.2.2 L1正则
代入L1求导后,得到含有符号函数的一项,在ω大于0时为1,小于0时为-1,在ω=0时|ω|没有导数,因此可令sgn(0)=0,在0处不使用L1正则化。
L1相比于L2,有所不同:
- L1减少的是一个常量,L2减少的是权重的固定比例,孰快孰慢取决于权重本身的大小,权重大时可能L2快,较小时L1快。
- L1使权重稀疏,L2使权重平滑,一句话总结就是:L1会趋向于产生少量的特征,而其他的特征都是0,而L2会选择更多的特征,这些特征都会接近于0。
2.3 Dropout
Dropout可以作为训练深度神经网络的一种trick供选择。在每个训练批次中,通过让p%的隐层节点值为0,可以明显地减少过拟合现象。
每次更新参数前随机将一定比例的结点丢掉:
会得到一个更精简的网络模型,而且每次训练都会重新选结点:
为了让最后的结果能保持一定的大小,也就是使得dropout的操作对结果的值在伸缩变换的影响抵消,如果dropout的比例为p%,那么最后的全体w都要乘上1-p%:
这里以常用的50%为例:
由上图可见这两种网络最后的输出都为z。
dropout是一种ensemble方法,类似于随机森林的做法,首先随机选取结点训练多个网络:
将所有的w乘上1-p%后叠加,这样就能实现相同的效果。因为这里都是线性叠加的,所以实际上是一样的。当然要最后结果一样,仅限于用线性的激活函数如ReLU,Maxout,但是其他的比如sigmoid函数,其实也是有效果的。
使用dropout的时候可能会使得训练结果变差,但是测试结果会变好。这里注意,测试的时候不能做dropout,而是将所有训练好的网络叠加后求平均。
参考博文:
https://www.datalearner.com/blog/1051537860479157
https://www.cnblogs.com/skyfsm/p/8456968.html
https://blog.csdn.net/program_developer/article/details/80737724