李宏毅《机器学习》| 神经网络训练不起来怎么办(下)

目录

三、自动调整学习速率(Learning Rate)

1.loss无法再下降时,gradient真的很小吗?

2.特制化learning rate

Root Mean Square

RMSProp

Adam:RMSProp+Momentum

3.Learning Rate Scheduling

Learning Rate Decay

Warm Up

4.Optimization的完整版本

四、分类(Classification)

1.Classification as Regression?

Class as one-hot vector

Classification with softmax

2.Loss of Classification

Mean Square Error

Cross-entropy

五、批次标准化(Batch Normalization)简介

Changing Landscape

feature normalization

Considering Deep Learning

Batch Normalization


接上篇李宏毅《机器学习》| 神经网络训练不起来怎么办(上)

三、自动调整学习速率(Learning Rate)

1.loss无法再下降时,gradient真的很小吗?

在训练一个network时,我们往往会把它的loss记录下来,随着参数update的次数增加loss通常会减小,最后就卡住了。多数时候可能会认为是因为走到了critical point,gradient=0,无法更新参数。但当loss无法再下降时,gradient真的很小吗?

比如当训练终止时,loss几乎已经不动,但gradient却在反复振荡。可能是现在的gradient在error surface山谷的两个谷壁间反复振荡,这时loss不会再下降,但gradient却不是最小的(步幅太大,没法掉下去)。

如果gradient descend所有的参数都设了同样的learning rate,那么当步幅过大时,无法得到较小的loss;反之,无法逼近local minima。当遇到更复杂的error surface,training一个deep network时,gradient descend或许是唯一可以依赖的工具。

2.特制化learning rate

我们需要gradient descend更好的版本——learning rate,特制化每一个参数。

一个大的原则是:如果某一方向上gradient值很小,即较为平坦,则希望learning rate大一点;反之,如果某一方向上坡度很大,可以让learning rate大一点。

Root Mean Square

修改学习率的具体操作:

这也被用在adagrad中。坡度缓的时候,gradient较小,而σ是gradient的平方和取平均再开根号。所以若gradient小则算出的σ就小,learning rate就大(蓝色曲线)。反之,坡度陡峭时,gradient较大,σ就比较大,learning rate就较小(绿色曲线)。

RMSProp

但就算是同一参数,所需的learning rate也会随时间而改变,所以希望learning rate可以动态调整。

RMS Prop的方法是新增一个α,这是一个需要自己调整的hyper parameter 。

以第二步\theta_{i}^{2}\leftarrow \theta_{i}^{1}-\frac{\eta}{\sigma_{i}^{1}}g_{i}^{1}为例:若α趋于0,代表g_{i}^{1}相较于之前算出的gradient较重要;反之,如果α趋于1 ,代表现在算出的g_{i}^{1}不太重要,之前算出的gradient较重要。 α决定了g_{i}^{1}在整个\sigma_{i}^{1}里面占多大的影响力,用RMSProp就可以动态调整σ这一项。

如当滚到下坡时(第三个点)gradient 变大,如用RMSProp使α设小一点,即让刚看到的gradient影响较大的话,就可以很快使σ值变大,也就可以很快让步伐变小(踩一个刹车,避免飞出去)。

Adam:RMSProp+Momentum

目前最常用的optimization的策略是Adam:RMSProp + Momentum

例如,一开始的那个简单的error surface无法train起来,加上 Adaptive Learning Rate 以后:

如右下角所示,最开始的方法只能走到刚刚拐弯的地方,加上Adam后逐渐可以走到终点。因为左右方向上的gradient很小,所以左右方向的learning rate会自动变大,不断前进。至于为什么走到一个地方突然爆炸,是由于\sigma_{i}^{t}是将所有的gradient累计,初始的地方很大,后来纵轴方向上的gradient都很小,累计了很多这样很小的gradient,当累计到一定程度后,step就变得很大,暴走喷出去;随后走到了gradient较大的地方,σ又慢慢变大,于是参数update的距离慢慢变小(左右振荡力度变小),又回到中间峡谷,所以喷出去后有办法修正回来。

3.Learning Rate Scheduling

