【深度学习】02-03-类神经网络训练不起来怎么办?(Batch 批量 和 Momentum 动量)-李宏毅老师21&22深度学习课程笔记

总结

SGD Vs BGD Vs MBGD ?
参考:梯度下降的三种方式的优缺点 - 666的文章 - 知乎

Small Batch Vs Large Batch ?
mini batch 有更高的准确率。L1&L2 交替使用可以逃离鞍点。
mini batch 有更高的泛化能力。mini batch 更容易进入Flat minima 而不是 sharp minima。
large batch 每个epoch的更新时间更短。

batchsize对模型的影响
参考:深度学习中的batch的大小对学习效果有何影响? - 龙鹏-笔名言有三的回答 - 知乎
参考:【AI不惑境】学习率和batchsize如何影响模型的性能? - 龙鹏-笔名言有三的文章 - 知乎

Gradient Descent + Momentum
每一次在移动参数的时候不只往 Gradient 的反方向移动参数,而是 Gradient 的反方向的基础上加上前一步移动的方向,两者加起来的结果去调整去到我们的参数。该方案模拟物理世界的惯性,可以使得update越过saddle point或坏的local minima。

回顾:Optimization with Batch

实际上在算微分的时候,并不是真的对所有 Data算出来的 L 作微分而是把所有的 Data 分成一个一个的 Batch(或者Mini Batch)。

在这里插入图片描述

每一个 Batch 的大小为B。我们每次在 Update 参数的时候,是拿B笔资料计算 Loss、计算 Gradient,然后更新擦参数;拿另外B笔资料,再算个 Loss、算个 Gradient,再 Update 参数,以此类推。所以不会拿所有的资料一起去算出Loss,我们只会拿一个 Batch 的资料,拿出来算 Loss。

所有的 Batch 看过一遍,叫做一个 Epoch,实际操作的过程中,在使用Batch 的时候,你会做一件事情叫做Shuffle(洗牌,混乱)

shuffle(中文意思:洗牌,混乱)。shuffle在机器学习与深度学习中代表的意思是,将训练模型的数据集进行打乱的操作。

Shuffle 有很多不同的做法,一个常见的做法就是在每个 Epoch 开始之前会重新分一次 Batch,从而每一个 Epoch 的 Batch 都不一样。

批量梯度下降(Batch Gradient Descent,BGD):每次采用所有数据下降。
随机梯度下降(Stochastic Gradient Descent,SGD):每次用一个样本来梯度下降。
小批量梯度下降(Mini-Batch Gradient Descent, MBGD):每次迭代使用一个以上又不是全部的样本。

MBGD 是集中了SGD和BGD的优点。使用多个样本相比SGD提高了梯度估计的精准度,小批量的估计。缺点是同SGD一样,每次梯度的方向不确定,可能需要很长时间接近最小值点,不会收敛通常在使用MBGD之前先将数据随机打乱,然后划分Mini-batch,所以MBGD有时也称SGD。
Mini-batch 大小的选择通常使用2的幂数,可以获得更少的运行时间。

参考:梯度下降的三种方式的优缺点 - 666的文章 - 知乎

Small Batch v.s. Large Batch - 每次Update耗时对比 LB不一定大于SB (考虑并行运算)& Noisy SB>LB

在这里插入图片描述

比较上图左右两边这两个Case,假设现在有20笔训练资料,考虑两个最极端的状况:

左边的 Case 没有用 Batch,这种状况叫做Full Batch。
右边的 Case 就是,Batch Size 等于1。

先来看左边的 Case。在左边 Case 中,因为没有用 Batch, Model 必须把20笔训练资料都看完才能够计算 Loss 和 Gradient。也就是必须要把所有20笔 Examples 都看完以后,参数才能够 Update 一次。假设开始的地方在蓝线上边的端点,把所有资料都看完以后Update 参数就从上面的端点移动到下边的端点。

在这里插入图片描述

如果 Batch Size 为1,代表只需要拿一笔资料出来算Loss就可以 Update 参数。所以每次 Update 参数的时候,只看一笔资料就可以。也就是看一笔资料就 Update 一次参数;再看一笔资料,再Update 一次参数。如果共有20笔资料,那在每一个 Epoch 里面,参数会 Update 20次。那因为现在只看一笔资料,就 Update 一次参数,所以用一笔资料算出来的 Loss在图中显然是比较 Noisy 的。也就是Update 的方向是曲曲折折的。

