李宏毅机器学习Task5打卡

一. 局部最优值和鞍点
为什么最优解会失败呢?在training时,参数已经训练了很多,更新了很多次参数,但仍然对loss不满意。或者一开始,model就训练不起来。
可能是因为,参数走到一个偏微分为0 的地方。
而偏微分为0的时候,不一定是局部最优解,比如说鞍点saddle point。
image

像是gradient 为0的点,统称为critical point临界点。

所以如何判断gradient是卡在local minimal还是卡在saddle point 呢?如果卡在local minimal,那是没有路可以继续更新的;而如果是卡在saddle point,那参数是可以继续向下更新的。

在θ处,L(θ)是可以近似展开的,也就是泰勒展开,如下图:
image
而在critical point 处,说明gradient为0,也就是绿色的那一项为0.
所以第三项告诉了critical point的处境。
image

所以,我们如何根据红色的那一项Hessian来判断loss的形状呢?
有三种情况,如果红色框框里都大于0,则在θ‘附近,L(θ)一直大于L(θ‘),所以θ’是局部最小值;反之,是局部最大值;而如果红色框框里的值有时大有时小,则为一个saddle point。
而如何判断红色框框里面的正负值呢?可以通过H的eigen value(特征值)来判断,如下图:
image

举个简单的例子:
加入model是y = w1w2x
通过一次偏微分,可得知,在w1=0,w2=0的时候,是critical point。
而如何判断是鞍点还是局部最优解呢?
通过算二次偏微分就可以知道,如下图,将w1=0,w2=0带入二次微分的值,得到H矩阵,可以算出H的特征值有大于零也有小于零的,所以0,0是saddle point。
image

而如果某个点是saddle point,则如何更新参数呢?可以根据H矩阵来进行更新。
image
如果λ<0,则红色框框小于0,让u = θ-θ‘,则θ= u+ θ’,所以沿着u的方向,就可以让Loss减小。

所以只要沿着特征向量的方向,就可以让Loss变小。

所以说虽然critical point 没有gradient,但是在saddle point只要找出负的特征值和对应的特征向量,就能够找到让Loss变小的方向

但是在实际中,由于计算量较大(需要计算二次微分和特征值特征向量),所以并不实用。

但是,saddle point和local minima哪个更常见呢?

其实在更高纬度的视角中,每个local minima都可以是saddle point。

在现实中,我们在训练network的时候,参数往往动辄就百万甚至千万以上,所以在计算loss时,error surface其实在一个非常高的维度中(参数有几个,就代表有几维)。

下图是一个训练网络的结果,每个点就代表训练之后,把Hessian矩阵算出来的结果:

image

所以看出来,这张图越往右,说明这张图越像local minima,但是它仍有接近一般的负的特征值,即说明,仍有一半的参数能够调整使得loss更小

所以local minima并没有那么常见。所以在训练网络时,觉得gradient很小,不再更新参数了,往往是因为卡在了一个saddle point。

二. 批次
在训练的时候,并不是对所有的数据进行训练,来update 参数,而是将所有的数据,分成一个个的batch。并根据那一个个的batch来计算他们的最终参数。如下图;

image

所有的batch看过一遍,便是一个epoch(纪元)。

shuffle:

在每一个epoch开始之前,我们都会将数据分成一个个的batch。每一个epoch的batch是不一样的。这样的情况叫做suffle。

为什么要用batch呢?
image

如上图的左边,当没有分batch时,或者说所有的数据都放一个batch中(full batch)时,模型必须要计算完所有的数据后才能update一次参数。

而如果像右边,当batch较小时,(此时设为1),只需要计算完一个数据,就能够更新一次参数。如果总共有20个数据,则总共会更新20次参数。

它们的特点也如下所示:
image

左边的每一步都非常的较慢但是稳健,而右边每一步的差别较大但是运算速度较快。但事实真的如此么?

注意:如果考虑平行运算的话,左边的(full batch)的情况,每次运算的时间并不一定比较长。

比如在进行手写数字识别的时候,10和100,1000个数据其实时差不多的。因为GPU会进行平行计算
image

所以说,当数据比较小的时候,small batch 比 large batch更耗时。因为每次update参数的时间是差不多的,但是small batch会计算更多的次数,所以会更费时间。
image

所以说上面的特点也并不是正确的
image

而大的batch没有了运算慢的劣势,是否只剩下每一次更新参数都稳健精确的优点了呢?

事实上也并非如此,其实,noisy的gradient更有利于training。如下图:
image

看上图,batch越大,validation的精度越差。但这也不是过拟合,因为batch越大,training的结果也越差。

