深度学习模型遇到的问题以及解决的tips(李弘毅机器学习-Tips for deep learning)
在深度学习过程中,我们会遇到很多问题,并不是所有的问题都是overfitting。
比如下面这个很经典的例子:
这个例子中,随着迭代次数的增加,50-layers的网络在训练集上本身就比20-layers的网络表现差。而在测试集上也表现差,这类问题我们不能只看测试集的结果就说是一个overfitting的例子。还要看训练集。因此,在深度学习的过程中我们会遇到很多问题,不同的问题有不同的解决办法。 当下主要有以下办法:
- New activation function(使用新的或者变化的**函数)
- Adaptive Learning rate(适应性变化的学习率)
- Early stopping(早结束)
- Regularization(正则化)
- Dropout
part1 : New activation function
问题:梯度消失(Vanish Gradient )
首先我们对梯度消失的问题进行解释:通过训练我们发现刚network的左端刚开始的部分梯度比较小,对应的学习的比较慢,几乎还保持在刚开始赋予的随机值周围。但是在network的右端梯度比较大,学习的非常快,并且已经接近收敛。这种收敛可并不是什么好现象,因为后端的输入是前端的输出,在输出结果还近似于随机值时,后端开始收敛,那么并没有学习到什么有效的信息。
为什么会出现这种情况呢?我们假设一开始权重的差值w比较大,然后经过一层sigmoid函数,w变小了,然后再经过一层sigmoid函数变得更小,一层一层直到输出层。在l不变的情况下,w不断变小,使得梯度 不断变大。看来问题是出现在**函数sigmoid上面了,我们需要改变它。
这时候,我们将sigmoid函数替换成Relu函数。为什么换成Relu呢,很简单它容易计算,可以看成无限个sigmoid叠加,更重要的是它可以避免梯度消失。
Relu是一种特殊的Maxout,Maxout人如其名就是让比较大的东西输出。Maxout最杰出的地方在于它可以使得**函数变成可以学习的,也就是说随着训练,**函数会不断变化。Maxout主要有两个步骤:一个是分组,这个是事先自己规定好的。第二是比大小,选出最大的,进入下一层。
如上图所示,我们将(5,7)分为一组,(-1,1)分为一组然后进行选出其中比较大的7和1进入下一组。我们前面有说道,Relu是特殊的Maxout,我们来进行一下解释。
我们将另外两个权重为0,也就是我们对于两个节点的值可以绘出两条直线:和。曲线1大于曲线2的情况取曲线1的值,曲线2大于曲线1的情况取曲线2的值。取值情况刚好和ReLu曲线吻合。(这里的ReLu我们进行平移过的Relu并不是原始定义的Relu)。我们将另外两个权重不为0时,也就是我们对于两个节点的值可以绘出两条直线:和=+曲线1大于曲线2的情况取曲线1的值,曲线2大于曲线1的情况取曲线2的值。这里Maxout对应的取值曲线有又变化了(绿色曲线),也就是说得到了一个新的**函数。在使用Maxout进行训练时,我们会使用较大的那一个节点,而将值较小的节点直接忽略掉。但是随着输入X的不断变化,所有节点都会被选中进行连接。
我们可能会有这样的疑问:通过Maxout几乎变成了线性模型,那么等是不是就不会被链接。但是其实不用担心,随着输入值x的变化,谁大谁小也会不断的变化,几乎所有的节点都会被链接。
part2: Adaptive Learning rate
在训练过程中,我们在平缓的地方需要大的learning rate,在陡峭的地方需要小的learning rate。也就是说我们需要变化的learning rate。目前有一个方法叫做:RMSProp。这个方法是将前一次的参数平方和当前的梯度平方用参数进行平衡然后开方作为当前参数。具体公式见下图:
但仅仅这样是不够的,这样并没有克服梯度下降过程中停到局部最优的问题。于是,有人想到了这样一个情节。在物理世界中,一个球从高处往下滚动,除了重力,还会依靠惯性。那么如果我们把惯性(Momentum)利用到梯度下降中,会如何呢?这里我们使用的惯性是前一次梯度下降的方向。也就是我们每次更新参数的时候,都会考虑当前的梯度下降方向和前一次梯度下降方向的综合作用,类似平行四边形法则,确定一个新的梯度方向。如下图所示:
红线是计算出来的梯度,蓝色的线是前一次的方向,绿色的线是我们需要移动的方向。因为计算公式是= -L(因为梯度的系数为负,所以红色的方向为其反向延长线。还有虽然用的是前一次的梯度方向,但是其实是前面所有的方向综合。因为每次的方向为= -L(,对于= -L(= ( -L()-L(。依次类推。但这种方法只是加以改进,并不能保证可以解决局部最优的问题。
part 3:Early stopping
由上图可以知道,随着迭代次数的不断增加,训练集上的错误率是不断降低的,但是到达某一值时,测试集上的错误不降反而开始上升。这就意味着我们不能再迭代了,需要停下来。因此我们需要确定什么时候停下来,这时候,我们一般会选取交叉验证集,但交叉验证集上错误率最小的时候我们选择停下来。
part 4:Regularization
正则化是我们通常使用的手段。这里我们采取两种范数进行正则化:
L1范数
这里 sgn的意思是取正负号。当为正时,取正号。为负,取负号。
L2范数
根据公式可以得到,会因为正则项不断变小。
part 5:Dropout
首先我们来定义一下什么是Dropout:
在训练集上,我们每次更新参数之前,都会随机丢掉p%的神经元节点(neuron)。这样一来,每次更新参数时候的网络结构都不同。相当于我们每次都采用的是新的网络结构。但是为了保证训练集和测试集的一致性,我们在测试集上也进行处理。我们不丢掉神经元节点(neuron),而是改变权重w:给权重w都乘以1-p%。如下:
Dropout我们可以这样形象化的理解:比如一个长跑运动员,为了锻炼自己的能力,每次训练的时候跑步都帮上很多沙袋负重跑,然后在真正比赛的时候,卸掉沙袋跑步,那么习惯了负重跑的他,取掉沙袋之后一定会跑得很快很轻松。而我们在训练时,通过Dropout,使得神经元减少,也就是网络不那么完善,但是在测试时,使用完善的网络结构,那么表现一定更好。其实Dropout也是一种ensemble.
Ensemble就是把data分配到不同的网络中,然后做计算,然后把分网络中的答案进行平均。
而Dropout也是同理。使用不同的min-batch用不同的网络结构去训练。如果有M个神经元,那么每个神经元有两种方案,选或者不选,则一共有个方案。并且参数是共享的,也就是说很多参数都在不同的min-batch和网络结构中训练。
但就如我们一开始提到的:为了保持训练集和测试集的一致,给权重乘以1-p%,那么什么情况下,可以真正保持一致呢?答案很显然,就是当**函数是线性函数的时候。
以下面一个例子进行说明:
一共有两个神经元,有四种方案。将所有结果加起来除以4,和在测试集上权重乘以1/2的结果是一样的。这里的**函数是线性的。