CS231n笔记七:训练神经网络3(优化方法)

一、更好的优化optimization

1、随机梯度下降算法(Stochastic Gradient Descent, SGD)的问题
  1. 损失函数对一个参数很敏感(在该维度变化很快),对其它参数很不敏感
    以两个参数为例,那么loss函数的图像可能看起来像一个taco一样,其中一个参数的变化只会导致loss的横向移动,实际上loss的值没有太大改变;而另一个参数会引起loss的纵向变化。那么我们在计算梯度时,梯度的方向可能就是直着向下的,而不是想着最优值的方向,那么以合适的学习率在梯度方向移动也会导致“用力过猛”,最终呈现出zigzag的优化路线。
    在这里插入图片描述

对于随机梯度下降算法,这个问题在高维空间中会更加普遍
在这里插入图片描述
也就是说学习步长并没有很平均的分配到两个参数上,对于一个参数它变化得过快,而另一个参数却没什么变化。

  1. 局部极小值(local minima)或鞍点(saddle points)
    (1)啥是鞍点:鞍点(Saddle point),在微分方程中,沿着某一方向是稳定的,另一条方向是不稳定的奇点,叫做鞍点。在泛函中,既不是极大值点也不是极小值点的临界点,叫做鞍点。在矩阵中,一个数在所在行中是最大值,在所在列中是最小值,则被称为鞍点。在物理上要广泛一些,指在一个方向是极大值,另一个方向是极小值的点。
    如在下面这个函数中,(0,0)就是一个鞍点:
    在这里插入图片描述
    在这里插入图片描述
    (2)SGD在局部极小值和鞍点处遇到的问题:不管是局部极小值还是鞍点,这两种点处的梯度值都为0,那么当参数优化到这些点时就会被卡住!在高维空间中,鞍点比局部极小值更常见。

  2. 梯度来自于minibatch,因而可能有噪声
    由于计算梯度的代价比较高,所以通常只会在一个minibatch上来算梯度,从而估算真实梯度。正是因为这种估计,所以算出来的梯度可能会有噪声,导致优化路径曲里拐弯,很耗时间。
    在这里插入图片描述


2、SGD的优化:SGD + Momentum(带动量的SGD)

1、新增一个速度变量velocity(初始为0),每次参数不再在梯度的方向上更新,而是在速度的方向上更新。其中rho(即ρ)为摩擦系数,通常为一个较大的值。
速度velocity的计算为 vx = rho * vx + dx
在这里插入图片描述
2、这样增加速度变量的好处就是:
(1)可以想象一个球滚下山,它的速度越滚越大,那么即使我在局部极小值点或者鞍点处没有梯度,它仍然有很大的速度可以继续滚下去,不会轻易被卡住。
(2)有了速度之后,zigzag的梯度可能在计算速度时就被抵消掉了,这样实际上可以减小在敏感参数上的速度分量,反而增加在不敏感参数上的速度,就不会出现zigzag的现象了。
(3)同时由于加上了动量,噪声会被抵消掉一些,从而使优化过程更加平滑的接近到最优值位置。
在这里插入图片描述
3、我们还有一种动量优化,叫做Nesterov Momentum
(1)在传统的动量优化中,我们首先计算该点的梯度,然后用梯度去修正当前的速度,得到二者的复合值作为实际前件的步长方向。
(2)在Nesterov中,我们首先按照现有的速度前进一下,然后计算前进后的点的梯度,再用这个梯度做矫正进一步走到最终正确的位置。
在这里插入图片描述
用公式来表示Nesterov Momentum就是这样的:
在这里插入图片描述


3、AdaGrad和RMSProp

