李宏毅机器学习系列-深度学习小贴士

李宏毅机器学习系列-深度学习小贴士

是过拟合的错么

我们在做深度学习的时候经常会遇到一些问题,比如我们发现测试集上的效果不好,于是我们马上认为是过拟合,其实不一定,过拟合是在训练集效果好,测试集不好的情况下才有的,而如果训练集都不好,测试集看到不会好啦,这样就可能是没训练好,结构不对,参数不对,激活函数没选好等等问题。
李宏毅机器学习系列-深度学习小贴士
比如下面的例子,一个是20层的网络,一个是56层的网络,在训练集上就不好,测试集上当然也好不到哪里去,这个不算过拟合吧,仅仅是训练每训练好,因为你想,20层的网络都可以做在训练集上训练好,56层比他更深,怎么可能训练起来比他差,只要前20层参数一样,后36层参数为0就可以啦,所以应该是训练的问题,比如梯度消失问题,后面会讲:
李宏毅机器学习系列-深度学习小贴士

深度学习的技巧

一般为了在训练集上有好的效果,我们会选择不同的激活函数和可调节的学习率,为了在测试集上也有好效果,避免过拟合,我们会采用提前停止,正则化和Dropout:
李宏毅机器学习系列-深度学习小贴士
我们先来看看手写识别的效果跟深度之间的关系,可以看到层数越多,效果越不好,直观上好像觉得是过拟合,其实不是,这个效果是在训练集上的,不是应该层数越多,模型越强啊,效果越好么,所以不应该是过拟合,还是训练的问题:
李宏毅机器学习系列-深度学习小贴士

梯度消失

那到底训练上出了什么问题呢,比如梯度消失问题,也就是说越靠近输出的地方梯度越大,越容易更新,学的越快,离输出越远的地方更新的越慢,几乎等于梯度0了:
李宏毅机器学习系列-深度学习小贴士
为什么会这样呢?这个是由于反向传播中激活函数的问题,根据上一篇的反向传播可以知道,梯度是跟激活函数相关的,如果是sigmoid的话,他会把输入压缩到0到1,而他的导数最大值是0.25也是小于1的,反向传播中要用到sigmoid本身和他的导数,因此乘的多了自然就越来越小啦:
李宏毅机器学习系列-深度学习小贴士

Relu

那怎么解决这个问题呢,有人提出来Relu这个激活函数,这个函数看上去很简单,计算也简单,虽然不可以微分,但是不可微分的点是取不到的,正真在做的时候可以给参数一个很小很小的偏差,不会是0了,而且导数要么是0要么是1,可以解决梯度消失问题:
李宏毅机器学习系列-深度学习小贴士
看下他的运行机制,如下图可以看到激活函数使得神经元变成线性单元了,而且输出就是0和1两个值,不会出现梯度越来越小:
李宏毅机器学习系列-深度学习小贴士
如果将输出为0的单元去掉,整个网络在这一个样本迭代就是一个瘦的线性模型了,那会不会整个模型就是闲线性模型了,当然不会啦,这个只是在一个样本迭代中的,不同的输入生成的是不同的线性模型,虽然每个样本是线性的模型,但是对于整体样本来说模型是非线性的:
李宏毅机器学习系列-深度学习小贴士
那问题由来了,输入如果小于0的话,输出是0,梯度变0,就不更新了,所以就提出了Leaky Relu,和Parametric Relu,让梯度不至于是0,参数当然要自己调啦:
李宏毅机器学习系列-深度学习小贴士

Maxout