解决的暴走的方法:Learning Rate Scheduling,即令learning rate与时间有关,随着时间增加令η越来越小,因为越更新离终点越近。

Learning Rate Decay

在刚刚的例子中如果使用该方法,在将要暴走的时候由于时间限制learning rate会慢慢变小,知道走到终点。

Warm Up

learning rate要先变大后变小

那么为什么要用warm up呢?一个可能的解释是,在\theta_{i}^{t+1}\leftarrow \theta_{i}^{t}-\frac{\eta^{t}}{\sigma_{i}^{t}}g_{i}^{t}中σ是一个统计的结果,传达某一个方向到底有多陡峭或者平滑的信息,但这需要足够多的数据统计结果才会精准。一开始σ并不精准,所以最开始不要使learning rate距离初始值太远,令learning rate小一点,探索、搜集有关error surface的信息;等σ统计得较为精准后,再慢慢增大learning rate(具体可见RAdam)。

4.Optimization的完整版本

momentum有考虑gradient的方向,root mean square考虑gradient的大小,所以两者并不会抵消。

接下来探讨的方向是:路不好走,就直接将山炸平,即能否通过修改Neural Network使得error surface变得相对平整,相对便于train。

四、分类(Classification)

1.Classification as Regression?

Regression就是输入一个向量,输出一个数值,我们希望输出的数值跟某个label(目标)越接近越好。其实可以把Classification当作Regression来看:输出仍然是scaler y,要让y跟正确答案的Class越接近越好,但y是一个数字,所以必须把Class也变成数字。假设Class1就是编号1...,那y跟Class的编号越接近越好。

我认为这个方法只适合定序数据,即数字可以表示个体在有序状态中所处的位置,比如此时的假设意味着Class1跟Class2比较像,跟Class3比较不像;但不适合定类数据,即数字仅用于区分类别,没有序次关系。

Class as one-hot vector

比较常见的做法是把Class用one-hot vector来表示,此时两两Class之间的距离都是一样的。如果目标\hat{y}是一个向量,如\hat{y}是有3个element的向量,那network输出的维度也要是3个数字。目前为止所讲的network都只output一个数值(因为过去做的都是regression的问题,所以只output一个数字),那怎么改到三个数值呢?就是把本来output一个数值的方法重复三次:

a_{1},a_{2},a_{3}乘上3个不同的weight加上bias,得到y_{1},再把a_{1},a_{2},a_{3}乘上另外3个weight加上另外一个bias得到y_{2},再把a_{1},a_{2},a_{3}再乘上另外一组Weight再加上另外一个bias得到y_{3},就可以产生3组数字。此时input一个feature的vector,就产生y_{1}y_{2}y_{3},希望y_{1}y_{2}y_{3}离目标越接近越好。

Classification with softmax

做classification时,往往会把y再通过一个叫做激活函数(softmax)的function得到y',然后计算y'跟\hat{y}间的距离。为什么要加上softmax呢?(关于softmax函数可以参考之前的笔记:激活函数) 

一个比较简单的解释是,这个one-hot vector\hat{y}里的值都是0,1,但y里面有任何值。既然目标只有0和1,就先把y给normalize到0到1间,这样才好跟label计算相似度。