比较一下这两个方法会发现左边Full Batch的情况的蓄力的时间比较长,还有它技能冷却的时间比较长,你要把所有的资料都看过一遍才能够 Update 一次参数。

而右边的这个方法,当Batch Size =1的时候,蓄力的时间比较短,每看到一笔资料,就会更新一次参数。假设有20笔资料,所有资料看过一遍,就已经更新了20次的参数。

但是Full Batch的方法有一个优点,它更新参数的这一步是稳的;右边Batch Size =1这个方法的缺点是它更新参数的每一步是不稳的

看起来左边的方法跟右边的方法各有优劣。左边Full Batch是蓄力时间长,但是威力比较大;右边Batch Size =1技能冷却时间短,但是比较不准。

但是实际上考虑并行运算的话,full batch 并不一定比右边 batch size = 1 时间长。

Larger batch size does not require longer time to compute gradient

在这里插入图片描述

上图是一个真实的实验。事实上,比较大的 Batch Size,计算 Loss,再算 Gradient 所需要的时间,不一定比小的 Batch Size 要花的时间长。

上图是MNIST (Mixed National Institute of Standards and Technology database)是美国国家标准与技术研究院收集整理的大型手写数字数据库。机器要做的事情,就是给它一张图片,然后判断这张图片是0到9的哪一个数字,它要做数字的分类。

在上图的实验中,我们想要知道给机器一个 Batch,它要计算出 Gradient进而 Update 参数到底需要花多少的时间。

图中列出了 Batch Size 等于1、等于10、等于100、等于1000所需要耗费的时间。

你会发现 Batch Size 从1到1000需要耗费的时间几乎是一样的,你可能直觉上认为对于1000笔资料,计算 Loss,然后计算 Gradient花的时间是一笔资料的1000倍,但是实际上并不是这样的。

因为在实际做运算的时候, GPU可以做并行运算。因为可以做平行运算,这1000笔资料是平行处理的,所以1000笔资料所花的时间并不是一笔资料的1000倍。当然 GPU 平行运算的能力是有限的,当 Batch Size 非常非常巨大的时候,GPU 在跑完一个 Batch,并计算出 Gradient 所花费的时间还是会随 Batch Size 的增加而逐渐增长。

所以如果 Batch Size 是从1到1000,所需要的时间几乎是一样的;但是当你的 Batch Size 增加到 10000,乃至增加到60000的时候,就会发现 GPU 要算完一个 Batch,把这个 Batch 中的资料都拿出来算 Loss,再进而算 Gradient所要耗费的时间,确实随 Batch Size 的增加而逐渐增长。

当然,不同型号的GPU的并行计算的能力不同,通过GPU并行计算能力进步的过程中也可以体现时代的发展。

Small Batch v.s. Large Batch - 每轮epoch耗时对比 SB远大于LB (考虑并行运算)

Smaller batch requires longer time for one epoch

所以GPU 虽然有平行运算的能力,但它平行运算能力终究有个极限,所以你 Batch Size 真的很大的时候时间还是会增加的。

在这里插入图片描述
但是在有平行运算的能力的情况下,当你的 Batch Size 小的时候,你要跑完一个Epoch花的时间是比大的 Batch Size 还要多,为什么?

如果今天假设我们的训练资料只有60000笔,Batch Size =1。那要60000个 Update 才能跑完一个 Epoch;如果今天是 Batch Size =1000,要60个 Update 才能跑完一个 Epoch;假设Batch Size =1与 Batch Size =1000要计算算 Gradient 的时间根本差不多,那60000次 Update,跟60次 Update 比起来,它的时间的差距量就非常可观。

上图左边这个图是 Update 一次参数,拿一个 Batch 出来计算一个 Gradient,Update 一次参数所需要的时间;右边这个图是跑完一个完整的 Epoch需要花的时间。你会发现左边的图跟右边的图的趋势正好是相反的。

假设你 Batch Size =1,跑完一个 Epoch要 Update 60000次参数,它的时间是非常可观的。但是假设你的 Batch Size =1000,Update 60次参数就会跑完一个 Epoch。所以 Batch Size=1000的时候所需要的计算时间是比 Batch Size =1时要短、要快。

在没有考虑平行运算的时候,你觉得大的 Batch 比较慢;但实际上,在有考虑平行运算的时候,一个大的 Batch 计算一个epoch花的时间反而是比较少的。