如果要做同样的事,只能用Relu么,可以是别的样子的函数么,当然可以,于是有人提出了Maxout,Relu只是其中的一种情况,Maxout做的就是选择一定数量的输出,然后选里面最大的一个作为他们的输出,类似于最大池化:
李宏毅机器学习系列-深度学习小贴士
我们来看一下,最简单的Relu例子,其实他做的就是把蓝色的线z变成了绿色的线a:
李宏毅机器学习系列-深度学习小贴士
如果我们用两个神经单元z1,z2z_1,z_2z1​,z2​,其中一组参数为0,用max对两个神经元的输出取最大值,就可以表示Relu了,红色的线是参数为0的z2z_2z2​输出,蓝色的z1z_1z1​,而绿色的是求max后的,刚好是Relu的结果a,所以Relu是Maxout的一种特殊情况:
李宏毅机器学习系列-深度学习小贴士
Maxout的一般情况是怎么样的呢,看下图,一般情况就是一个凸函数,而且参数都是可以学习的:
李宏毅机器学习系列-深度学习小贴士
更一般的说,Maxout激活函数分段的线性凸函数,分多少断就看分组里有多少个元素(神经元),即maxout里的元素z1,z2z_1,z_2z1​,z2​,是两个,当然可以有多个:
李宏毅机器学习系列-深度学习小贴士
那这个要怎么训练呢,其中max函数只是选了一个神经元最大值的:
李宏毅机器学习系列-深度学习小贴士
其实可以看成是个线性单元:
李宏毅机器学习系列-深度学习小贴士
如果我们把最大的神经元留下,其他的函数,整个网络就变成一个瘦的线性的网络了,这个就是一般的反向传播训练了,当然你看你会问,被你删除的参数就不训练了么,当然不是,根据输入的不同,输出的神经元的最大值也会不同,网络的结构也不同,所以整体上参数都是会被训练到的,只是次数可能会不同的:
李宏毅机器学习系列-深度学习小贴士

可调节的学习率

我们来看下前面有讲过的AdaGrad,让不同参数有不同学习率,损失函数平滑的地方,学习率大一点,陡峭的地方学习率小一点,只需要考虑几个方向就行,方向里面变化率是一致的:
李宏毅机器学习系列-深度学习小贴士

RMSProp

但是很多时候,我们的损失函数不像这个凸函数的样子那么好,在同一个方向里面也可能有不同的变化率,看下面的复杂的损失函数,水平方向在某个区域比较平坦,所以学习率比较小,但是在另外的区域可能会出现陡峭的情况,学习率就会变大,所以AdaGrad就不适用了,需要更加能动态调整学习率的方法,于是提出了RMSProp:
李宏毅机器学习系列-深度学习小贴士
他是怎么做的呢,他给了一个参数α\alphaα,让他决定是取决于之前的梯度,还是现在的梯度:
李宏毅机器学习系列-深度学习小贴士

Momentum

除了学习率的问题呢,梯度下降法还有其他的问题,比如平原点,鞍点,或者局部最小点,其实局部最小点在深度学习中的问题不用太担心,有个理论说,因此参数很多,如果是在局部最小点,那每个参数都需要在在这个某个点是局部最小值,这样的几率很小,如果假设几率为ppp,有1000个参数的话,几率就是p1000p^{1000}p1000,很小很小,所以不用太担心,参数越多可出现的概率越低:
李宏毅机器学习系列-深度学习小贴士
上面的这些问题又个办法可以解决,假设局部最小点也不是很深,我们可以用惯性来解决,如果让一个小球有惯性,那他从高点滚下来的时候,或许可以越过上面所说的平原点,鞍点和局部最小点:
李宏毅机器学习系列-深度学习小贴士
我们来看看一般的梯度下降法是怎么走的,这个在前面的课程里讲过,就不多多说了:
李宏毅机器学习系列-深度学习小贴士
来看看带动量的,因为每次都会考虑前面的惯性,也就是动量,会有之前的速度影响,所以就像下面这样,梯度的建议是红色的虚线方向,但是之前的速度让我们还是走绿色的虚线方向,于是两个合起来就是蓝色的方向,是不是看起来比直接走红色的要缓一点啊:
李宏毅机器学习系列-深度学习小贴士
从数学式子来看,其实即是考虑了之前的梯度越现在的梯度也是有影响的,至于影响大小,可以调节参数λ\lambdaλ:
李宏毅机器学习系列-深度学习小贴士
更直观的来说就像下图,小球从上面下来,在不同的地方都会考虑梯度和现在的速度,然后产生新的速度,或者他在局部最小点的时候,惯性的速度比较大,就可能会冲出局部最小点:
李宏毅机器学习系列-深度学习小贴士

Adam

如果结合RMSProp和Momentum的特性,也就是Adam了,即可以很好的动态调节学习率,又带有惯性速度,下面就是具体算法,参考下:
李宏毅机器学习系列-深度学习小贴士

Early Stopping