(1)AdaGrad(通常不用):

  • 累加梯度的平方,然后把步长除以平方。对于poor conditioning的情况,如果loss对某个参数不敏感,也就是在这个方向上的梯度比较小,但是由于我把步长除以了梯度的平方和,那么步长会相应的比较大,这样最终在这个方向上移动的距离也不会很小;相反的,如果loss对这个参数敏感,那么虽然梯度比较大,但步长会比较小,这样移动的距离也不会很大,相当于能把更新方向掰正一点。
  • AdaGrad的一个问题:累加的梯度平方和会越来越大,这样我算出来的步长就会越来越小越来越小。对于凸函数来说,这个特征还挺好的,这使得我们在接近最优值时找的很慢,也就是很细致,最终达到收敛。但是对于非凸函数来说,这个就不太好了,因为你可能会在局部最优点附近移动得越来越慢,最终卡在局部最优值的位置。
    在这里插入图片描述

(2)RMSProp:
为了解决上述的问题,我们提出了AdaGrad的变体。在RMSProp中,我们还是会计算梯度平方的和,但是在累加时会让梯度平方按照一定比例衰减,防止累加和无限制的增大。实际上这也有点像一种动量(第二动量),区别在于我们加的是梯度平方,instead of单纯的梯度。
在这里插入图片描述

(3)对比
从下面这个图可以看出,动量版SGD会跑得很快,可能会overshoot一点,然后再回来;但RMSProp则是一直在仔细调整前进的方向,它不会overshoot,基本可以直接找的最优值。
在这里插入图片描述


4、Adam(对第一动量和第二动量的结合)

1、Adam版本一:相当于把动量SGD和RMSProp结合在一起了。
在这里插入图片描述

一个问题:由于我们人为的把第二动量初始化为0了,那么再第一次移动时,最后一个式子中除以第二动量也是一个非常接近0的数(因为beta2一般很大,所以dx*dx在第一步时不会有什么贡献),那么这就导致我们在第一次移动时会以一个很大的步长移动,那我的初始化工作就全毁了。

2、首选:Adam版本二(无偏估计)
对第一动量和第二动量增加一个无偏估计,让它们除以(1 - beta ** t),这样可以防止一开始的动量特别小导致步长很大。在 t 很小时,(1 - beta ** t)会很接近于0,这样一除之后两个unbias值都会比较大,可以防止最后一行算出来步长很大的情况出现。
在这里插入图片描述


5、学习率衰减

对于以上优化算法,我们都是把学习率当作一个不变的超参数来看待的。但实际上学习率随着学习过程而衰减也可能是一个很好的办法,它可以在loss遇到瓶颈时帮助突破这个瓶颈。
在这里插入图片描述
在这里插入图片描述

注意:一开始的时候不要用学习率衰减,要先试一下不衰减时loss是啥样的,然后有针对性的决定在哪个地方开始衰减学习率。


6、一阶优化和二阶优化
  1. 一阶优化
    用一阶偏导算出来梯度,做一个一阶泰勒逼近,相当于一个线性逼近。这要求我们的步长不能太长,因为实际上我们用梯度算出来的方向只是一个切线方向,沿这个方向走得太多可能会导致我们偏离实际方向。
    在这里插入图片描述

  2. 二阶优化
    同时利用一阶偏导和二阶偏导的信息,对loss函数做一个二阶泰勒逼近,也就是用一个二阶函数来逼近loss。这样的逼近通常更加准确,这样我们可以直接跳到二阶函数的最小值处,也不会偏离真实方向多远。也就是说在传统二阶优化方法(牛顿法)中是没有学习率的。
    在这里插入图片描述

海森矩阵???
拟牛顿法???


7、模型集成

实际上我们不希望在训练集上有很低的loss,而是在验证集和测试集上。模型集成的想法是我们初始化很多不同的模型,然后训练每个模型,来看在验证集和测试集上哪个效果更好。
上面的方法需要对每个模型都训一遍,如果我们在训练过程中收集模型的快照snap,用这个快照作为备选模型,会减少训练的次数从而提高效率。一种方法是在训练过程中疯狂调整学习率,一会大一会小,这样模型的参数就可能会收敛到目标函数的不同区域里,给它们记录下来,这样就可以通过一次训练得到多个不同的模型,最后看哪个更好即可。