上图是soft-max的block,输入y_1,y_2,y_3会产生y_{1}^{'},y_{2}^{'},y_{3}^{'}。先把所有的y取一个exponential,就算是负数,取exponential后也变成正的;然后再对它做normalize,除掉所有y的exponential值的和,然得到y'。具体做法:y_1,y_2,y_3分别取exponential后把它全部加起来,得到一个summation,再把exp y_{1}^{'}除summation,exp y_{2}^{'}除掉summation,exp y_{3}^{'}除掉summation,就得到y_{1}^{'},y_{2}^{'},y_{3}^{'},且都介于0到1之间,y_{1}^{'},y_{2}^{'},y_{3}^{'}的和是1。除此之外,softmax还有一个附带的效果:会让大的值跟小的值的差距更大。

如果是两个class会是怎么样?既可以直接套用softmax这个function,但更常用的是sigmoid(这两件事情是等价的)。

2.Loss of Classification

Mean Square Error

把x丢到network里产生y后,会通过softmax得到y',再计算y'跟\hat{y}间的距离,记作е。计算y'跟\hat{y}间的距离不只一种做法。可以是Mean Square Error:计算\hat{y}里每一个element的平方和,当作error,即计算两个向量间的距离。当minimize MSE时,让\hat{y}等于y'。

Cross-entropy

一个更常用的做法是cross-entropy:e=-\sum_{i}\hat{y_{i}}lny_{i}^{'},当\hat{y}跟y'相等时,也可以minimize cross-entropy的值,此时MSE会是最小的,cross-entropy也会是最小的。

Minimize Cross-entropy其实就是maximize likelihood(极大似然),它们两个就是一模一样的东西,只是同一件事不同的讲法而已。cross-entropy更常用在分类里,在pytorch里,cross-entropy和softmax是被绑在一起的,是一个set,只要copy cross-entropy,里面就自动内建了softmax。

接下来从optimization的角度说明相较于MSE,Cross-entropy更常被用于分类

现在做3个class的分类:Network先输出y_1,y_2,y_3,在通过softmax后产生y_{1}^{'},y_{2}^{'},y_{3}^{'}。假设正确答案就是[1 0 0],计算向量[1 0 0]跟y_{1}^{'},y_{2}^{'},y_{3}^{'}间的距离,用е来表示(可以是MSE,也可以是Cross-entropy)。假设y_1,y_2,y_3的变化分别是-10-10,-10-10,-1000。由于y_3设得很小,所以经过softmax后y_{3}^{'}就非常趋近于0,跟正确答案非常接近,且对我们的结果影响很少。总之y_3设一个定值,只看y_2y_3有变化的时候,对e、对loss有什么样的影响。

如果e分别设定为MSE跟Cross-entropy,算出来的Error surface会有什么不一样呢?

上图分别在e是MSE跟Cross-entropy时,y_1,y_2的变化对loss对error surface的影响(红色代表loss大,蓝色代表loss小)。 如果y_1很大,y_2很小,就代表y_{1}^{'}会很接近1,y_{2}^{'}会很接近0,所以不管是对MSE或是Cross-entropy,y_1y_2小时loss都是小的。反之,如果y_1很小,y_2很大的话,y_{1}^{'}会很接近0,y_{2}^{'}会很接近1,此时loss会比较大。 所以这两个图都是左上角loss大,右下角loss小,我们希望最后在training的时候,参数可以走到右下角。

假设选择Cross-Entropy,左上角这个地方是有斜率的,所以有办法透过gradient一路往右下走。 如果选MSE的话就卡住了,MSE在loss很大的地方是非常平坦的,如果初始在这个地方,离目标非常远,且gradient又很小(趋近于0),就无法用gradient descent顺利走到右下角。 如果做classification选MSE,有非常大的可能性会train不起来,当然这是在没有好的optimizer的情况下;如果用Adam,这个地方gradient很小,那learning rate会自动调大,也许还有机会走到右下角,不过这会让training比较困难,training的起步比较慢。 所以就算是loss function的定义,都可能影响training是不是容易,可以通过修改loss function改变optimization的难度。

五、批次标准化(Batch Normalization)简介

Changing Landscape

如果error surface很崎岖,它比较难train,batch normalization就是其中一个把山铲平的想法。不要小看optimization这个问题,有时error surface是confessed的(比如碗状)都不见得很好train。

假设两个参数对loss的斜率差别非常大,在\omega_1方向上斜率变化很小,\omega_2上变化很大,如果learning rate是固定的,可能很难得到好的结果,所以需要adaptive的learning rate ,较进阶的optimization的方法才能够得到好的结果。

可以从另一个方向想,直接把难做的error surface改掉。假设有一个非常简单的linear model没有activation function,输入是x_1,x_2,对应的参数是\omega_1,\omega_2,什么样的状况会产生上面这种比较不好train的error surface呢?

如果\omega_1\omega_2有改变,y就有改变,e随着也有改变,进而loss也有改变。当input很小时,假设x_1的值都很小,\omega_1有变化的时候,它对y的影响也是小的,进而loss变化也是小的。

反之,当input很大时 ,假设x_2的值都很大,\omega_2有变化时,它对y的影响也是大的,进而loss变化也是大的。

当input的feature每一个dimension的值它的scale差距很大时,就可能产生像这样的error surface。

feature normalization

如果可以给不同的dimension同样的数值范围,那可能就可以制造比较好的error surface,让training变得比较容易一点。有很多不同方法可以做到,将其统称为feature normalization。其中一个方法是:

假设x^1x^R是所有训练资料的feature vector,把同一个dimension不同笔资料中的数值取出来,计算某个dimension的mean,记作m_i;第i个dimension的standard deviation记作\sigma_i。接下来就可以做标准化normalization得到新的数值\tilde{x_{i}^{r}}\leftarrow \frac{x_{i}^{r}-m_{i}}{\sigma_{i}},做完normalization的dimension的数值平均是0 ,variances是1。

当所有的dimension都做一样的normalization后,所有feature不同的dimension的数值都在0上下,那可能就会制造一个比较好的error surface。所以像这样的normalization往往对training有帮助, 可以在做gradient descent的时使得loss收敛更快。

Considering Deep Learning

当然deep learning可以做feature normalization,可能会把feature做normalization以后得到\tilde{x},把它丢到deep network里面去做接下来的计算。但进一步地,对\omega_2来说,a^1,a^2,a^3其实也是另外一种input,虽然\tilde{x}已经做过normalization,但通过\omega_1后没有做normalization。

如果z^1不同dimension间的数值分布仍然有很大差异的话,要train\omega_2第二层的参数会不会也有困难呢?所以也应该对a或z进行normalization(对\omega_2来说a或z其实也是一种feature)。 那应该在activation function之前做normalization还是之后呢?

在实际操作上这两件事情其实差异不大,如果选sigmoid,比较推荐对z做feature normalization(因为sigmoid在0附近斜率比较大,所以如果对z做feature normalization,把所有的值都挪到0附近,算出来的gradient值会比较大)。

对z做feature normalization:把z想成是另一种feature,分别计算三个vector里每一个dimension的μ和σ,然后把z标准化。

z^1改变的时候μ和σ也会随着改变 ,右侧z^1,z^2,z^3的值也会跟着改变,之前\tilde{x}^1,\tilde{x}^2,\tilde{x}^3是独立分开处理的,但在做feature normalization后,这三个example变得彼此关联了,所以做feature normalization时要把这一整个process,即收集feature算出μ和σ这件事情当做network的一部分。

也就是说之前的network都只是吃一个input得到一个output,现在这个大的network是吃一堆 input,用这堆input在这个network里算出μ和σ然后接下来产生一堆output。

Batch Normalization

随之而来的问题是:训练资料里的data非常多,没有办法一次把上百万的数据丢到一个network里面。在实际操作中,不应该让这个network考虑整个training data里所有的example,只会考虑一个batch里的example。因为在实际操作中只对一个batch里的data做normalization,即batch normalization。注:Batch Normalization适用于batch size比较大的时候。

在做Batch Normalization时候,往往还会有下面的操作:

实操中,γ初始值是一个都是1的向量,β初始值是一个都是0的向量。network在一开始训练时,每个dimension的分布是较接近的,也许训练够长的一段时间,已经找到一个较好的error surface,走到一个好的地方后,再把γ和β慢慢加进去。 

接下来是testing部分,有时又叫inference。Batch Normalization在testing中遇到一些问题:假设真的有系统上线,batch设64,一定要等64笔资料都进来才做一次运算吗?这显然是不行的,如果是线上服务,每笔资料进来都有做一次运算,不能等累积了一个batch的资料才开始做运算。那如果根本就没有一个batch,应该怎么算μ和σ?

实际上pytorch已经帮你处理好了。用训练时得到的\bar{\mu}\bar{\sigma}来代替。其中p是一个hyper parameter,通常设为0.1。

具体可参考论文: 

其中黑色虚线代表没有做batch normalization的结果,红色的虚线代表用了batch normalization的结果,可以在比较短的时间内跑到比较好的结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值