Optimization
- 1.Adaptive Learning Rate
- 2.不同的参数需要不同的学习率
- 3.Root Mean Square
- 4.RMSProp
- 5.Adam
- 6.learning rate scheduling
- 7.warm up
- 总结
critical point不一定是你在训练一个network时候遇到的最大的障碍。
1.Adaptive Learning Rate
也就是我们要给每个参数不同的Learning rate
往往在训练一个network的时候,你会把他的loss记录下来,随着你参数不断的update,你的loss呢不再下降了,就卡住了。。那多数时候这个时候大家就会猜说诶,那是不是走到了critical point,因为gradient等于零的关系,所以我们没有办法再更新参数。
当我们说走到critical point的时候,意味着gradient非常的小,但是你有确认过,当你的loss不再下降的时候,gradient真的很小吗?其实并不然。
下面这个例子,当我们的loss不再下降的时候,gradient的这个向量并没有真的变得很小,在最后训练的最终结的时候,loss几乎没有在减少了,但是gradient却突然还上升了一下。这个是我们的error surface,现在的gradient在error surface的两个谷壁间不断的来回的震荡,这个时候你的loss不会再下降,所以你会觉得看到这样子的状况,但是实际上他真的卡到了critical point、卡到了settle point、卡到了local minima吗?不是的。它的gradient仍然很大,只是loss不见得在减小了。
所以当你今天你训练个network,后来发现loss不再下降的时候,可能只是单纯的loss没有办法在下降,而不是卡在了那些点上。
我们在训练的时候其实很少卡到settle point或者是local minima,多数时候training在还没有走到critical point的时候,就已经停止了,但这并不代表说critical point不是一个问题,我们真正当你用gradient descent来做optimization的时候,你真正应该怪罪的对象往往不是critical point,而是其他的原因。
那为什么如果今天critical point不是问题的话,为什么我们的training会卡住呢,我这边举一个非常简单的例子。
你会发现说就连这种convex的error surface,形状这么简单的error surface,你用gradient descent都不见得能把它做好
学习率= 1 0 − 2 10^-2 10−2,时候,在震荡没有办法慢慢的滑到山谷里面,这时试着去调整了这个learning rate
学习率= 1 0 − 7 10^-7 10−7终于不再震荡了,终于从这个地方滑滑滑滑滑滑到山谷底,然后终于左转了,但是你发现说这个训练永远走不到终点,因为我的learning rate已经太小了,在这个很斜的地方,这个坡度很陡gradient的值很大,所以还能够前进一点,左转后的这个地方坡度已经非常的平滑了,这么小的learning rate根本没有办法再让我们的训练前进,,
gradient descent这个工具连这么简单的error surface都做不好,那如果难的问题,他又怎么有可能做好呢
那怎么把gradient descent做得更好呢?在之前我们的gradient descent里面,所有的参数都是设同样的learning rate,这显然是不够的,learning rate应该要为每一个参数特制化。
2.不同的参数需要不同的学习率
大原则:如果在某一个方向上gradient的值很小,在某一个方向上非常的平坦,那我们会希望learning rate调大一点;如果在某一个方向上非常的陡峭,某一个方向上坡度很大,那我learning rate可以设的小一点。
之前在讲gradient descent的时候,往往是讲所有参数update的式子,为了简化问题,我们现在只看一个参数,你完全可以把这个方法推广到所有参数的状况。
不同的参数我们要给它不同的sigma,同时他也是iteration dependent的,不同的iteration我们也会有不同的sigma。
如何计算这个sigma呢?
一个常见的类型是算gradient的Root Mean Square
3.Root Mean Square
这样的话坡度比较大的时候learning rate就减小,坡度比较小的时候learning rate就放大。
坡度比较小的时候如 θ 1 \theta_1 θ1,g小–> σ \sigma σ小—>learning rate就大(你在update的时候的量啊就比较大)
坡度比较大的时候如 θ 2 \theta_2 θ2,g大–> σ \sigma σ大—>learning rate就小
所以有了 σ \sigma σ这一项以后,你就可以随着gradient的不同,每个参数gradient的不同,来自动的调整learning rate的大小
上面的这个参数不会随时间改变,我们刚才的假设是同一个参数,它的gradient的大小就会固定是差不多的值,如果来看这个新月型的error surface,考虑横轴的话,有的地方地方坡度比较平滑,有的地方地方坡度比较陡峭,所以就算是同个参数,同一个方向,我们也期待说learning rate是可以动态的调整的。
所以就有了RMSProp
4.RMSProp
这个方法没有论文。
这个方法的第一步跟刚才讲的算Root Mean Square一模一样
第二步算 σ 1 \sigma_1 σ1的方法和算Root Mean Square的时候不一样,上一个的每一个gradient都有同等的重要性,但在RMSProp你可以自己调整现在的这个gradient的重要性,
如果我 α \alpha α设很小趋近于零,就代表说我觉得g1相较于之前所算出来的gradient而言比较重要;如果我 α \alpha α设很大趋近于1,那就代表说我觉得现在算出来的g1比较不重要。
这个 α \alpha α就会决定现在刚算出来的 g t g_t gt它有多重要
如果你用RMSProp的话,你就可以动态调整 σ 1 \sigma_1 σ1这一项.
比如下面的黑线,是我们的error surface,开始小球一路平坦,说明G算出来很小,G算出来很小,就代表说这个 σ \sigma σ算出来很小, σ \sigma σ算出来很小,就代表说现在update参数的时候,我们会走比较大的步伐;
当滚到斜坡时候,我们gradient变大了,如果是Adam的话,它反应比较慢;但如果你用RMSProp,把 α \alpha α设小,就是让新看到的gradient影响比较大,那你就可以很快的让 σ \sigma σ的值变大,然后很快让你的步伐呢变小。
又走到平滑的地方时候,调整 α \alpha α,让他比较看重于最近算出来的gradient,所以你gradient变小,它的这个 σ \sigma σ的值变大值呢就变小了,然后呢你走的步伐呢就变大了。
5.Adam
最常用optimization的策略就是Adam:RMSProp+Momentum
我们再看开始的例子,用了第二个的方法后做起来是这个样子的。这个gradient都取平方,再平均再开根号,然后接下来在左转的时候,刚才我们update了10万次卡住了,现在可以继续走下去,因为这个左右的方向的这个gradient很小,所以learning rate会自动调整,左右这个方向learning rate会自动变大,所以这个步伐呢就可以变大。
但走着走着突然爆炸了,为什么走到这边突然爆炸了呢?因为我们在算这个 σ \sigma σ的时候是把过去所有看到的gradient都拿来做平均,所以这个纵轴的这个方向,这个纵轴的方向虽然在初始的这个地方感觉gradient很大,但是这边走了很长一段路以后,这个纵轴的方向gradient算出来都很小,所以纵轴的这个方向就累积了小的 σ \sigma σ,累积到一个地步以后,这个step就变很大,然后就暴走就喷出去了,,
不过喷出去后走到gradient比较大的地方以后, σ \sigma σ又慢慢的变大, σ \sigma σ变大以后,这个参数update的距离,update的这个步伐大小又慢慢的变小,所以就发现说诶走着走着突然往左右喷了一下,但是这个喷这个喷了一下,不会永远就是震荡,不会做简谐运动,他这个左这个这个力道会慢慢变小,让它慢慢的慢慢的又回到中间这个峡谷了。
这样怎么办呢?有一个方法也许可以解决这个问题,这个叫做learning rate schedule
6.learning rate scheduling
我们这个式子还有个参数 η \eta η,他要是跟时间有关的,我们不要把它当成一个常数。
最常见的策略啊叫做learning rate decay,也就是说随着时间不断的进行,随着参数不断的update,我们这个 η \eta η让它越来越小,让这个learning rate越来越小。
为什么要让这个learning rate越来越小呢?因为一开始我们距离终点很远,随着参数不断update,我们距离终点越来越近,我们参数的更新要能够慢慢的慢下来。
所以刚才那个状况,如果加上learning rate decay的话,我们就可以很平顺的走到终点。因为在后面这个 η \eta η已经变得非常的小了,虽然说他本来想要左右乱喷,但是会乘上这个非常小的 η \eta η,那就停下来了,就可以慢慢的走到终点。
除了learning rate decay以外,还有另外一个经典非常常用的learning rate schedule的方式叫做warm up。
7.warm up
这个warm up的方法是说我们这个learning rate要先变大后变小
Residual Network这边特别注明它反其道而行,一开始要设0.01,接下来设0.1,还特别加个注解
同时warm up在transformer里面也用一个式子提了它好,你实际上把它的把这个方程画出来,就会发现它就2learning rate会先增加,然后接下来再递减。
所以发现说warm up这个技术,在很多知名的network里面都有被当做一个黑科技,就论文里面不解释说为什么要用这个,但就偷偷在一个小地方,你没有注意到。
那为什么需要warm up呢?这个仍然是今天一个可以研究的问题了。
这边有一个可能的解释是说,当我们在用Adam、RMSProp时候,我们要计算 σ \sigma σ,这个sigma它是一个统计的结果,告诉我们说某一个方向他到底有多陡或者是多平滑,那这个统计的结果要看了够多笔数据以后,这个统计才精准,所以我们一开始呢 σ \sigma σ不精准,所以开始不要让我们的参数走离初始的地方太远,一开始让learning rate比较小,是让他探索搜集一些有关error surface的情报,等sigma统计比较精准以后,再把让learning ray呢慢慢的爬升,这是一个解释为什么我们需要warm up的可能性。
如果你想要学更多有关warm up的东西的话,可以看RAdam。
总结
有关optimization的部分,我们从最原始的gradient descent进化到下面这个版本
这个版本我们有momentum,也就是说我们现在不是完全顺着这个时间点算出来gradient的方向来更新参数的,而是把过去所有算出来的规定的方向做一个加总,当做update方向,这个是momentum。
那接下来到底应该要update多大的步伐呢?我们要除掉gradient的root mean square。
疑问:这个momentum是考虑过去所有的gradient,这个 σ \sigma σ也是考虑过去所有的gradient,一个放在分子,一个放在分母,都考虑过去所有的gradient不就是正好抵消了吗?
其实这个momentum和 σ \sigma σ他们在使用过去所有gradient的方式是不一样的。
momentum是直接把所有的gradient通通都加起来,他有考虑方向,考虑gradient的正负号,考虑gradient是往左走还是往右走。
但是root mean square,它不考虑gradient的方向了,它只考虑gradient的大小,我们在算 σ \sigma σ时候都要取平方向,把gradient取一个平方向,是把平方的结果加起来,所以我们只考虑gradient的大小,不考虑它的方。
所以momentum跟这个 σ \sigma σ算出来的结果并不会互相抵消掉。
最后我们还会加上一个learning rate的schedule。
这种optimizer除了Adam以外还有各式各样的变形.