如果要比较这个 Batch Size 大小的差异的话,直接用技能冷却时间的长短并不精确。看起来在技能时间上面,大的 Batch 并没有吃亏,甚至还占优。

所以事实上在上图有20笔资料的情况中,如果你用 GPU 的话,其实左右两图Update一次的时间可能是一样的。所以大的 Batch的技能冷却的时间,实际上并不长。那难道真的就时看起来大的 Batch 比较好?

Noisy Gradient Descent 有益于 Training 可得到更高准确率

实际上有一个比较神奇的事情: Noisy 的 Gradient反而可以帮助 Training。

在这里插入图片描述

如果拿不同的 Batch 来训练模型,你可能会得到上图中的结果,左边是 MNIST ,右边是 CIFAR-10 (都是影像辨识的问题)。

横轴代表的是 Batch Size,从左到右越来越大
纵轴代表的是正确率,越上面正确率越高,(正确率越高越好)

而如果你今天看 Validation Acc (验证集)(val 代表 validation,acc/loss代表训练集,val_acc/val_loss代表验证集。)上的结果,会发现Batch Size 越大,Validation Acc 上的结果越差。但这个不是由于Overfitting,因为如果你看你的 Training 的话,会发现 Batch Size 越大,Training 的结果也是越差的。

我们现在用的是同一个模型,照理说它们可以表示的 Function 就是一模一样的。但是神奇的事情是,大的 Batch Size往往在 Training 的时候会给你带来比较差的结果。

这个是 Optimization 的问题,当你用大的 Batch Size 的时候,你的 Optimization 可能会有问题,小的 Batch Size,Optimization 的结果反而是比较好的,为什么会这样?

为什么 Noisy Update 有更高准确率?- Small Batch L1&L2 逃离鞍点

“Noisy” update is better for training(“噪音”更新更适合训练)

为什么小Batch Size在 Training Set 上会得到比较好的结果;为什么Noisy 的 Update、Noisy 的 Gradient 会在 Training 的时候,会有比较好的结果?

在这里插入图片描述

假设在Full Batch的情况下,在 Update 参数的时候,你就是沿著一个 Loss Function 来 Update 参数,Update 到一个 驻点的时候就停下来了,此时Gradient =0。如果你不特别去看Hession,只用 Gradient Descent 的方法,你就没有办法再更新参数了。

但是如果在 Small Batch 的情况下。因为每次是挑一个 Batch 出来算它的 Loss。所以相当于每一次 Update 参数的时候,你用的 Loss Function 都是越有差异的。你选到第一个 Batch 的时候,你是用 L1 来算你的 Gradient;你选到第二个 Batch 的时候,你是用 L2 来算你的 Gradient。假设你用 L1 算 Gradient 的时候,发现 Gradient 是零,无法在进行更新。但 L2 它的 Function 跟 L1 又不一样,L2 就不一定会卡在驻点,所以 L1 卡住的话就换下一个 Batch ,用L2 再算 Gradient。

所以相比较在Full Batch的情况下,Small Batch不会因为驻点的存在就早早的结束训练,你还是有办法 Training 你的 Model,还是有办法让你的 Loss 变小。所以今天这种 Noisy 的 Update 的方式结果反而对 Training,其实是有帮助的。

为什么 Noisy Update 有更高泛化能力?- Large Batch易Sharp Minima & Small Batch易 Flat Minima(待研究有争论)

“Noisy” update is better for generalization
还有另外一个更神奇的事情,其实小的 Batch 也对 Testing 有帮助。

假如在训练中你有一些方法,调大的 Batch 的 Learning Rate,然后有办法把大的 Batch跟小的 Batch 训练得一样好。结果你会发现小的 Batch,居然在 Testing 的时候会是比较好的。

以下这个实验结果是引用自,On Large-Batch Training For Deep Learning,Generalization Gap And Sharp Minimahttps://arxiv.org/abs/1609.04836,这篇 Paper 的实验结果。

在这里插入图片描述

那这篇 Paper 中作者 Train 了六个 Network,里面有 CNN、有 Fully Connected Network,做在不同的 Cover 上来代表这个实验具有泛用性。在很多不同的 Case 都观察到一样的结果。

它小的Batch有256笔,大的 Batch 就是Data Set 乘 0.1,Data Set 有60000笔,那你大的 Batch里面有6000笔资料。

