深度学习的Tips

☆樱花仙子☆ 提交于 2020-01-07 08:39:26

引言

本文主要讲解了在进行深度学习时一些实用的提示。是李宏毅 深度学习-Tips for Trainning DNN的笔记。

深度学习的方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dTgu1wjh-1578197312330)(_v_images/20200104124958206_27790.png)]

经过三步骤后得到一个神经网络,接下来判断在训练集上的表现如何?如果结果不好则回头看看三个步骤哪里出了问题;如果在训练集上的正确率很好,则拿训练集来试试,如果此时在测试集上的准确率不好,则说明是过拟合了;如果在训练集和测试集都得到很好的结果话,就说明这个网络是比较nice的。

不要错怪过拟合

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nHYlXKT8-1578197312331)(_v_images/20200104125852265_5960.png)]

在上图右56层的网络的错误率比20层的还要高,不能这样就说是过拟合导致的。从上图左可以看到在训练集上20层的结果本来就比56层的就好,说明这个网络没有训练好。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-evoqlLQb-1578197312331)(_v_images/20200104130402195_30141.png)]

训练集上的结果不好与测试集上的结果不好是不一样的,有不同的途径可以解决这些问题。比如Dropout可以用于解决由于参数多而样本少导致的过拟合问题。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QwVAwVsr-1578197312332)(_v_images/20200104130751686_21601.png)]

针对这些问题的解决方法可以有上面几种,比如如果在训练集上的结果不好,我们可以尝试换一个激活函数。

在手写数字识别中,激活函数就从Sigmoid换到了relu

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EC1PQmNg-1578197312332)(_v_images/20200104130958067_8143.png)]

激活函数是Sigmoid的情况下,当隐藏层的数量到了9,10层的时候,整个准确率就不忍直视了。见深度学习实例——Keras实现手写数字识别

造成上面这种情况有个原因是梯度消失问题(Vanishing Gradient Problem)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-smMSH1oU-1578197312332)(_v_images/20200104131235127_15758.png)]

当网络很深的时候,靠近输入层的前面几层中的参数(权重和偏差)对最后损失函数的影响很小,而在靠近输出层的几层中的参数影响很大。
所以会发现在靠近输入的地方参数更新很慢,而靠近输出的地方参数更新很快。在输入的地方参数几乎还是随机初始值的时候,输出的地方参数已经收敛了。

Cw=?ΔCΔw\frac{\partial C}{\partial w} = ?\frac{\Delta C}{\Delta w} 参数ww对总损失的影响程度可以理解为,当对参数ww进行微调时,比如改变Δw\Delta w对总损失的改变量ΔC\Delta C有多大。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Tbf8CSus-1578197312332)(_v_images/20200104132350968_15143.png)]
比如我们调整了靠近输入层参数,调整了很大的Δw\Delta w,这可以直接影响临近网络层输出的值,但是由于Sigmoid函数的特性,这个影响会逐层衰减的。

观察它的函数图像就知道了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iWmUGr5x-1578197312333)(_v_images/20200104132427208_30989.png)]

它会把负无穷大到正无穷大强行压缩到0和1之间,如果有很大的输入变化,通过该函数后得到的输出变化会很小。而每通过一层的Sigmoid函数,它的影响又一次衰减,最后对总损失的影响也就很小了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nJD7qbUq-1578197312333)(_v_images/20200104132657005_10680.png)]

那怎么解决这个问题呢,有人提出了修正线性单元函数(ReLU)。

ReLU

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JahCf5sp-1578197312334)(_v_images/20200104133009497_27984.png)]

zz是这个激活函数的输入,aa是这个激活函数的输出,如果输入大于零,输出就等于输入;如果输入小于零,输出就是0.

选择这个激活函数的理由有下:

  1. 计算很快
  2. 生物上的原因
  3. 等同于无穷多不同偏差Sigmoid函数叠加的结果
  4. 可以解决梯度消失问题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rhJi6EtL-1578197312334)(_v_images/20200104133344059_9137.png)]

这是一个用ReLU作激活函数的神经网络。根据它的性质,我们知道,它的输出无非就是两种,一是零,二是输入值。在输出值等于输入值的情况下,就是线性的(a=za=z)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sYJWOsej-1578197312334)(_v_images/20200104133600435_14146.png)]