为什么同一个模型,同一个网络,为什么得不出相同的结果呢?

因为这不是model的问题,问题出在optimization(最优解)上。

为什么小的batch,会有较好的结果呢?

用大的batch来算gradient,可能会卡在某个点;而利用small batch来算gradient,虽然某一个batch可能会卡住,但是由于batch的数量很多,其他的batch可能是可以计算的。
image
而且,小的batch不仅对training有帮助,对testing也是有帮助的。
通过下图可以看出来,即使在training的时候有差不多的精度,在testing的时候,小的batch也是比大的batch有较好的精度。
image

为什么会这样呢?

如下图,假设有一个loss的趋势如下,有很多的local minima,但是,其实local minima也是有好差之分的,我们认为,在相对平缓的地方出现的local minima为好的,在“山谷”里出现的为差的。
image

因为当testing 和training的loss图像差别不大,可能由于数据问题出现偏移时,好的local minima对testing的loss影响并不大;而“峡谷”中的local minima则会和testing有着很大的差别。

我们认为大的batch更可能产生"峡谷"中的local minima。

因为小的batch参数更新的频率较高,所以一个小的“峡谷”,小的batch可能会及时的“跳出”。

小的batch和大的batch的比较如下:
image

momentum(动量)
可以对抗saddle point和local minima的技术。

把loss看作一个斜坡,参数看作一个小球,这样在更新参数就相当于把球滚下来,这样即使碰到了saddle point甚至local minima也不一定会停下来。
image

普通的gradient如下图:
image

每次先计算gradient,然后反方向更新一次参数;依次这样进行,直至最终。

而加了momentum的gradient如下图:
image

每次更新参数,不是往gradient的反方向移动,而是往“反方向加上前一步移动的方向的综合方向”进行移动。

还一种解读方式就是,现在每一步的参数更新不是只考虑当前的gradient,而是考虑之前所有gradient的综合。

总结如下:
image

  1. critical point的gradient为0
  2. critical point可能是saddle point也可能是local minima
    2.1 是哪一种可以通过hessian矩阵来判断
    2.2 如果是saddle point能够通过hessian矩阵的特征向量来指明调整方向
    2.3 local minima其实并不常见
  3. 小的batch size和momentum有助于让参数逃离critical point

三. 自动调整学习速率
在训练一个网络的时候,cirtical point并不是会遇到的最大的问题。
image

在训练时,loss不再下降的时候,我们通常会认为是gradient为0,参数的更新卡在了一个critical point。而,当我们看一起gradient的趋势时可能会看到gradient并不是0。
分析其原因,可能是参数的更新遇到了下面这个情况:
image

这种情况下,loss不再减小,但是gradient并不是0,训练也没有碰到local minima。
这时,我们需要调整每一个参数的learning rate。

多数training,在没有走到critical point的时候,就已经进行不下去了。
所以在训练时,loss不再减少,训练不下去的时候,真正的“凶手”可能是learning rate。

当learning rate较大时(10的-2次方),可以看到参数在最优解的地方“反复横跳”,而当learning rate调整到较小的时候,会发现当参数在“山谷”时,更新的步幅太过于小,向右下角的图,在山谷区域,这么短的长度,更新了10万个点。
image

所以,我们需要特质化的learning rate,不同的参数,需要不同的learning rate。

image
我们其实是希望当一个地方loss比较陡峭时,learning rate可以小一点;而当loss比较平缓的时候,learning rate可以调大一点。

learning rate 如何根据gradient作调整呢?
原来的参数更新如下图:
image
n是learning rate,是固定的。
而现在,将n调整为下图:
image
而上式中的θ如何计算出来呢?如下图:
image
θ是过去所有gradient的均方根。

上面的这种方式,被用到Adagrad中。

而当error surface非常的复杂呢?比如说如下图这样的:
image

所以说即使是同一个参数,同一个方向,我们也希望learning rate可以动态的调整。如何做呢?
image

图中的a需要自己手动调整,如果将a设置的非常小,就意味着我们在计算learning rate的时候,考虑后一项的gradient比较多。

现在最常用的方法就是上面的方法(RMSProp)和Momentum结合的Adam方法。
image

再进行训练,Adagrad的训练结果如下:
image

因为,θ要考虑过去每次的gradient,而在“山谷中”我们累积了较多的较小的gradient,而它又在分母的位置,所以loss会在某一个地方爆发出来。

如何不让它爆发呢?
也有修改的方法,就是让n和时间相关就好,随着时间的进行,让分子n也逐渐减小(因为随着训练,gradient会大概率的越来越小)。
修改之后的结果如下图所示:
image