然后作者想办法将大的 Batch 跟小的 Batch都 Train 到差不多的 Training Accuracy(训练精度)上(如上图左边的红框)。但是就算在 Training 的时候两者的结果差不多,在Testing 的时候大的 Batch 居然比小的 Batch 差。

Training 的时候两者表现都很好,Testing 的时候大的 Batch 表现的不好,准确率低,这代表了Overfitting(过拟合)。产生这个现象的原因在这篇文章里给出来了。

在这里插入图片描述

假如上图中的两条曲线代表了Training Loss和Test Loss。在Training Loss中可能有很多的Local Minima。在这些局部最小的点上,Loss的值都很低,有的可能都趋近于0。在这些局部最小的点中,有好的Minima跟坏的 Minima 之分。

如果一个 Local Minima 它在一个曲线峡谷里面(图中的sharp minima),它是坏的 Minima;如果Local Minima它在一个较为平缓的曲线段上(上图中的Flat minima),它就是好的 Minima。为什么会有这种差异?

假设现在 Training 跟 Testing 中间有一个 Mismatch(不匹配),Training 的 Loss 与Testing 的 Loss所对应的Function不一样。有可能是本来你 Training 跟 Testing 的 Distribution(分布)就不一样。

也有可能因为 Training 跟 Testing都是从 Sample 的 Data 算出来的,也许训练集和测试集从样本数据算出来的不一样,所以它们的Loss当然不一样。

假设Testing的就是把 Training Loss的Function往右平移一点(上图中的虚曲线)。这时候会发现对左边这个在一个盆地裡面的Minima(Flat minima)来说,它在 Training 和Testing 上面的结果,不会差太多(Flat minima上的红虚线),只差了一点点;但是右边这个在峡谷中的 Minima就差的比较多了(Sharp minima上的红虚线)

在这里插入图片描述
Sharp minima在Training Set 上算出来的 Loss 很低,但是Training与Testing 之间有差别,所以在测试的时候,这个误差曲面的移动让Sharp minima算出来的 Loss就变得很大。

很多人相信这个大的 Batch Size会让我们倾向于走到峡谷里面,而小的 Batch Size倾向于让我们走到盆地裡面

直觉上的想法是这样的,小的 Batch有很多的 Loss,它每次 Update 的方向都不太一样。如果今天这个峡谷非常地窄,它可能在某次Update的过程中就跳出去了,因为每次 Update 的方向都不太一样,它的 Update 的方向也就随机性。所以很小的峡谷没有办法困住小的 Batch。

如果峡谷很小,它可能Update一次就跳出去,如果有一个非常宽的盆地它才会停下来;那对于大的 Batch Size,它就是顺著规定的Update的方向移动,它就很有可能走到一个比较小的峡谷裡面

但这只是一个解释,学术界有争论,这个其实还是一个尚待研究的问题。

Small Batch Vs Large Batch

在这里插入图片描述

上图比较了一下Small Batch与Large Batch。

在有平行运算的情况下Small Batch跟Large Batch运算的时间并没有太大的差距(除非你的Large Batch非常大才会显示出差距来)。

但是完成一个 Epoch 所需要的时间里,Small Batch比较长,Large Batch反而比较快,所以从一个 Epoch需要的时间来看,Large Batch占优。

Small Batch的Update的方向比较Noisy,Large Batch的Update 的方向比较稳定。但是 Noisy 的 Update 的方向反而会在 Optimization 的时候会更有优势,而且在 Testing 的时候也会占优。所以Large Batch跟Small Batch各有优缺点。

所以 Batch Size也属于需要人工调整的 Hyperparameter

是否可以兼具SB&LB两者优点 - 可以,已有很多研究

那是否可以兼具两者的优点?
在这里插入图片描述

这是可能的,有很多学者都在探讨这个问题。上述的Paper中都有赘述。

Momentum - 另一个逃离saddle point&local minima的技术

Momentum也是除了调整Batch大小以外另一种可以解决驻点问题的方法,运作方法如下:

Small Gradient

在这里插入图片描述

假设 Error Surface是在物理的世界中的真正的斜坡,而参数是一个球,你把球从斜坡上滚下来。如果发生 Gradient Descent(梯度下降),它走到 Local Minima 或 Saddle Point 就停住了

但是在物理的世界中一个球如果从高处滚下来,**如果有惯性,球在遇到平面时它还是会继续往右走。**如果它的动量够大的话,甚至它走到一个 Local Minima还是会继续往右走,甚至翻过这个小坡然后继续往右走。