输出是零的神经元其实是不会影响整个输出的,因此可以直接拿掉它们,得到下面这样的图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VXWKgjsd-1578197312334)(_v_images/20200104133645645_27103.png)]

整个看起来就是一个很瘦长的线性网络,并且在输入等于输出时,不会出现梯度消失问题。

但是有个问题是,当我们使用ReLU时,整个网络就变成了线性的了吗?
我们用深度学习就是不想要我们的函数是一个线性的,希望它是一个比较复杂的非线性的。

其实整个网络还是非线性的。怎么说呢,ReLU虽然在大于零的区间是线性的,在小于等于零的部分也是线性的,但是它整体不是线性的,因为不是一条直线。

的确对于单一的样本A,经过由ReLU激活函数所构成的神经网络,其过程确实可以等价是经过了一个线性变换M1,
但是对于样本B,在经过同样的网络时,由于每个神经元是否激活(0或者wx+b)与样本A经过时情形不同了(不同样本),
因此B所经历的线性变换M2并不等于M1。因此,ReLU构成的神经网络虽然对每个样本都是线性变换,
但是不同样本之间经历的线性变换M并不一样,所以整个样本空间在经过ReLU构成的网络时其实是经历了非线性变换的。

ReLU还有很多变种,比如一种是这样的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GUBkorpa-1578197312335)(_v_images/20200104135002468_5579.png)]

ReLU中,当输入小于零时,微分是0,这样就无法更新参数了。这个变种就是为了解决这个问题,当输入小于零时,
输出还是有一点点值,比如乘上0.010.01。但是为什么乘以0.010.01呢,不是其他的呢。因此又有人提出了参数化的ReLU

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jpu1u2C2-1578197312335)(_v_images/20200104135229826_25519.png)]

其中α\alpha也可以通过训练数据的梯度下降方法学习出来。

还有人提出了叫做Maxout的函数。

Maxout

ReLUMaxout的一种特例。它是可以自学习的激活函数。用个例子来解释它。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-udxAOGKm-1578197312336)(_v_images/20200104135520681_28219.png)]

假设有两个输入,经过权重和偏差得到输出。本来这些输出是需要传给激活函数来得到一个新值的,但是现在并不这么做。

把输出事先分组,每个组里面选出最大的输出值。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JqTuuA7Y-1578197312336)(_v_images/20200104135736263_30308.png)]

可以把上面红色框框起来的部分说成就是神经元,接下来7,17,1又乘上不同的权重,得到不同的输出,同样继续分组,选最大者

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8NDSpefj-1578197312336)(_v_images/20200104135925831_6449.png)]

实际上组内的数量也是可以超过2的。

我们上面为什么说ReLUMaxout的一种特例呢。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rV2F8eaJ-1578197312337)(_v_images/20200104140133646_9950.png)]

ReLU中是这样计算激活函数的输出值aa的,如果看xxaa的关系,可以如下图绿线所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2JKeU7uA-1578197312337)(_v_images/20200104140258453_25545.png)]

蓝线是xxzz的关系。

如果用Maxout,我们增加一组参数w=0,b=0w=0,b=0,得到输出z2z_2,然后选则z1,z2z_1,z_2比较大的当成输出aa:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WlvI4AUi-1578197312338)(_v_images/20200104140410996_25246.png)]

如果我们看z1z_1xx的关系,得到下图蓝线,看xxz2z_2的关系得到水平的红线:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OYsdGTUc-1578197312338)(_v_images/20200104140600711_20236.png)]

那再经过选取较大的操作后,实际的输出aaxx的关系如绿线所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YiiFMGTz-1578197312338)(_v_images/20200104140648202_29168.png)]

所以看以看出Maxout能做到ReLU做到的事情,并且ReLU做不到的事情,它也可以做到。

比如第二组参数中w,bw,b不取0,比如取其他一个非零值w,bw^\prime,b^\prime,就可以得到下面这个函数图形:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lj7lXwm2-1578197312339)(_v_images/20200104140950467_10222.png)]

而这个激活函数长什么样子,是由参数w,b,w,bw,b,w^\prime,b^\prime决定的,而这些参数是可学习的,因此说它是一个自学习的激活函数。

随着分组内的元素个数不同,它的图形也不同

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5l8SwyAI-1578197312339)(_v_images/20200104141216632_25697.png)]

接下来的问题是Maxout如何训练呢

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g2MhUgFJ-1578197312339)(_v_images/20200104141305710_9332.png)]

