文章目录
General Guidance
具体的改进问题判断与解决方法步骤如下(适用于大多数网络设计):
首先检测网络在training data上的loss,要确保model在training data能学起来。
当发现training data的loss很大时,可能是model bias、optimization;如果在training data上loss很小时,这时在testing data上loss很大可能是overfitting或mismatch,如果testing data上loss也很小,呢么大概率可以芜湖起飞!
model bias
这里的model bias,指的就是你的model设计太过simple,这里的simple我们可以理解为太简单,无法适应实际情况,弹性不够。
Solution:
这时,能让loss变小的function,并不在你的model所构建出的假设空间中,所以不论怎么训练参数都无法达到好的效果。
所以我们应该重新设计model,让它变得更复杂更有弹性,比如,增加更多的参数、使用更deep的model等等
优化问题
’
当training data上的loss过大时,不一定是model bias,也有可能是Optimization做的不好。很多时候很容易卡在局部最优解,gradient descent这个方法学习不到function set中比较好的一组参数。
判断Optimization问题还是model bias方法:
如果层数与参数增加了,效果反而不如简单的model时,大概率就是出现了Optimization问题。 反之,可能是model设计问题。
所以,我们可以先跑一些比较浅的网络,甚至一些不是deep learning的传统方法,之后与深度学习进行对比,发现问题所在。
Optimization问题解决方法:待续
过拟合
当训练集的loss小,测试集的loss大,可能是遇到了overfitting
造成Overfitting的原因是,model过于灵活,自由学习产生了训练集上的结果好,但完全不符合实际结果的model
在其他没有训练资料作为限制的地方,因为他的弹性很大,所以得到在测试资料上不一定好的model
Solution:
-
增加训练数据
收集更多的资料,这样就算model较为复杂也可以相对增加model的正确性。
同时,我们还可以做Data augmentation,比如把图像左右翻转,放大缩小等等来创造新的资料。 -
减小模型flexible
给模型一些限制,减少模型参数、让model公用参数、更少的训练Feature、早停法、Regularization(正则化)、Dropout
减少模型参数或者让model共用参数:
FC的弹性大于CNN,CNN是有一定限制的架构,他针对image的特性来限制模型的弹性
但是,我们也不能过于限制模型,过于限制又会导致模型出现model bias问题
我们可以发现随着model 的复杂性不断提升,testing loss会先下降后增加。这代表到了某个程度,overfitting的状况就会出现,所以我们需要选择一个最适合的model。
但是,我们不能用testing的结果反过来推断我们的模型,这是不讲武德的,训练集和测试集是互相独立的。
所以,我们使用一个Validation set作为验证集,来调整我们的模型
N-fold Cross Validation的做法
我们将Training set分成N等分,其中一份作为Val,其他的用作训练,重复N次后,取平均值作为结果.
你根据在val set挑选model,所以在public testing set上的分数就可以反映private teating set的分数。
mismatch
这也算是一种overfitting,但是它的原因和overfitting不一样,它无法通过收集更多的资料来解决。
这是因为它的训练资料和测试资料是不一样的,这样就算训练资料再增加也没有帮助了。
局部最小值 (local minima) 與鞍點 (saddle point)
Optimization失败的原因
现在我们要讲的是Optimization的部分,所以我们要讲的东西基本上跟Overfitting没有什麼太大的关联,我们只讨论Optimization的时候,怎麼把gradient descent做得更好,那為什麼Optimization会失败呢?
你常常在做Optimization的时候,你会发现,**随著你的参数不断的update,你的training的loss不会再下降,**但是你对这个loss仍然不满意,就像我刚才说的,你可以把deep的network,跟linear的model,或比较shallow network 比较,发现说它没有做得更好,所以你觉得deepnetwork,没有发挥它完整的力量,所以Optimization显然是有问题的
但有时候你会甚至发现,一开始你的model就train不起来,一开始你不管怎麼update你的参数,你的loss通通都掉不下去,那这个时候到底发生了什麼事情呢?
过去常见的一个猜想,是因為我们现在走到了一个地方,这个地方参数对loss的微分為零, 当你的参数对loss微分為零的时候,gradient descent就没有办法再update参数了,这个时候training就停下来了,loss当然就不会再下降了。
讲到gradient為零的时候,大家通常脑海中最先浮现的,可能就是local minima,所以常有人说做deep learning,用gradient descent会卡在local minima,然后所以gradient descent不work,所以deep learning不work。
但是如果有一天你要写,跟deep learning相关paper的时候,你千万不要讲卡在local minima这种事情,别人会觉得你非常没有水準,為什麼
因為不是只有local minima的gradient是零,还有其他可能会让gradient是零,比如说 saddle point,所谓的saddle point,其实就是gradient是零,但是不是local minima,也不是local maxima的地方,像在右边这个例子裡面 红色的这个点,它在左右这个方向是比较高的,前后这个方向是比较低的,它就像是一个马鞍的形状,所以叫做saddle point,那中文就翻成鞍点
像saddle point这种地方,它也是gradient為零,但它不是local minima,那像这种gradient為零的点,统称為critical point,所以你可以说你的loss,没有办法再下降,也许是因為卡在了critical point(驻点), 但你不能说是卡在local minima,因為saddle point也是微分為零的点
但是今天如果你发现你的gradient,真的很靠近零,卡在了某个critical point,我们有没有办法知道,到底是local minima,还是saddle point?其实是有办法的
為什麼我们想要知道到底是卡在local minima,还是卡在saddle point呢
- 因為如果是卡在local minima,那可能就没有路可以走了,因為四周都比较高,你现在所在的位置已经是最低的点,loss最低的点了,往四周走 loss都会比较高,你会不知道怎麼走到其他的地方去
- 但saddle point就比较没有这个问题,如果你今天是**卡在saddle point的话,saddle point旁边还是有路可以走的,**还是有路可以让你的loss更低的,你只要逃离saddle point,你就有可能让你的loss更低
所以鉴别今天我们走到,critical point的时候,到底是local minima,还是saddle point,是一个值得去探讨的问题,那怎麼知道今天一个critical point,到底是属於local minima,还是saddle point呢?
Warning of Math:
那怎麼知道说一个点,到底是local minima,还是saddle point呢?
你要知道我们loss function的形状,可是我们怎麼知道,loss function的形状呢,network本身很复杂,用复杂network算出来的loss function,显然也很复杂,我们怎麼知道loss function,长什麼样子,虽然我们没有办法完整知道,整个loss function的样子
Tayler Series Approximation:
但是如果给定某一组参数,比如说蓝色的这个θ′,在θ′附近的loss function,是有办法被写出来的,它写出来就像是这个样子
这个H叫做Hessian,它是一个矩阵,这个第三项是,再(θ−θ′)TH(θ−θ′),所以第三项会再补足,再加上gradient以后,与真正的L(θ)之间的差距.H裡面放的是L的二次微分,它第i个row,第j个column的值,就是把θ的第i个component,对L作微分,再把θ的第j个component,对L作微分,做两次微分以后的结果 就是这个Hij
L(θ),这个loss function,这个error surface在θ′附近,可以写成这个样子,这个式子跟两个东西有关係,跟gradient有关係,跟hessian有关係,gradient就是一次微分,hessian就是裡面有二次微分的项目
Hession
那如果我们今天走到了一个critical point,意味著gradient為零,也就是绿色的这一项完全都不见了
** g是一个zero vector,绿色的这一项完全都不见了,只剩下红色的这一项,**所以当在critical point的时候,这个loss function,它可以被近似為L(θ′),加上红色的这一项
我们可以根据红色的这一项来判断,在θ′附近的error surface,到底长什麼样子
知道error surface长什麼样子,我就可以判断
θ′它是一个local minima,是一个local maxima,还是一个saddle point
我们可以靠这一项来了解,这个error surface的地貌,大概长什麼样子,知道它地貌长什麼样子,我们就可以知道说,现在是在什麼样的状态,这个是Hessian
那我们就来看一下怎麼根据Hessian,怎麼根据红色的这一项,来判断θ’附近的地貌
我们现在為了等一下符号方便起见,我们把(θ−θ′)用v这个向量来表示
- 如果今天对任何可能的v,vTHv都大於零,也就是说 现在θ不管代任何值,v可以是任何的v,也就是θ可以是任何值,不管θ代任何值,红色框框裡面通通都大於零,那意味著说 L(θ)>L(θ′)。L(θ)不管代多少 只要在θ′附近,L(θ)都大於L(θ′),代表L(θ′)是附近的一个最低点,所以它是local minima
- 如果今天反过来说,对所有的v而言,vTHv都小於零,也就是红色框框裡面永远都小於零,也就是说θ不管代什麼值,红色框框裡面都小於零,意味著说L(θ)<L(θ′),代表L(θ′)是附近最高的一个点,所以它是local maxima
- 第三个可能是假设,**vTHv,有时候大於零 有时候小於零,**你代不同的v进去 代不同的θ进去,红色这个框框裡面有时候大於零,有时候小於零,意味著说在θ’附近,有时候L(θ)>L(θ’) 有时候L(θ)<L(θ’),在L(θ’)附近,有些地方高 有些地方低,这意味著什麼,这意味著这是一个saddle point
但是你这边是说我们要代所有的v,去看vTHv是大於零,还是小於零.我们怎麼有可能把所有的v,都拿来试试看呢,所以有一个更简便的方法,去确认说这一个条件或这一个条件,会不会发生.
这个就直接告诉你结论,线性代数理论上是有教过这件事情的,如果今天对所有的v而言,vTHv都大於零,那这种矩阵叫做positive definite 正定矩阵,positive definite的矩阵,它所有的eigen value特征值都是正的
所以如果你今天算出一个hessian,你不需要把它跟所有的v都乘看看,你只要去直接看这个H的eigen value,如果你发现
- 所有eigen value都是正的,那就代表说这个条件成立,就vTHv,会大於零,也就代表说是一个local minima。所以你从hessian metric可以看出,它是不是local minima,你只要算出hessian metric算完以后,看它的eigen value发现都是正的,它就是local minima。
- 那反过来说也是一样,如果今天在这个状况,对所有的v而言,vTHv小於零,那H是negative definite,那就代表所有eigen value都是负的,就保证他是local maxima
- 那如果eigen value有正有负,那就代表是saddle point,
那假设在这裡你没有听得很懂的话,你就可以记得结论,你只要算出一个东西,这个东西的名字叫做hessian,它是一个矩阵,这个矩阵如果它所有的eigen value,都是正的,那就代表我们现在在local minima,如果它有正有负,就代表在saddle point。
例子
那如果刚才讲的,你觉得你没有听得很懂的话,我们这边举一个例子
我们有一个史上最废的training set,这个data set说,我们只有一笔data,这笔data是x,是1的时候,它的level是1 所以输入1进去,你希望最终的输出跟1越接近越好
而这个史上最废的training,它的error surface,也是有办法直接画出来的,因為反正只有两个参数 w₁ w₂,连bias都没有,假设没有bias,只有w₁跟w₂两个参数,这个network只有两个参数 w₁跟w₂,那我们可以穷举所有w₁跟w₂的数值,算出所有w₁ w₂数值所代来的loss,然后就画出error surface 长这个样
四个角落loss是高的,好 那这个图上你可以看出来说,有一些critical point,这个黑点点的地方(0,0),原点的地方是critical point,然后事实上,右上三个黑点也是一排critical point,左下三个点也是一排critical point
如果你更进一步要分析,他们是saddle point,还是local minima的话,那圆心这个地方,**原点这个地方 它是saddle point,**為什麼它是saddle point呢
你往左上这个方向走 loss会变大,往右下这个方向走 loss会变大,往左下这个方向走 loss会变小,往右下这个方向走 loss会变小,它是一个saddle point
而这两群critical point,它们都是local minima,所以这个山沟裡面,有一排local minima,这一排山沟里面有一排local minima,然后在原点的地方,有一个saddle point,这个是我们把error surface,暴力所有的参数,得到的loss function以后,得到的loss的值以后,画出error surface,可以得到这样的结论
现在假设如果不暴力所有可能的loss,如果要直接算说一个点,是local minima,还是saddle point的话 怎麼算呢
这个hessian告诉我们,它是local minima,还是saddle point呢,那你就要看这个矩阵的eigen value,算一下发现,这个矩阵有两个eigen value,2跟-2 eigen value有正有负,代表saddle point
如果今天你卡的地方是saddle point,也许你就不用那麼害怕了,因為如果你今天你发现,你停下来的时候,是因為saddle point 停下来了,那其实就有机会可以放心了
因為H它不只可以帮助我们判断,现在是不是在一个saddle point,它还指出了我们参数,可以update的方向,就之前我们参数update的时候,都是看gradient 看g,但是我们走到某个地方以后,发现**g变成0了 不能再看g了,g不见了 gradient没有了,但如果是一个saddle point的话,还可以再看H,**怎麼再看H呢,H怎麼告诉我们,怎麼update参数呢
那今天如果λ小於零,eigen value小於零的话,那λ‖u‖²就会小於零,因為‖u‖²一定是正的,所以eigen value是负的,那这一整项就会是负的,也就是u的transpose乘上H乘上u,它是负的,也就是红色这个框裡是负的
所以这意思是说假设θ−θ′=μ,那这一项(θ−θ′)TH(θ−θ′)就是负的,也就是L(θ)<L(θ′)
也就是说假设θ−θ′=μ,也就是,你在θ’的位置加上u,沿著u的方向做update得到θ,你就可以让loss变小
因為根据这个式子,你只要θ减θ’等於u,loss就会变小,所以你今天只要让θ等於θ’加u,你就可以让loss变小,你只要沿著u,也就是eigen vector的方向,去更新你的参数 去改变你的参数,你就可以让loss变小了
所以虽然在critical point没有gradient,如果我们今天是在一个saddle point,你也不一定要惊慌,你只要找出负的eigen value,再找出它对应的eigen vector,用这个eigen vector去加θ’,就可以找到一个新的点,这个点的loss比原来还要低
Saddle Point v.s. Local Minima
到底saddle point跟local minima,谁比较常见呢
一个故事:略
总之这个从三维的空间来看,是没有路可以走的东西,在高维的空间中是有路可以走的,error surface会不会也一样呢
所以你在一维的空间中,一维的一个参数的error surface,你会觉得好像到处都是local minima,但是会不会在二维空间来看,它就只是一个saddle point呢,常常会有人画类似这样的图,告诉你说Deep Learning的训练,是非常的复杂的,如果我们移动某两个参数,error surface的变化非常的复杂,是这个样子的,那显然它有非常多的local minima,我的这边现在有一个local minima,但是会不会这个local minima,只是在二维的空间中,看起来是一个local minima,在更高维的空间中,它看起来就是saddle point,在二维的空间中,我们没有路可以走,那会不会在更高的维度上,因為更高的维度,我们没办法visualize它,我们没办法真的拿出来看,会不会在更高维的空间中,其实有路可以走的,那如果维度越高,是不是可以走的路就越多了呢,所以 今天我们在训练,一个network的时候,我们的参数往往动輒百万千万以上,所以我们的error surface,其实是在一个非常高的维度中,对不对,我们参数有多少,就代表我们的error surface的,维度有多少,参数是一千万 就代表error surface,它的维度是一千万,竟然维度这麼高,会不会其实,根本就有非常多的路可以走呢,那既然有非常多的路可以走,会不会其实local minima,根本就很少呢,
而经验上,如果你自己做一些实验的话,也支持这个假说
这边是训练某一个network的结果,每一个点代表,训练那个network训练完之后,把它的Hessian拿出来进行计算,所以这边的每一个点,都代表一个network,就我们训练某一个network,然后把它训练训练,训练到gradient很小,卡在critical point,把那组参数出来分析,看看它比较像是saddle point,还是比较像是local minima
- 纵轴代表training的时候的loss,就是我们今天卡住了,那个loss没办法再下降了,那个loss是多少,那很多时候,你的loss在还很高的时候,训练就不动了 就卡在critical point,那很多时候loss可以降得很低,才卡在critical point,这是纵轴的部分
- 横轴的部分是minimum ratio,minimum ratio是eigen value的数目分之正的eigen value的数目, **又如果所有的eigen value都是正的,代表我们今天的critical point,是local minima,如果有正有负代表saddle point,**那在实作上你会发现说,你几乎找不到完全所有eigen value都是正的critical point,你看这边这个例子裡面,这个minimum ratio代表eigen value的数目分之正的eigen value的数目,最大也不过0.5到0.6间而已,代表说只有一半的eigen value是正的,还有一半的eigen value是负的,
所以今天虽然在这个图上,越往右代表我们的critical point越像local minima,**但是它们都没有真的,变成local minima,**就算是在最极端的状况,我们仍然有一半的case,我们的eigen value是负的,这一半的case eigen value是正的,代表说在所有的维度裡面有一半的路,这一半的路 如果要让loss上升,还有一半的路可以让loss下降。
所以从经验上看起来,其实local minima并没有那麼常见,多数的时候,你觉得你train到一个地方,你gradient真的很小,然后所以你的参数不再update了,往往是因為你卡在了一个saddle point。
Batch and Momentum
Review: Optimization with Batch
我们实际上在算微分的时候,并不是真的对所有 Data 算出来的 L 作微分
每一个 Batch 的大小呢,就是大 B 一笔的资料,我们每次在 **Update 参数的时候,我们是拿大 B 一笔资料出来,算个 Loss,算个 Gradient,Update 参数,**拿另外B一笔资料,再算个 Loss,再算个 Gradient,再 Update 参数,以此类推,所以我们不会拿所有的资料一起去算出 Loss,我们只会拿一个 Batch 的资料,拿出来算 Loss
所有的 Batch 看过一遍,叫做一个 Epoch,那事实上啊,你今天在做这些 Batch 的时候,你会做一件事情叫做 Shuffle
Shuffle 有很多不同的做法,但一个常见的做法就是,在每一个 Epoch 开始之前,会分一次 Batch,然后呢,每一个 Epoch 的 Batch 都不一样,就是第一个 Epoch,我们分这样子的 Batch,第二个 Epoch,会重新再分一次 Batch,所以哪些资料在同一个 Batch 裡面,每一个 Epoch 都不一样的这件事情,叫做 Shuffle。
实际上考虑并行运算的话,左边这个并不一定时间比较长
Larger batch size does not require longer time to compute gradient:
这边是真正的实验结果了,事实上,比较大的 Batch Size,你要算 Loss,再进而算 Gradient,所需要的时间,不一定比小的 Batch Size 要花的时间长
因為在实际上做运算的时候,我们有 GPU,可以做并行运算,是因為你可以做平行运算的关係,这1000笔资料是平行处理的,所以1000笔资料所花的时间,并不是一笔资料的1000倍,当然 GPU 平行运算的能力还是有它的极限,当你的 Batch Size 真的非常非常巨大的时候,GPU 在跑完一个 Batch,计算出 Gradient 所花费的时间,还是会随著 Batch Size 的增加,而逐渐增长
Smaller batch requires longer time for one epoch:
但是因為有平行运算的能力,因此实际上,当你的 Batch Size 小的时候,你要跑完一个 Epoch,花的时间是比大的 Batch Size 还要多的
在没有考虑平行运算的时候,你觉得大的 Batch 比较慢,但实际上,在有考虑平行运算的时候,一个 Epoch 大的 Batch 花的时间反而是比较少的
你不是说大的 Batch,这个 Update 比较稳定,小的 Batch,它的 Gradient 的方向比较 Noisy 吗,那这样看起来,大的 Batch 好像应该比较好哦,小的 Batch 应该比较差,因為现在大的 Batch 的劣势已经,因為平行运算的时间被拿掉了,它好像只剩下优势而已.
那神奇的地方是 **Noisy 的 Gradient,反而可以帮助 Training,**这个也是跟直觉正好相反的
如果你今天拿不同的 Batch 来训练你的模型,你可能会得到这样子的结果,左边是坐在 MNIST 上,右边是坐在 CIFAR-10 上,不管是 MNIST 还是 CIFAR-10,都是影像辨识的问题
而如果你今天看 Validation Acc 上的结果,会发现说,Batch Size 越大,Validation Acc 上的结果越差,但这个不是 Overfitting,因為如果你看你的 Training 的话,会发现说 Batch Size 越大,Training 的结果也是越差的,而我们现在用的是同一个模型哦,照理说,它们可以表示的 Function 就是一模一样的
但是神奇的事情是,大的 Batch Size,往往在 Training 的时候,会给你带来比较差的结果
所以这个是什麼样的问题,同样的 Model,所以这个不是 Model Bias 的问题,这**个是 Optimization 的问题,代表当你用大的 Batch Size 的时候,你的 Optimization 可能会有问题,**小的 Batch Size,Optimization 的结果反而是比较好的,好 為什麼会这样子呢
“Noisy” update is better for training
為什麼小的 Batch Size,在 Training Set 上会得到比较好的结果,為什麼 Noisy 的 Update,Noisy 的 Gradient 会在 Training 的时候,给我们比较好的结果呢?一个可能的解释是这样子的
假设你是 Full Batch,那你今天在 Update 你的参数的时候,你就是沿著一个 Loss Function 来 Update 参数,今天 Update 参数的时候走到一个 Local Minima,走到一个 Saddle Point,显然就停下来了,Gradient 是零,如果你不特别去看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。
你还是有办法 Training 你的 Model,还是有办法让你的 Loss 变小,所以今天这种 Noisy 的 Update 的方式,结果反而对 Training,其实是有帮助的。
“Noisy” update is better for generalization
那这边还有另外一个更神奇的事情,其实小的 Batch 也对 Testing 有帮助。
假设我们今天在 Training 的时候,都不管是大的 Batch 还小的 Batch,都 Training 到一样好,刚才的 Case是Training 的时候就已经 Training 不好了
假设你有一些方法,你努力的调大的 Batch 的 Learning Rate,然后想办法把大的 Batch,跟小的 Batch Training 得一样好,结果你会发现小的 Batch,居然在 Testing 的时候会是比较好的,那以下这个实验结果是引用自,On Large-Batch Training For Deep Learning,Generalization Gap And Sharp Minimahttps://arxiv.org/abs/1609.04836,这篇 Paper 的实验结果
他想办法,在大的 Batch 跟小的 Batch,都 Train 到差不多的 Training 的 Accuracy,所以刚才我们看到的结果是,Batch Size 大的时候,Training Accuracy 就已经差掉了,这边不是想办法 Train 到大的 Batch 的时候,Training Accuracy 跟小的 Batch,其实是差不多的
但是就算是在 Training 的时候结果差不多,Testing 的时候你还是看到了,小的 Batch 居然比大的 Batch 差,Training 的时候都很好,Testing 的时候小的 Batch 差,代表 Over Fitting,这个才是 Over Fitting 对不对,好 那為什麼会有这样子的现象呢?在这篇文章裡面也给出了一个解释,
假设这个是我们的 Training Loss,那在这个 Training Loss 上面呢,可能有很多个 Local Minima,有不只一个 Local Minima,那这些 Local Minima 它们的 Loss 都很低,它们 Loss 可能都趋近於 0,但是这个 Local Minima,还是有好 Minima 跟坏 Minima 之分
如果一个 Local Minima 它在一个峡谷裡面,它是坏的 Minima,然后它在一个平原上,它是好的 Minima,為什麼会有这样的差异呢
- 因為**假设现在 Training 跟 Testing 中间,有一个 Mismatch,**Training 的 Loss 跟 Testing 的 Loss,它们那个 Function 不一样,有可能是本来你 Training 跟 Testing 的 Distribution就不一样。
- 那也有可能是因為 Training 跟 Testing,你都是从 Sample 的 Data 算出来的,也许 Training 跟 Testing,Sample 到的 Data 不一样,那所以它们算出来的 Loss,当然是有一点差距。
那我们就假设说这个 Training 跟 Testing,它的差距就是把 Training 的 Loss,这个 Function 往右平移一点,这时候你会发现,对左边这个在一个盆地裡面的 Minima 来说,它的在 Training 跟 Testing 上面的结果,不会差太多,只差了一点点,但是对右边这个在峡谷裡面的 Minima 来说,一差就可以天差地远
它在这个 Training Set 上,算出来的 Loss 很低,但是因為 Training 跟 Testing 之间的不一样,所以 Testing 的时候,这个 Error Surface 一变,它算出来的 Loss 就变得很大,而很多人相信这个大的 Batch Size,会让我们倾向於走到峡谷裡面,而小的 Batch Size,倾向於让我们走到盆地裡面
那他直觉上的想法是这样,就是小的 Batch,它有很多的 Loss,它每次 Update 的方向都不太一样,所以如果今天这个峡谷非常地窄,它可能一个不小心就跳出去了,因為每次 Update 的方向都不太一样,它的 Update 的方向也就随机性,所以一个很小的峡谷,没有办法困住小的 Batch
如果峡谷很小,它可能动一下就跳出去,之后停下来如果有一个非常宽的盆地,它才会停下来,那对於大的 Batch Size,反正它就是顺著规定 Update,然后它就很有可能,走到一个比较小的峡谷裡面
但这只是一个解释,那也不是每个人都相信这个解释,那这个其实还是一个尚待研究的问题
那这边就是比较了一下,大的 Batch 跟小的 Batch
左边这个是第一个 Column 是小的 Batch,第二个 Column 是大的 Batch
在有平行运算的情况下,小的 Batch 跟大的 Batch,其实运算的时间并没有太大的差距,除非你的大的 Batch 那个大是真的非常大,才会显示出差距来。但是一个 Epoch 需要的时间,小的 Batch 比较长,大的 Batch 反而是比较快的,所以从一个 Epoch 需要的时间来看,大的 Batch 其实是佔到优势的。
而小的 Batch,你会 Update 的方向比较 Noisy,大的 Batch Update 的方向比较稳定,但是 Noisy 的 Update 的方向,反而在 Optimization 的时候会佔到优势,而且在 Testing 的时候也会佔到优势,所以大的 Batch 跟小的 Batch,它们各自有它们擅长的地方
所以 Batch Size,变成另外一个 你需要去调整的 Hyperparameter。
Momentum
Momentum,这也是另外一个,有可能可以对抗 Saddle Point,或 Local Minima 的技术,Momentum 的运作是这个样子的
它的概念,你可以想像成在物理的世界裡面,假设 Error Surface 就是真正的斜坡,而我们的参数是一个球,你把球从斜坡上滚下来,如果今天是 Gradient Descent,它走到 Local Minima 就停住了,走到 Saddle Point 就停住了
但是在物理的世界裡,一个球如果从高处滚下来,从高处滚下来就算滚到 Saddle Point,如果有惯性,它从左边滚下来,因為惯性的关係它还是会继续往右走,甚至它走到一个 Local Minima,如果今天它的动量够大的话,它还是会继续往右走,甚至翻过这个小坡然后继续往右走
那所以今天在物理的世界裡面,一个球从高处滚下来的时候,它并不会被 Saddle Point,或 Local Minima卡住,不一定会被 Saddle Point,或 Local Minima 卡住,我们有没有办法运用这样子的概念,到 Gradient Descent 裡面呢,那这个就是我们等一下要讲的,Momentum 这个技术
Vanilla Gradient Descent:
那我们先很快的复习一下,原来的 Gradient Descent 长得是什麼样子,这个是 Vanilla 的 Gradient Descent,Vanilla 的意思就是一般的的意思,它直译是香草的,但就其实是一般的,一般的 Gradient Descent 长什麼样子呢
Gradient Descent + Momentum:
加上 Momentum 以后,每一次我们在移动我们的参数的时候,我们不是只往 Gradient Descent,我们不是只往 Gradient 的反方向来移动参数,我们是 Gradient 的反方向,加上前一步移动的方向,两者加起来的结果,去调整去到我们的参数,
那我们就看下面这个图:
g1 告诉我们,Gradient 告诉我们要往红色反方向这边走,但是我们不是只听 Gradient 的话,加上 Momentum 以后,我们不是只根据 Gradient 的反方向,来调整我们的参数,我们也会看前一次 Update 的方向
- 如果前一次说要往m1蓝色及蓝色虚线这个方向走
- Gradient 说要往红色反方向这个方向走
- 把两者相加起来,走两者的折中,也就是往蓝色m2这一个方向走,所以我们就移动了 m2,走到 θ2 这个地方
接下来就反覆进行同样的过程,在这个位置我们计算出 Gradient,但我们不是只根据 Gradient 反方向走,我们看前一步怎麼走,前一步走这个方向,走这个蓝色虚线的方向,我们把蓝色的虚线加红色的虚线,前一步指示的方向跟 Gradient 指示的方向,当做我们下一步要移动的方向
每一步的移动,我们都用 m 来表示,那这个 m 其实可以写成之前所有算出来的,Gradient 的 Weighted Sum.从右边的这个式子,其实就可以轻易的看出来
以此类推,所以你会发现说,现在这个加上 Momentum 以后,一个解读是 Momentum 是,Gradient 的负反方向加上前一次移动的方向,那但另外一个解读方式是,所谓的 Momentum,当加上 Momentum 的时候,我们 Update 的方向,不是只考虑现在的 Gradient,而是考虑过去所有 Gradient 的总合.
有一个更简单的例子,希望帮助你了解 Momentum
Adaptive Learning Rate
critical point其实不一定是,你在训练一个Network的时候,会遇到的最大的障碍,今天要告诉大家的是一个叫做Adaptive Learning Rate的技术,我们要给每一个参数不同的learning rate
Training stuck ≠ Small Gradient
People believe training stuck because the parameters are around a critical point …
為什麼我说这个critical point不一定是我们训练过程中,最大的阻碍呢?
loss不再下降的时候,大家就会猜说,那是不是走到了critical point,因為gradient等於零的关係,所以我们没有办法再更新参数,但是真的是这样吗
当我们说 走到critical point的时候,意味著gradient非常的小,但是你有确认过,当你的loss不再下降的时候,gradient真的很小吗?
gradient是一个向量,下面是gradient的norm,即gradient这个向量的长度,随著参数更新的时候的变化,你会发现说虽然loss不再下降,但是这个gradient的norm,gradient的大小并没有真的变得很小
这样子的结果其实也不难猜想,也许你遇到的是这样子的状况
这个是我们的error surface,然后你现在的gradient,在error surface山谷的两个谷壁间,不断的来回的震荡
这个时候你的loss不会再下降,所以你会觉得它真的卡到了critical point,卡到了saddle point,卡到了local minima吗?不是的,它的gradient仍然很大,只是loss不见得再减小了
所以你要注意,当你今天训练一个network,train到后来发现,loss不再下降的时候,你不要随便说,我卡在local minima,我卡在saddle point,有时候根本两个都不是,你只是单纯的loss没有办法再下降
Training can be difficult even without critical points:
如果今天critical point不是问题的话,為什麼我们的training会卡住呢,我这边举一个非常简单的例子,我这边有一个,非常简单的error surface
我们只有两个参数,这两个参数值不一样的时候,Loss的值不一样,我们就画出了一个error surface,这个error surface的最低点在黄色X这个地方,事实上,这个error surface是convex的形状(可以理解为凸的或者凹的,convex optimization常翻译为“凸优化”)
如果你不知道convex是什麼,没有关係,总之它是一个,它的这个等高线是椭圆形的,只是它在横轴的地方,它的gradient非常的小,它的坡度的变化非常的小,非常的平滑,所以这个椭圆的长轴非常的长,短轴相对之下比较短,在纵轴的地方gradient的变化很大,error surface的坡度非常的陡峭
那现在我们要从黑点这个地方,这个地方当作初始的点,然后来做gradient descend
你可能觉得说,这个convex的error surface,做gradient descend,有什麼难的吗?不就是一路滑下来,然后可能再走过去吗,应该是非常容易。你实际上自己试一下,你会发现说,就连这种convex的error surface,形状这麼简单的error surface,你用gradient descend,都不见得能把它做好,举例来说这个是我实际上,自己试了一下的结果
我learning rate设10⁻²的时候,我的这个参数在峡谷的两端,我的参数在山壁的两端不断的震盪,我的loss掉不下去,但是gradient其实仍然是很大的
那你可能说,就是因為你learning rate设太大了阿,learning rate决定了我们update参数的时候步伐有多大,learning rate显然步伐太大,你没有办法慢慢地滑到山谷裡面只要把learning rate设小一点,不就可以解决这个问题了吗?
事实不然,因為我试著去,调整了这个learning rate,就会发现你光是要train这种convex的optimization的问题,你就觉得很痛苦,我就调这个learning rate,从10⁻²,一直调到10⁻⁷,调到10⁻⁷以后,终於不再震盪了
终於从这个地方滑滑滑,滑到山谷底终於左转,但是你发现说,这个训练永远走不到终点,因為我的learning rate已经太小了,竖直往上这一段这个很斜的地方,因為这个坡度很陡,gradient的值很大,所以还能够前进一点,左拐以后这个地方坡度已经非常的平滑了,这麼小的learning rate,根本没有办法再让我们的训练前进
事实上在左拐这个地方,看到这边一大堆黑点,这边有十万个点, 所以显然就算是一个convex的error surface,你用gradient descend也很难train
所以我们需要更好的gradient descend的版本,在**之前我们的gradient descend裡面,所有的参数都是设同样的learning rate,这显然是不够的,learning rate它应该要為,每一个参数客製化**,所以接下来我们就是要讲,客製化的learning rate,怎麼做到这件事情
Different parameters needs different learning rate
那我们要怎麼客製化learning rate呢,我们不同的参数到底,需要什麼样的learning rate呢
从刚才的例子裡面,其实我们可以看到一个大原则,如果在某一个方向上,我们的gradient的值很小,非常的平坦,那我们会希望learning rate调大一点,如果在某一个方向上非常的陡峭,坡度很大,那我们其实期待,learning rate可以设得小一点
那这个learning rate要如何自动的,根据这个gradient的大小做调整呢。我们要改一下,gradient descend原来的式子,我们只放某一个参数update的式子,我们之前在讲gradient descend,我们往往是讲,所有参数update的式子,那这边為了等一下简化这个问题,我们只看一个参数,但是你完全可以把这个方法,推广到所有参数的状况
我们只看一个参数,这个参数叫做θit,这个θit在第t个iteration的值,减掉在第t个iteration这个参数i算出来的gradient git
g
i
t
=
∂
L
∂
θ
i
∣
θ
=
θ
t
{g{i}{^{t}}}=\frac{\partial{L}}{\partial{θ_i}}|{θ=θ^t}
git=∂θi∂L∣θ=θt 这个
g
i
t
{g{_i}{^{t}}}
git代表在第t个iteration,也就是θ等於θᵗ的时候,参数θᵢ对loss的微分,我们把这个θᵢᵗ减掉learning rate,乘上gᵢᵗ会更新learning rate到θᵢᵗ⁺¹,这是我们原来的gradient descend,我们的learning rate是固定的
这个σᵢᵗ你发现它有一个上标t,有一个下标i,这代表说这个σ这个参数,首先它是depend on i的,不同的参数我们要给它不同的σ,同时它也是iteration dependent的,不同的iteration我们也会有不同的σ
Root mean square:
那这个σ有什麼样的方式,可以把它计算出来呢,一个常见的类型是算,gradient的Root Mean Square
Adagrad
那这一招被用在一个叫做Adagrad的方法裡面,為什麼这一招可以做到我们刚才讲的,坡度比较大的时候,learning rate就减小,坡度比较小的时候,learning rate就放大呢?
RMSProp
刚才那个版本,就算是同一个参数,它需要的learning rate,也会随著时间而改变, 我们刚才的假设,好像是同一个参数,它的gradient的大小,就会固定是差不多的值,但事实上并不一定是这个样子的
举例来说我们来看,这个新月形的error surface
如果我们考虑横轴的话,考虑左右横的水平线的方向的话,你会发现说,在绿色箭头这个地方坡度比较陡峭,所以我们需要比较小的learning rate,
但是走到了中间这一段,到了红色箭头的时候呢,坡度又变得平滑了起来,平滑了起来就需要比较大的learning rate,所以就算是同一个参数同一个方向,我们也期待说,learning rate是可以动态的调整的,于是就有了一个新的招数,这个招数叫做RMS Prop
RMS Prop这个方法有点传奇,它传奇的地方在於它找不到论文,非常多年前应该是将近十年前,Hinton在Coursera上,开过deep learning的课程,那个时候他在他的课程裡面,讲了RMS Prop这个方法,然后这个方法没有论文,所以你要cite的话,你要cite那个影片的连结,这是个传奇的方法叫做RMS Prop
这个黑线是我们的error surface,从这个地方开始你要update参数,好你这个球就从这边走到这边,那因為一路上都很平坦,很平坦就代表说g算出来很小,代表现在update参数的时候,我们会走比较大的步伐
接下来继续滚,滚到这边以后我们gradient变大了,如果不是RMS Prop,原来的Adagrad的话它反应比较慢,但如果你用RMS Prop,然后呢你把α设小一点,你就是让新的,刚看到的gradient影响比较大的话,那你就可以很快的让σ的值变大,也可以很快的让你的步伐变小
你就可以踩一个煞车,本来很平滑走到这个地方,突然变得很陡,那RMS Prop可以很快的踩一个煞车,把learning rate变小,如果你没有踩剎车的话,你走到这裡这个地方,learning rate太大了,那gradient又很大,两个很大的东西乘起来,你可能就很快就飞出去了,飞到很远的地方
如果继续走,又走到平滑的地方了,因為这个σᵢᵗ 你可以调整α,让它比较看重於,最近算出来的gradient,所以你gradient一变小,σ可能就反应很快,它的这个值就变小了,然后呢你走的步伐就变大了,这个就是RMS Prop,
Adam
那今天你最常用的,optimization的策略,有人又叫做optimizer,今天最常用的optimization的策略,就是Adam
Adam就是RMS Prop加上Momentum
Learning Rate Scheduling
我们刚才讲说这个简单的error surface,我们都train不起来,现在我们来看一下,加上Adaptive Learning Rate以后,train不train得起来,
那这边是採用,最原始的Adagrad那个做法啦,就是把过去看过的,这个learning rate通通都,过去看过的gradient,通通都取平方再平均再开根号当作这个σ ,做起来是这个样子的
什麼是learning rate的scheduling呢
我们刚才这边还有一项η,这个η是一个固定的值,learning rate scheduling的意思就是说,我们不要把η当一个常数,我们把它跟时间有关
最常见的策略叫做Learning Rate Decay,也就是说,随著时间的不断地进行,随著参数不断的update,我们这个η让它越来越小
那这个也就合理了,因為一开始我们距离终点很远,随著参数不断update,我们距离终点越来越近,所以我们把learning rate减小,让我们参数的更新踩了一个煞车,让我们参数的更新能够慢慢地慢下来,所以刚才那个状况,如果加上Learning Rate Decay有办法解决
刚才那个状况,如果加上Learning Rate Decay的话,我们就可以很平顺的走到终点,因為在这个地方,这个η已经变得非常的小了,虽然说它本来想要左右乱喷,但是因為乘上这个非常小的η,就停下来了 就可以慢慢地走到终点,那除了Learning Rate Decay以外,还有另外一个经典,常用的Learning Rate Scheduling的方式,叫做Warm Up
Warm Up这个方法,听起来有点匪夷所思,这Warm Up的方法是让learning rate,要先变大后变小,你会问说 变大要变到多大呢,变大速度要多快呢 ,小速度要多快呢,**这个也是hyperparameter,**你要自己用手调的,但是大方向的大策略就是,learning rate要先变大后变小,那这个方法听起来很神奇,就是一个黑科技这样,这个黑科技出现在,很多远古时代的论文裡面
这个warm up,最近因為在训练BERT的时候,往往需要用到Warm Up,所以又被大家常常拿出来讲,但它并不是有BERT以后,才有Warm Up的,Warm Up这东西远古时代就有了,举例来说,Residual Network裡面是有Warm Up的
这个Residual Network裡面,就已经记载了Warm Up的这件事情,它说我们用learning rate 0.01,取Warm Up,先用learning rate 0.01,再把learning rate改成0.1
这边有一个可能的解释是说,你想想看当我们在用Adam RMS Prop,或Adagrad的时候,我们会需要计算σ,它是一个统计的结果,σ告诉我们,某一个方向它到底有多陡,或者是多平滑,那这个统计的结果,要看得够多笔数据以后,这个统计才精準,所以一开始我们的统计是不精準的
一开始我们的σ是不精準的,所以我们一开始不要让我们的参数,走离初始的地方太远,先让它在初始的地方呢,做一些像是探索这样,所以一开始learning rate比较小,是让它探索 收集一些有关error surface的情报,先收集有关σ的统计数据,等σ统计得比较精準以后,在让learning rate呢慢慢地爬升
所以这是一个解释,為什麼我们需要warm up的可能性,那如果你想要学更多,有关warm up的东西的话,你其实可以看一篇paper,它是Adam的进阶版叫做RAdam,裡面对warm up这件事情,有更多的理解
Summary of Optimization
所以我们从最原始的gradient descent,进化到这一个版本
这个版本裡面
-
我们有Momentum,也就是说我们现在,不是完全顺著gradient的方向,现在不是完全顺著这一个时间点,算出来的gradient的方向,来update参数,而是把过去,所有算出来gradient的方向,做一个加总当作update的方向,这个是momentum
-
接下来应该要update多大的步伐呢,我们要除掉,gradient的Root Mean Square
那讲到这边可能有同学会觉得很困惑,这一个momentum是考虑,过去所有的gradient,这个σ也是考虑过去所有的gradient,一个放在分子一个放在分母,都考虑过去所有的gradient,不就是正好抵销了吗,
但是其实这个Momentum跟这个σ,它们在使用过去所有gradient的方式是不一样的,Momentum是直接把所有的gradient通通都加起来,所以它有考虑方向,它有考虑gradient的正负号,它有考虑gradient是往左走还是往右走
但是这个**Root Mean Square,它就不考虑gradient的方向了,它只考虑gradient的大小,**记不记得我们在算σ的时候,我们都要取平方项,我们都要把gradient取一个平方项,我们是把平方的结果加起来,所以我们只考虑gradient的大小,不考虑它的方向,所以Momentum跟这个σ,算出来的结果并不会互相抵销掉
- 那最后我们还会加上,一个learning rate的scheduling
我们需要一些比较好的方法,来做optimization,前面有一座山挡著,我们希望可以绕过那座山,山不转路转的意思这样,你知道这个gradient,这奇怪的error surface,会让人觉得很痛苦
Normalization
当error surface(误差曲面)的landscape(景观)十分崎岖的时候,Model难以进行训练。那能不能直接把误差曲面形成的山削平,从而让其容易进行训练。
Batch Normalization就是把山削平的方法之一。
题外话:不要小看optimization问题,有时候就算 error surface 是 convex(凸面)的、一个碗的形状,都不见得好 train。
假设有两个参数,它们对 Loss计算斜率时的差别非常大,在w1方向上的斜率变化很小,在w2方向上面斜率变化很大。
如果采用固定的 learning rate,一般很难得到好的结果,所以才需要adaptive learning rate、 Adam 等等改进过的 optimization 的方法才能够得到好的结果。
现在从另外一个方向想,直接把难训练的 error surface 修改一下,看能不能够改成容易进行训练的误差曲面。
在修改误差曲面之前有一个问题,为什么w1和w2的斜率差别大?
假设现在有一个非常简单的model,它的输入是x1和x2,它门对应的参数就是w1和w2。Model是一个 linear 的 model,没有 activation function(激活函数)
其中,y=x1w1+x2w2+b;e为y与y^的差距。把所有 training data e 加起来就是 Loss,然后 minimize Loss。
什么样的情况会产生不好 train 的 error surface 呢?
也就是通过对w1进行修改,从而让y发生了变化,接着引起e的变化,最终改变了L。
那什么情况下当w1发生改变时对L的影响最小呢?也就是其在error surface上的斜率会很小。
一个可能性是当 input 很小的时候。假设 x1的值在不同的 training example 中都很小,由于 x1 是直接乘上 w1。如果 x1 的值都很小,w1 有变化的时候,它对 y 的影响也是小的,对 e 的影响也是小的,它对 L 的影响就会是小的。
反之,如果 x2的值都很大,当 w2 有一个小小的变化的时候,虽然 w2 这个变化可能很小,但是因為它乘上了一个很大的 x2,那 y 的变化就很大, e 的变化就很大,那 L 的变化就会很大。就会导致我们在 w 这个方向上做变化的时候,改变一点点 w 的值,error surface 就会有很大的变化。
那有没有可能出现上图这种情况。在输入feature是时候,对于不同dimension(尺度;范围)的feature,都具有相同数值范围的Loss,从而产生比较容易训练的error surface呢?
Feature Normalization
这个操作的作用是:
- 做完 normalize 以后,dimension 上面新数值(也就是取出所有特征向量中处于相同分量位置的元素;上图被绿色框框住的部分)的平均值为0,variance就为1。所以这一排数值的分布就都会在 0 上下
- 对每一个 dimension都做一样的 normalization就会发现所有 feature 不同 dimension 的数值都在 0 上下,从而可以制造一个比较好训练的 error surface
像这样子的Feature Normalization 的方式,往往有助于模型的训练。它可以让你在做 gradient descent 的时候让它的 Loss 收敛更快一点,可以让 gradient descent的训练更顺利一点。这个是 Feature Normalization的优点。
Considering Deep Learning:
虽然x_1已经进行了标准化,让输入的x的值的变化幅度缩小了。但是通过W1和sigmoid之后得到的z和a就又变成没有进行标准化的参数了。因此对于W2来说,z和a都算是W2的特征值,为了W2可以更好的进行训练,需要对a和z进行标准化。
如果神经网络中采用了sigmoid,那么推荐对z进行标准化。因为Sigmoid 是一个 s 型函数,它在 0 附近斜率比较大。所以如果你对 z 做 Feature Normalization。把所有的值都归一到 0 附近,到时候算 gradient 的时候算出来的值会比较大。
如果神经网络中没有使用sigmoid,不一定要在z这里进行标准化,如果是选别的位置(比如a)也会有好的结果也说不定,一般来说而言,normalization要放在 activation function 之前或之后都可以,在实操上可能没有太大的差别。
那接下来选择对z进行标准化。
在原先的处理过程中,
是独立分开处理的(上图红框部分),但是我们在做 Feature Normalization 以后,这三个example变得彼此有关联了。
那么上图红框内可以看成一个大的network。
- 之前的 network都只有一个 input,得到一个 output
- 现在有一个比较大的 network,这个大的 network有一堆 input,用这堆 input 在这个 network中算出 μ和σ,得到一堆output
那这边就会有一个问题了,因为训练资料中的 data 非常多,现在一个 data set(数据集),benchmark corpus(基准语料库) 都有上百万笔资料, GPU 的 内存容量完全无法进行存储。
在实际操作的时候,不会让这一个 network 考虑整个 training data 中的所有 example。你只会考虑一个 batch 中的 example。 举例来说, batch 设为 64,那你这个红框中的巨大的 network就是把 64 笔 data 读进去,算这 64 笔 data 的μ和σ,这 64 笔 data 都去做 normalization。
由于我们在实操的时候,只对一个 batch 中的 data做 normalization,所以这个方法叫做 Batch Normalization。但是Batch Normalization显然有一个问题,就是你一定要有一个够大的 batch,才算得出 μ 跟σ ,假设batch size 设为1,就没有计算μ和σ的必要了。
所以Batch Normalization适用于 batch size 比较大的时候。
batch size比较大的时候,如果batch size 中的 data就足以表示整个 corpus(语料库) 的分布,那就可以用这个batch的Feature Normalization代替整个corpus的Feature Normalization,作为 approximation(近似值)。
再乘上另外一个向量γ ,做 element wise 的相乘。而 γ 和 β 可以想成是 network 的参数,它们是另外再被learn出来的。
为什么要有这一步?如果进行 normalization 以后,
的平均就一定是 0,这样会给 network 带来一些限制,也许这个限制会带来一些负面的影响,所以我们把 γ 和 β加进去,从而 network 的 hidden layer(隐藏层) 的 output 的平均值不是 0 ,这样network就会learn γ 和 β,来调整
的分布,也就是输出的分布。
那么为什么要添加γ 和 β?你实际上在训练的时候 γ 和 β 的初始值:
- γ 的初始值都设为1,所以γ一开始其实是一个里面的值都是 1 的向量。
- β的初始值为元素全部都是 0 的向量
所以 network 在一开始训练的时候,每一个 dimension 的分布是比较接近的,也许训练到后面时,已经训练足够长的一段时间,并且已经找到一个比较好的 error surface。训练到一个比较好的误差曲面以后,那再把γ 和 β慢慢地加进去往往对你的训练是有帮助的。
Testing:
以上说的都是 training 的部分,testing有时候又叫 inference(推断) 。那么Batch在 testing 的时候会遇到哪些问题?在 testing 的时候,会一次性把所有的 testing 的资料给Model,所以可以在 testing 的资料上面制造一个又一个的 batch。**但是在一个线上的系统中,testing的资料一般不会一次性的传输给Model。**大多情况下,实时传输的测试资料是达不到batch 设定的值的。
Batch Normalization 在 testing 的时候,你并不需要做什麼特别的处理,PyTorch 帮你处理好了:每一个 batch 计算出来的μ和σ,都会拿出来算 moving average(滑动平均/移动平均)
每一次取一个 batch 的时候,就会算一个 μ1;取第二个 batch 出来的时候,就算个 μ2;一直到取第 t 个 batch 出来的时候,就算一个μt。接下来会算一个 moving average,通过上图红框中的式子来进行计算。公式中右边的
是μ1到μt的平均值,p为 hyper parameter,一般pytorch中设为0.1。同样也可以通过红框的式子计算σ。
总结
QA1:BN和LN的区别
- Batch Normalization 的处理对象是对一批样本, Layer Normalization 的处理对象是单个样本。Batch Normalization 是对这批样本的同一维度特征做归一化, Layer Normalization 是对这单个样本的所有维度特征做归一化
- 它们的出发点都是让该层参数稳定下来,避免梯度消失或者梯度爆炸,方便后续的学习。但是也有侧重点。
一般来说,如果你的特征依赖于不同样本间的统计参数,那BN更有效。因为它抹杀了不同特征之间的大小关系,但是保留了不同样本间的大小关系。(CV领域)
而在NLP领域,LN就更加合适。因为它抹杀了不同样本间的大小关系,但是保留了一个样本内不同特征之间的大小关系。对于NLP或者序列任务来说,一条样本的不同特征,其实就是时序上字符取值的变化,样本内的特征关系是非常紧密的。
QA2:Transformer为什么用LN
当单个样本的长度不一致时,就需要用到layerNorm
CV呢?
Transformer模型相比CNN模型的优点在于它能捕捉一个样本内部的长距离依赖关系,比如一种图像中不同patch的关系,一句话里不同单词的关系。
Batchnorm为批归一化,对相同批次中所有样本的同一位置特征做归一化,而layernorm是对某个样本的所有位置特征做归一化。BN归一化会抹去同一样本所有位置特征的原有大小关系,LN会保留这种大小关系。
结论:使用LN保留了同一样本内部特征的大小关系,因此更有利于Transformer模型(注意力机制)捕捉全局信息。