前情回顾
回顾上节课中涉及到的Gradient Descent 内容:
现在假设θ就是一个模型的参数集合,我们使用loss function 来更新参数集合的变化。
然后我们使用如下式子来代表Loss function对于参数的偏微分:
那我们用可视化的方式来看这个问题:目前假设只有两个参数,我们随机选一个初始位置θ0,
我们一步一步按照graident descent的方式,红色代表gradient,就是看做等高线的法线,那我们要做的就是反向移动,一直移动
关于Learning rate
learning设置的大小将影响在Loss function上更新的参数的快慢和幅度。如果太大,可能无法真正进入到全局最低点,如果太小,可能步伐太小,太慢。
所以在做gradient descent的时候要把这下面这个图画出来,如果不画出来,会觉得非常卡。
learning rate太大,就会飞出去,太小太缓慢,大一点就又不够拟合。
有的时候,我们在做测试会发现情况不好,所以就要回头看看这个曲线,是否需要调整Learning rate,但是调整learning rate比较麻烦,如何自动的调整呢?
大原则:
1. Learning Rate通常会随着参数的update,变得越来越小
1.1 因为通常最开始的时候,初始点距离最优点比较远,所以我们希望步伐大一点,尽快走到最低点。
1.2 但经过几次参数更新后,我们会比较接近最优点,这时候就需要减少learning rate 让它能够收敛在最低点附近。
1.3 例如,在 t 时刻,我们让他的learning rate 除以t+1 开根号,来进行减小。
但是这样还不够!!!
因为不可能one-size-fits-all.最好的情况是每一次的参数update,我们都给他不通的learning rate。
下面介绍一些大招:
1. Adagrad
以上就是Adagrad 的做法,是说,每次参数更新的learning rate, 都给他
除以之前算出来微分值的root mean square
(
均方根
)
设如下的式子,gt是t时刻的Loss function 对参数w的偏微分。学习率唉塔t。
在之前我们普通gradient descent中,更新w参数,我们会直接减去这个唉塔t乘以gt。
在
Adagrad里面我们把学习率除以西格玛t,这个西格玛t是过去所有参数w的偏微分值得均方根(root mean square
)。
现在也就是说对于每次更新参数,learning rate的值都不一样。
所以在
Adagrad里面就是这么做的:
第一次,更新w1,我们回去给学习率learning rate
去除以一个
那西格玛0又等于过去所有参数w的偏微分值得均方根,在第一次的场景下,他就等于g0的均方根。
那第二次,更新w2,我们学习率
就等于上面是式子的,然后我们更新本次的学习率,去求
,让去除以之前所有参数w的偏微分值得均方根,那么本次他应该等于g0的平方+ g1的平方,然后取平均(除以2),再开根号。
然后第三次:
重复这个动作,直到第t次,
的算法,就是把之前所有对于w的偏微分平方和取平均后开根号。
总结下来Adagrad的算法就简写成这个样子,这里给出了的算法,
由于上面式子,分子分母都有同样的一个t+1分之1的开根号,所以这个约掉之后就生下面的简写:
Adagrad是adaptive learning rate里面最简单的,这种方法在更新的后期会越来越慢,因为学习率变得越来越小。使用
Adam的话就比较不会有这样的情况。
而在普通的gradient descent下面,更新快慢取决于两个参数,一个是学习率,一个是偏微分gradient。gradient 越大step越大。
然而在
Adagrad里面看着有点矛盾。
下面可以看出,gradient越大step越大, 而分母,确实gradient越大step越小,自相矛盾??
这里就牵扯出来Adagrad的设计理念,它本来的理念是想看看这个模型到底有多大的
反差!
例如上面这个例子,在两次training的时候,每次参数都有一个非常大的反差值,这个时候Adagrad就可以利用分子分母的制约来看看到底有多大的反差。
正式的解释:
考虑这样一个曲线,然后y对于x作微分,可以得出|2ax + b|的两条直线
这个函数的最低点,是
现在随机选一个点X0,怎么的一个步伐是最好的呢,当然直接一步到位,步伐长度直接都等于他到最低点之间的距离最好。
那他们之间的距离是多少呢? 是,然而|2ax0 + b|是什么呢,他是X0这一点的一次微分
那也就是说在只考虑一个参数的情况下,gradient descent听起来很有道理,微分值越大,那我们距离远点越远。如果踏出去的步伐,跟微分大小成正比,那可能是最好的一步。
那我们同时考虑好多个参数的时候,就不一定成立。比如W1 和 W2 两个参数。
看下面的Loss function的等高线图
如果我们先看W1的参数, 我们先用蓝色切一刀,我们得到的error surface如下蓝色曲线。
如果针对W1考虑a、b两个点,那么确实a>b
如果我们接着考虑W2,我们用绿色切一刀,得到的error surface如下面绿色曲线,、
针对W2考虑的c、d两点,得到c>d
然而将两个参数得到的四个点放到一起看看,也就是说虽然a>c,但是c却比a更靠近最地点
那如果对于多个参数我们该怎么想呢?回到最佳距离这个例子,我们去看最佳距离的分布,是2a。
再去看曲线对于x的一次微分得到的|2ax + b|,那对于曲线做2次微分呢?我们就得到了2a,他是一个常量。
所以这个2次微分得结果就出现在了最好的step的分母地方。
所以得到的结论就是最好的step是跟一次微分成正比,跟而次微分城反比。
也就是说如果二次微分比较大,那这个时候update的参数的量比较小。而二次微分比较大的时候,参数的update量比较小。
所以最好的step是应该要把二次微分考虑进来。
那么最好的做法是什么呢?
来看图,考虑二次微分进来,发现W1对于他的二次微分相对比较小,因为他的等高线是相对平滑的谷,
而对于W2的二次微分相对比较大, 因为他得等高线是相对比较尖的谷。
所以光比较a跟c的微分值是不够的,要比较a和c点的一次微分除掉他的二次微分,再来比较,才能够真正显示哪个点距离最低点比较近
那这件事情跟
Adagrad什么关系呢?
列出
Adagrad式子看
是一个常量,不理他,gt是一次微分,而分母下面的那个gi的平方再开根号,其实就代表了2次微分。
可是又有疑问了,为什么不直接算二次微分呢?
确实,是可以直接算二次微分的。这里不适用,那是因为有的时候一次微分的运算就会很久很久,再算二次微分就会更慢,这个效率是不能承受的。Adagrad是使用的
一次微分的值来模拟近似二次微分。
那他是怎么做的呢?
下面,我们考虑二次微分比较平缓的峡谷,和一个二次微分比较尖的峡谷。
那我们看到他们的一次微分张下面这样:我们在上面选择sample多个点,就能大概看的出他的二次微分的近似大概长什么样子。
其实呢,Adagrad就是用在一次微分上做大量sampling 的平方和,在开根号,来近似描述二次微分的形状。结束!
2. Stochastic Gradient Descent - 随机梯度下降
-- 让你的training 更快一点
在一般的gradient descent 里面,我们使用全部的training example 去进行update
而在Stochastic Gradient Descent 里面,loss function也只算这一个example的loss,接下来在update参数的时候也只考虑那一个
也就是说,普通的GD他会需要遍历所有的example才开始进行update参数,
而Stochastic GD 会看一个参数update一次,看一个参数update一次,就会相对比较快。
而且SGD每一次的update,可能会跟总体的update方向不见得一致,但大体方向却是一致的,但是从update到step步伐会比较快。
3.
Feature Scaling - 特征缩放
例如有两个features,其中一个比另一个的range大很多,那我们可以将很大的那个的range缩小到差不多一致。
为什么要这么做呢?
以上面的模型为例,也就是因为y的结果是来源于特征X和权重W的乘积,所以,如果其中一个特征X2的取值范围比X1的取值范围大了100倍,那么X2特征对于整体的影响要远远大于X1对于整体估算的影响。这显然不合理。
从loss surface来看W1的微分对于loss比较小,W2对于loss影响比较大。
如果,X1,X2取值range比较接近,那loss surface看着就是圆形的
像那种椭圆的error surface,不用adagrad很难搞定。因为从任意一点走向最低点, 都要绕弯路。
而圆形的error surface,从任意一点都可以几乎直线走到最低点,效率很快。所以做了scaling很重要。
Feature Scaling的做法:
有R个feature X, 对于每一个维度比如说i,假设他的均值是
,他们的标准差是,然后根据公式去计算,
做完这件事后,就会得到所有维度的均值是0,所有variance方差都是1. 这就是正太标准化。
Gradient Descent 数学理论依据-- 泰勒公式
如下图,假设有两个参数的model,如果给出一个error function,没有办法马上讲出最低点,但是可以得出如果给出一个初始点,我们可以在初始点一定范围之内可以找出最小值,然后我们更新一下位置到θ1, 然后在画一个圆圈在这个范围内再找一个点,更新到θ2,然后一直下去。
然而,现在的问题是,怎么在一个很小的圈圈范围内,找到最小的点。
这个就要从Taylor Series(泰勒级数)开始,高阶导数次幂趋向于高阶无穷小,所以最后舍去。回头去复习泰勒级数。
例如单个变量的泰勒级数, 使用泰勒展开式去模拟近似曲线,假如只保留第二项,那么他就画出来可能是一条斜线。
也就是说,如果x是取接近于π/4的时候,后面的平方项、立方项、高次方项等都会非常小,近似于0,那么这时候右边的式子就和sin(x)在π/4位置处重合。以此类推。
下面例子是多变量泰勒级数,类似于上面单参数的式子,x、y两个参数时,当x、y都趋近于x0、y0的时候,所有高阶项都很小趋近于0,所以这时就只剩下了最后的对于x,y的一阶导数项。
这里一阶导数微分的值得出就是常数项而已,所以只剩下了h(x0,y0)+ A(x-x0) + B(y-y0)
那么下面基于泰勒公式的话,我们有两个参数,起始点(a,b),我们可以在很小的这个范围内,使用泰勒公式,对loss function 做简化:
所以在红色的圈内,loss function可以写成下面这样
由于上面式子L(a,b)和偏微分项都是常数,我们就用下面字母替代:
整个式子就变得简单了。
那我们来计算怎么来使上面这个loss function 最小呢?
首先,我们先忽略s,因为s是常数项,跟θ没有关系,不会影响L的取值。我们设θ1-a的值是丢他θ1,θ2-b的值是丢他θ2.
那么肯定有丢他θ1+丢他θ2的平方和会小于这个圆的半径的平方。
那么怎么去选择
丢他θ1和丢他θ2的值,才能让丢他θ1和丢他θ2的值最小呢?
方法就是:
1.把丢他θ1和丢他θ2向量指向(u,v)的反方向
2.让向量的长度达到极限,即指向圆的边缘。
所以结论就是如下式子,让
丢他θ1和丢他θ2等于负的(u,v),然后乘上一个系数,这个系数就是用来控制向量的长度,让他正好达到圆的边缘。这个时候取值的θ算出来的loss function的值是最小的。
展开来写就是,今天去找在一个以(a,b)为中心点的范围内最小值(θ1,θ2),就等于中心点(a,b)减去一个常数乘以(u,v)
然后,我们再将u,v带进去看看,忽然发现,这个式子压根就是gradient descent嘛,一模一样!!!
原来如此啊,gradient descent 是从泰勒展开式的原理得来的。
但是只有在红色圈的半径够小的情况下,泰勒公式的准确度才会更高。也就是说,learning rate的那个参数每一次update都需要很小很小,精确度才能比较高。
也就是说在做gradient descent的时候,要给定一个合理小的learning rate, 才能保证泰勒展开式的准确性,如果learning rate过大,会导致泰勒展开式不成立,这样失去了理论依据,那么也就自然导致了gradient descent那个式子的不准确。
上面的泰勒公式只考虑了一次式,但是泰勒公式不是还有更高阶的2次,3次等,为什么不考虑呢?
如果考虑2次,理论上learning rate就可以设得大一点,也是可以的。但是这样的话,你就会需要去计算二次微分以及更多的运算。
需要考虑这样的多出来的运算带来的代价是否合理。在做deep learning的时候这些多出来的运算是无法承受的。
Gradient Descent 的限制
Gradient Descent 梯度下降会卡在
local minima和
saddle point
两个地方
但是在实际操作中,可能还没有到任何一个local minima或者 saddle point 的地方之前,比如平原带,微分值已经非常小的时候,就会把它停下来。你以为我们已经达到了全局最优解。