所以今天在物理的世界中一个球从高处滚下来的时候,它并不一定会被 Saddle Point或 Local Minima 卡住。人们就想到有没有办法运用同样的概念到 Gradient Descent 中,这个就是Momentum 这个技术。

Vanilla Gradient Descent

在这里插入图片描述

先看一下原来的 Gradient Descent 长得什么样子。上图为Vanilla(一般的;香草) 的 Gradient Descent,就是一般的Gradient Descent 。

一般的 Gradient Descent就是说,我们有一个初始的参数叫做θ⁰ ,计算一下Gradient,之后向 Gradient 的反方向去 Update 参数。

更新到新的参数以后,再计算一次 Gradient,再往 Gradient 的反方向 Update 一次参数…… Process 就一直这样进行下去。

Gradient Descent + Momentum

但是加上 Momentum 以后,每一次在移动参数的时候不只往Gradient 的反方向移动参数,而是 Gradient 的反方向的基础上加上前一步移动的方向,两者加起来的结果去调整去到我们的参数。

在这里插入图片描述

具体来说就是先找一个初始参数θ⁰,假设上一步参数更新的量m⁰=0。之后再θ⁰处计算Gradient的方向g⁰。

然后就要决定更新下一个参数如何移动,就是Gradient的方向加前一步的方向。现在是刚开始,所以前一步是 0,也就是 Update 的方向跟原来的 Gradient Descent 是一样的:
在这里插入图片描述

但从第二步开始,加上 Momentum 就不太一样了。从第二步开始计算g1,之后Update 的方向不是g1的反方向,而是根据上一次 Update 方向,也就是 m1 减掉 g1当做我们新的 Update 的方向.记为m2。

在这里插入图片描述

在这里插入图片描述

仔细看上图。g1 也就是Gradient 告诉我们要往红色箭头的反方向走(也就是虚线箭头的方向),但是我们不是只根据 Gradient 的反方向来调整我们的参数,我们也会看前一次 Update 的方向。

  • 前一次往m1蓝色及蓝色虚线这个方向走。
  • 根据Gradient 要往红色虚线方向走。
  • 把两者相加起来,走两者的折中。也就是往蓝色的m2这一个方向走,所以我们就移动 m2,走到 θ2 这个地方。

接下来反覆进行同样的过程,在θ2计算出 Gradient,但我们不只根据 Gradient 反方向走,我们看前一步怎么走。前一步走这个蓝色虚线(m2)的方向。我们把蓝色虚线(m2)加红色虚线(g2)当做我们下一步要移动的方向。

在这里插入图片描述

如果每一步的移动都用 m 来表示,那这个 m 可以写成之前所有算出来的Gradient 的 Weighted Sum(加权和),也就是下面这个式子(递推公式)

在这里插入图片描述

以此类推就会发现,Momentum是Gradient 的反方向加上前一次移动的方向;但另一个意思是Momentum 所包含的Update 的方向不是只考虑现在的 Gradient,而是考虑过去所有 Gradient 的总合。

下面有个更简单的例子:

在这里插入图片描述

从上图这个曲线的最上方(黑球位置)开始 Update 参数,Gradient 的方向告诉我们应该往右 Update 参数。刚开始没有前一次 Update 的方向,所以就完全按照 Gradient 的方向向右移动参数。

在这里插入图片描述

移动到第二个黑球之后,此时的Gradient 变得很小,告诉我们往右移动,但只能移动一点点,但是由于前一步是往右移动的,把前一步的方向用蓝色虚线来表示。把 Gradient 告诉我们要走的方向跟前一步移动的方向加起来,得到往右走的方向。再往右走,走到一个 Local Minima,照理说走到 Local Minima梯度就消失了,就无法向前走了,走到 Saddle Point 也一样,没有 Gradient 的方向已经无法向前走了

在这里插入图片描述

但是如果有 Momentum 的话,由于 Momentum 不是只看 Gradient,还有前一步的方向,前一步的方向告诉我们向右走,那就继续向右走。甚至你走到最右边(第四个黑球)这个地方,此时Gradient 告诉你应该要往左走了,但是前一步的影响力比 Gradient 要大,还是继续往右走,甚至翻过一个小丘,搞不好就可以走到更好 Local Minima,这个就是 Momentum 有可能带来的好处。

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值