因为有个max,因此它不能微分啊。其实还是可以的,假设我们用红框框出来比较大的值。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-60RGKgaH-1578197312340)(_v_images/20200104141424092_4586.png)]

对应的输出aa就会成了线性的。我们可以拿掉在较大PK中被干掉的权重,就成了下图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6edWw0P3-1578197312341)(_v_images/20200104141556506_22184.png)]

假设给定上面这个一个比较细长的神经网络,既可以用反向传播算法进行训练。但问题是那些没被训练到的被拿掉的权重怎么办。其实因为我们有不同的样本,会得到不同的zz值,max值也不一样,也就是整个网络的结构也就不一样,最后每个权重和偏差实际上都会被训练到。

Adagrad 学习率

机器学习入门之梯度下降中,我们已经探讨过Adagrad学习率

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j0i2BaRo-1578197312341)(_v_images/20200104142322980_24188.png)]

知道参数ww的更新会考虑到过去所有的梯度值。但在深度学习中,情况会更加复杂。损失函数的图形可能是任何形状

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t7qNHiIv-1578197312341)(_v_images/20200104142627972_3205.png)]

甚至在同一个方向上(同一个参数ww),不同区域所需的学习率都不同。因此需要动态调整学习率的方法。
Adagrad有个进阶版,叫RMSProp

RMSProp

这个方法是这么做的

w1w0ησ0g0w^1 \leftarrow w^0 - \frac{\eta}{\sigma^0}g^0

把固定的学习率η\eta除上一个值σ\sigma,第一次的时候σ0=g0\sigma^0=g^0,就是第一次算出的梯度值,在算出新的梯度g1g^1后:

w2w1ησ1g1w^2 \leftarrow w^1 - \frac{\eta}{\sigma^1}g^1

新的σ\sigma值变成了这样计算:σ1=α(σ0)2+(1α)(g1)2\sigma^1=\sqrt{\alpha(\sigma^0)^2 + (1-\alpha)(g^1)^2}
α\alpha的值是可以自己调整的。

w3w2ησ2g2w^3 \leftarrow w^2 - \frac{\eta}{\sigma^2}g^2

这时σ2\sigma^2是这样计算的: σ2=α(σ1)2+(1α)(g2)2\sigma^2=\sqrt{\alpha(\sigma^1)^2 + (1-\alpha)(g^2)^2}

这和原来的Adagrad不一样,原来的Adagrad是计算g0,g1,g2g^0,g^1,g^2的平方和求均值再开根号。

巧妙之处在于RMSProp可以调整α\alpha值,如果设成小一点,就是说更相信新的梯度而无视旧的梯度。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pQgNAHpY-1578197312341)(_v_images/20200104143904750_6859.png)]

这解决了学习率的问题,那除了这个问题,在做深度学习的时候还可能会卡在局部最小值上。

寻找神经网络最佳参数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qInVcSrZ-1578197312342)(_v_images/20200104144358005_29830.png)]
可能卡在上面这几种情况,梯度就为0了,也就是参数不更新了。

其实在有很多参数的神经网络中,几乎没有这个问题,可以看成是很平滑的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qInVcSrZ-1578197312342)(_v_images/20200104144358005_29830.png)]

我们也可以探讨下如何解决局部最小值问题,我们知道在我们真实世界中,是有惯性的,当一个铁球从山顶滚下来的时候,哪怕到了一个凹点,也可能会因为惯性继续滚动,从而达到真正的最低点。

那么在做梯度下降的时候,如何加上这个惯性呢。

选一个初始值θ0\theta^0,用v0v^0记录前一个时间点移动的方向。

接下来计算在θ0\theta^0的梯度,现在要移动的方向并不是红色箭头的方向,而是v1=λv0ηΔL(θ0)v^1=\lambda v^0 - \eta \Delta L(\theta^0)

在这里插入图片描述

因为第一步时还没有惯性,因此还没影响,我们来看第二步

在这里插入图片描述

会因为惯性的影响而走的方向是θ2\theta^2,其中绿线虚线是上一步走的方向,也就是惯性方向。整个过程如下图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gyMWsozm-1578197312343)(_v_images/20200104151135954_7826.png)]

在第ii个时间点移动的量其实是过去所有算出来的梯度的总和。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ieeadnZs-1578197312343)(_v_images/20200104151318039_3035.png)]