接下来介绍在过拟合的一些解决方法,比如Early Stopping,他在做的就是在训练集训练好,测试集也可以是验证集开始不好的情况下直接停止,这个时候应该是比较好的结果,再下去测试结果可能就不好了,具体的做法可以看看keras里面的方法:
李宏毅机器学习系列-深度学习小贴士

Regularization

第二种方法叫正则化,这个我在其他文章里也有提过,有兴趣的可以看我的文章,就当是个补充看看。
简单来说,就是给损失函数加个惩罚项,带有一个惩罚系数λ\lambdaλ,给参数做个约束,一般我们都是用L2正则化,也就是范数的平方,如果是二维向量,可以理解为向量大小的平方:
李宏毅机器学习系列-深度学习小贴士
先来看看L2的正则化,我们对损失函数进行求导整理后会发现参数更新的前面多了一个乘积项,我们可以调节参数λ\lambdaλ来对这个进行控制,一般来说是小于1的,也就是进行了权重衰减:
李宏毅机器学习系列-深度学习小贴士
再看看L1的正则化,涉及到绝对值,就是一个形状开口向上的V函数,我们可以看到,参数的更新始终会减去一个式子,也就是说L1的更新参数的变化每次都会减去一个常数(ηλ\eta \lambdaηλ固定的情况下),而L2的是进行参数的缩小衰减,如果参数w出现很大的值,L2会很快的减小,而L1会慢慢减小,因为L2是直接缩放,L1是慢慢的减去一个数。如果参数w出现很小的值,L2会减小的慢,而L1会减小快,可能很快就为0了。因此L2一般不会出现较多的0参数,而L1可能会,还会有一些很大的值:
李宏毅机器学习系列-深度学习小贴士
权重衰减也类似于人脑的神经连接一样,你用的多的也就是训练的多的神经会被保留下来,少的就会消失:
李宏毅机器学习系列-深度学习小贴士

Dropout

这个的意思就是在训练的时候把一部分的神经元给丢弃,比如p%的神经元不训练:
李宏毅机器学习系列-深度学习小贴士
丢弃了之后,我们就可以得到一个瘦长的网络,参数就没有那么多了,从而可以避免过拟合,每次批处理我们都会重新采集随机p%个神经元丢弃:
李宏毅机器学习系列-深度学习小贴士
在测试的时候呢,我们不用丢弃,需要将所有参数乘以(1-p%):
李宏毅机器学习系列-深度学习小贴士
为什么要乘以(1-p%)呢,这个直觉的理解就好像火影里小李在训练的时候是帮着重物的,然后在战斗时会把重物给拿去:
李宏毅机器学习系列-深度学习小贴士
举个比较直观的例子,假设我们的p是50%,参数已经算出来了,那左边的z算出来肯定只有右边的一半,因此右边要要乘以(1-50%):
李宏毅机器学习系列-深度学习小贴士
更加正式的解释就是,Dropout是一种集合,他把很多的不同的神经网络结合在一起,有点想随机森林:
李宏毅机器学习系列-深度学习小贴士
在测试的时候就好像把数据给每一个神经网络,然后求他们输出的平均:
李宏毅机器学习系列-深度学习小贴士
因为在每个批次都会重新去采样p%个神经元不训练,所以你在每一个批次训练的神经网络其实可能都是不一样的,但是所有的参数是共享的,有些权重可能会被训练很多次,有些可能少一点,但是基本都会被训练到:
李宏毅机器学习系列-深度学习小贴士
然后我们发现,那么多不同结构的神经网络的输出的平均和整一个网络参数乘以(1-p%)的结果相近:
李宏毅机器学习系列-深度学习小贴士
来看一个直观的例子,左边是4种不同参数被丢弃概率是50%的平均,右边是整个的乘以(1-50%),发现他们是相等的,但是在非线性的情况下通常是不相等的,神奇的是虽然不相等,但是最后的结果还是可以的,所以会有种说法说,如果网络是线性的,那Dropout就会比较好,事实上也是,比如Relu+Dropout:
李宏毅机器学习系列-深度学习小贴士

总结

本篇主要介绍了深度学习的一些问题和解决的一些技巧,包括梯度消失问题,过拟合问题,思维导图:
李宏毅机器学习系列-深度学习小贴士
好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵,图片来自李宏毅课件,侵删。

上一篇:深度学习基础系列:VGG


下一篇:神经网络中的激活函数的比较