Warm up
让learning rate先变大,后变小。
image
虽然没有特别正式官方的解答,但是可能的原因是:
在计算Adagrad, Adam的时候,需要计算θ,而θ又是一个统计的结果,而统计需要有足够的数据才算精准,所以说我们一开始的时候,不要让数据走的太远,让learning rate先从小慢慢的爬升,等到有一定的数据基础之后,再缓慢下降。

总结:
image
改进后的训练式如上。θ和momentum需要考虑到过去所有的gradient,而momentum需要考虑gradient的方向、正负号等等,而θ只考虑gradient的大小。

四. 损失函数

分类

Regression:
输入一个变量x,通过一个model输出一个y,让结果与标准答案越近越好

Classification as regression:

输入一个变量x,通过一个model,输出一个y,希望结果与calss的编号相似。
image

但是class1和class2比较接近,class1与class3比较不同。这是真的合理的么?显然并不是。所以怎么办呢?

在分类时,将class用one-hot vector来表示。
这样它们两两之间的距离是一样的。
image

Classification中的y为一个矩阵,需要经过softmax进行处理,将y里面的任何值全变成0到1之间,最后在于标准答案做比较。

Softmax处理的原理如下图:
image
简单来说就是单位化,exp(yi)除以它们的总和。这样它们的结果全在0至1之间。

注意:exp(yi)是指以e为底,yi为指数。
计算结果y’和标准答案之间的距离怎么求呢?

除了求他们各个距离平方的总和之外,还有另一个公式,如下:
image
为什么会有cross-entropy这么奇怪的公式呢?

因为“最小化交叉熵等价于最大似然“。注意:一般pytroch在计算cross-entropy的时候,会默认把softmax一起计算。

那换个角度对cross-entropy进行解释如下:
如下图,我们将y1,y2,y3进行softmax处理后,得到y’,并计算其与正确答案之间的距离。只考虑y1,y2时,如果y1很大,y2很小的时候,y1’会很接近1,y2’会很接近0。那么无论对MSE还是Cross-entropy,loss都是小的。而如果反之,y1很小,y2很大的时候,loss都是较大的。

而有些点,在MSE中会被卡住,不知道如何继续更新参数。而在cross-entropy却可以进一步计算gradient更新参数。
image
MSE在这种loss很大的地方,是非常平坦的,它的gradient非常小,容易被卡住。

所以说改变loss function也可以改变训练的难度。

五. 批次标准化

如果w1,w2之间的斜率差很多的时候吧,是很难计算到最优解的。
那如何判断w1和w2的斜率呢?
首先,改变一下w1,那么y,也会跟着改变,最后Loss也会跟着改变。那么怎么样才能让w1对结果L的改变很小呢?首先,就是如果w1的输入,x1,如果很小的话,w1产生的影响也较小。
而如果x2很大,那么结果对w2就非常敏感。

所以差别较大的输入x1,x2会造成w1,w2的斜率差别较大,导致训练难度增加。
所以应该控制输入的batch有相似的数值范围。
image

Feature Normalization的一种方法:
如,让同一纬度的每个数值都减去它们的均值,并除以标准差。
image

然而,在深度学习中,标准化的后的输入,经过计算后得到的z和a也同样作为w2的输入,所以仍然需要对z或者a进行标准化。
(对z或者a进行标准化是差别不大的)
image

对z做标准化的过程如下:
image
而标准化后的z为:
image
所以可以得到标准化后的z1,z2,z3:
image

注意,在标准化之后,z1,z2,z3和a1,a2,a3都是彼此关联的了,因为它们都需要通过均值和标准差计算获得,所以当改变z1时,a2,a3也会跟着改变。
image
上述过程,适用于batch的size较大的情况。

在进行标准化的时候,通常会将标准化后的z再做一步处理,如下:
image
为什么呢?因为没处理前的标准化的z平均是0,可能会对后面的计算产生影响,所以再做一步处理,让其平均不为0。

讲完了training的部分,接下来是testing的部分。
很多线上的服务,等不到数据的全部,就要进行testing。所以还没有batch,就需要进行testing。在training的时候,计算每个均值和标准差的moving average,如下图:
image

为什么batch 标准化会有帮助呢?

有一种解释,如下图,我们的x通过一定的计算A得到a,然后a再通过一定的计算得到b。然后我们通过gradient更新A和B。
这里B是通过a计算出来的,所以是有利于a的计算结果,但是现在更新了A之后,a也变成了a’,所以更新后的B’并不一定对a’也合适。而标准化后能够消除这种影响。也许就对结果又帮助。
image
当然也有学者,反驳了以上的论点。

Batch normalization能够改变error surface变得平滑。

浙ICP备19012682号