我们看v2v^2v2v^2里面同时有θ0\theta^0θ1\theta^1算出来的梯度。这两个梯度的权重也不一样,越之前的梯度对现在方向的影响越小,但是还有一定的影响。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ErvHtqfj-1578197312344)(_v_images/20200104151608171_13201.png)]

在最后的时候,惯性建议我们继续向右走。这样有可能跳出局部最小点,而走到全局最小点。但是还是有可能跳不出去。

Adam

Adma可以看成是RMSProp+Momentum

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eb0uRE3M-1578197312344)(_v_images/20200104151910319_23729.png)]

在这个算法中,首先要初始惯性m0m_0,而v0v_0是RMSprop中的。

然后算出梯度gtg_t,根据它来算出新的mtm_t,就是现在要走的方向(考虑了过去走的方向加上梯度),
接下来算出vtv_t,它是过去的vt1v_t-1加上梯度的平方,
然后把它们都除以一个值,
最后更新θ\theta

Early Stopping

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ta82OdCu-1578197312344)(_v_images/20200104152605554_29623.png)]

如果在训练集中的表现很好,但是在测试集中的表示不好,要怎么做呢?上图介绍了三个方法,这小节先来学习第一个方法。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ap7peHlj-1578197312345)(_v_images/20200104164401357_7368.png)]

如果学习率调整的恰当的话,总误差在训练集上会随着不停的训练而变小。因为训练集合测试集不一样,有可能在训练集上总误差减小的时候,在测试集上反而增大。

如果你知道在测试集上总误差的变化,那么应该停在测试集上总误差最小的地方,而不是训练集上总误差最小的地方。

但我们不会真的直到测试集总误差的变化,一般用一个验证集(Validation set)来模拟测试集上的变化。

Regularization(正则化)

正则化重新定义损失函数

假设原来的损失函数是L(θ)L(\theta),正则化就是在原来的损失函数基础上加了一些东西(惩罚项)生成一个新的损失函数:

L(θ)=L(θ)+λ12θ2 L^\prime(\theta) = L(\theta) + \lambda \frac{1}{2}||\theta||_2

这个叫L2的正则化 θ2=(w1)2+(w2)2+||\theta||_2=(w_1)^2+(w_2)^2 + \cdots的作用是使得图像更加平滑,防止抖动。

梯度: Lw=Lw+λw\frac{\partial L^\prime}{\partial w}=\frac{\partial L}{\partial w} + \lambda w

现在更新参数会:

wt+1wtηLw=wtη(Lw+λwt)=(1ηλ)wtηLw w^{t+1} \rightarrow w^t - \eta \frac{\partial L^\prime}{\partial w} = w^t - \eta \left(\frac{\partial L}{\partial w} + \lambda w^t \right) \\ = (1-\eta \lambda)w^t -\eta \frac{\partial L}{\partial w}
(1ηλ)(1-\eta \lambda)中,假设ηλ=0.01\eta \lambda=0.01,会使得每次更新wtw^t都变小一点。

L1的正则化就是 θ1=w1+w2+||\theta||_1=|w_1| +|w_2| + \cdots 其中两个竖线是绝对值

L(θ)=L(θ)+λ12θ1 L^\prime(\theta) = L(\theta) + \lambda \frac{1}{2}||\theta||_1

梯度: Lw=Lw+λsgn(w)\frac{\partial L^\prime}{\partial w}=\frac{\partial L}{\partial w} + \lambda sgn(w)

对于sgn函数,如果ww是正数,它输出是11,;如果是负数,它输出是1-1,它的图像如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-15lXJ3HE-1578197312345)(_v_images/20200105111628419_21760.png)]

更新参数:

wt+1wtηLw=wtη(Lw+λsgn(wt))=wtηLwηλsgn(wt) w^{t+1} \rightarrow w^t - \eta \frac{\partial L^\prime}{\partial w} = w^t - \eta \left(\frac{\partial L}{\partial w} + \lambda sgn(w^t) \right) \\ = w^t -\eta \frac{\partial L}{\partial w} - \eta\lambda sgn(w^t)
如果wtw^t是正的,ηλsgn(wt)\eta\lambda sgn(w^t)就是正的,会减去一些;如果wtw^t是负的,ηλsgn(wt)\eta\lambda sgn(w^t)也是负的,就会加上一些正数,整个负的变小。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!