二、正则化

中心思想:在训练时引入某种随机性或噪声,而在测试时把这种随机性平均化掉
引:前面提到的模型集成告诉我们如何从众多模型中选出一个最好的,但我们更关注如何提高一个特定模型的性能。我们可以在模型里加一些正则化项,这样可以有效防止过拟合,从而在测试集上得到更好的正确率。

1、Dropout(非常常见!!!!)
  1. 基本思想
    在每次正向传播的过程中,会随机选择一些神经元置0(即把这一个神经元的激活函数的输出值置为0),每次正向传播中被置0的神经元都是不同的。
    如下图,左边是正常的全连接网络,右边是一次传播中被置0之后的网络。置0后的网络中相当于只有一部分神经元起效,且每次被置0的神经元都不同,也就是每轮迭代时有效的神经元都是随机选取的。
    在这里插入图片描述

  2. 具体细节
    实际上dropout相当于把网络做了一个改动,之前我只需要把x和W做点乘作为输出即可,现在我有多了一个random mask,就是一个随机的掩码z,用来决定哪些神经元会被置为0。就像下面的式子一样:
    在这里插入图片描述

但这样的问题是会引入随机性,也就是我们的输出output是不确定的,它取决于mask的取值。这在训练的时候还好,但在测试的时候是不可接受的,因为我们不希望自己网络的预测结果是一个随机的值(即上一次是这个值,下一次又变了)。所以需要对测试结果做平均化"average out",来消除测试结果的随机性。
一般的想法是取”积分“,也就是对所有z对应的预测结果值做加权求和。但这个代价太大了,因为z有巨多巨多个,不可取。
一种好的办法是
考虑单个神经元,在没有随机掩码z时,它的输出应该是w1x + w2y;而在有随机掩码的训练过程中,假设将一个神经元置0的概率为0.5,那么我们对总共4中掩码z做加权求和,得到输出应为1/2(w1x + w2y),这个是训练时的平均输出结果。我们会发现这个结果和之前假设没有掩码时的结果有一个很明显的倍数关系,而倍数就是将一个神经元置0的概率0.5。因此在测试时,我们可以按照无掩码的情况正常计算输出值,最后在输出值前乘一个将神经元置0的概率p,即可得到平均化的输出结果。(注意是给每个神经元的输出值都乘p!!!)
在这里插入图片描述

对以上方法的一个小trick
通常在测试过程中我们很注重效率,所有不希望额外乘个p。那么我们可以选择inverted dropout,也就是不在测试时乘p,而在计算训练时神经元的输出结果时除以一个p,因为训练通常在GPU上进行,它很快。
在这里插入图片描述

批量归一化也是一种正则化!!!


2、数据增强 Data Augmentation

对输入图像进行:水平翻转、裁剪、色彩抖动、旋转、拉伸…
如在ResNet中,训练时sample random crops/scales,测试时average a fixed set of crops。


三、迁移学习

引:如果想训练一个很复杂的网络,但没有一个足够大的数据集,那么迁移学习可以用来解决这个问题。

1、迁移学习思想

例如我想做分类的任务,分出来十种狗的品种,但狗的数据集很小,不足以训练整个网络,那么我可以先用一个大数据集,如imageNet,来训练我的整个神经网络。在整个网络的参数都训练完之后,我只需要修改最后一个全连接层的权值矩阵,比如原来训imageNet时它是1000*4096的,而训狗是需要10 * 4096的矩阵,那么我就只要换一个矩阵并且求出来这个矩阵里面的参数即可。对于前面的所有矩阵,我都沿用imageNet训出来的参数即可。
如果你的可用数据集更大一些,那么不光可以训最后一个全连接层,还可以适当的finetune一下之前的权值参数。通常finetuning时的学习率要设小一点,一般设为之前学习率的十分之一。
在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值