梯度下降(GD)是将风险函数、损失函数最小化的一种常用的方法,是神经网络模型训练最常用的优化算法。对于深度学习模型,基本都是采用梯度下降算法来进行优化训练的。
目标函数J(θ)关于参数θ的梯度是目标函数上升最快的方向。对于最小化优化问题,只需要将参数沿着梯度相反的方向前进一个步长,就可以实现目标函数的下降。这个步长又称为学习速率η。参数更新公式如下:
θ ← θ − η ▽ θ J ( θ ) \theta \leftarrow \theta -\eta \bigtriangledown _{\theta }J(\theta ) θ←θ−η▽θJ(θ)
上一篇讲到最基本的线性回归问题,假设只有一个变量。那么会得到直线y = ax + b,最终就是优化参数a、b,寻找最小的loss。
l o s s = J ( θ ) = 1 2 m ∑ i = 1 m ( y θ ( x i ) − y i ) 2 loss = J(\theta ) = \frac{1}{2m}\sum_{i=1}^{m}(y_{ \theta }(x_{i})- y_{i})^{2} loss=J(θ)=2m1i=1∑m(yθ(xi)−yi)2
显然loss函数是一个二次函数,问题就转化成了如何求二次函数的最小值。
step1:假设我们要优化的函数是 y = x 2 y = x^2 y=x2,初始条件为 x 0 x_0 x0 = 2, y 0 y_0 y0 = 4。图示如下
图中红色的点就是我们的初始点,很显然,我们想要找的最终最优点是绿色的点(0,0) 。
step2:对目标函数求微分
d y d x = 2 x \frac{dy}{dx} =2x dxdy=2x
这就是所谓的梯度,当x=2的时候,可以求得该点的梯度为4,简单来说就是当前这一点的’倾斜程度’是4。
step3:下面给出几个例子
x | -2 | -1 | 0 | 1 | 2 |
---|---|---|---|---|---|
y | 4 | 1 | 0 | 1 | 4 |
梯度 | -4 | -2 | 0 | 2 | 4 |
从表格中很容易发现,梯度的绝对值越大,数据点所在的地方就越陡。数字为正数时,越大,表示越向右上方陡峭,反之亦然。好了,懂了什么是梯度,下面我们就来聊聊梯度下降是什么。
step4:现在我们先假设我们自己就是一个球,呆在图中的红点处,我们的目标是到绿点处,该怎么走呢?
很简单,顺着坡向下走就行了。现在球在(2,4)点处,这一点的倾斜程度是4,向右上方陡峭,接下来要做的就是向山下走。
step5:那么每一次走多远呢?
先小心一点,按当前倾斜程度的1%向下走。也就是 x n e w x_{new} xnew = x 0 x_0 x0 - 0.01*4, x n e w x_{new} xnew = 1.96, y n e w y_{new} ynew = 3.8416<4。小球成功的往下滚了一点,这样一直滚下去,最终就会滚到绿色的点,如下图
红色的曲线表示了小球的滚动路线。
梯度下降法转换成数学语言就是在每一次迭代按照一定的学习率α沿梯度的反方向更新参数,直至收敛,公式
θ t + 1 = θ t − α d f d θ \theta _{t+1} = \theta _{t}-\alpha \frac{df}{d\theta } θt+1=θt−αdθdf
接下来我们回到房价预测问题上。
step1:
y p , i = a x i + b l o s s = 1 2 m ∑ i = 1 m ( y p , i − y i ) 2 y_{p,i} = ax_i + b \qquad \qquad loss = \frac{1}{2m}\sum_{i=1}^{m}(y_{p,i}-y_i)^2 yp,i=axi+bloss=2m1i=1∑m(yp,i−yi)2
step2:将上面两个方程合并,并把1/2放到方程右边
l o s s = 1 m ∑ i = 1 m 1 2 ( a x i + b − y i ) 2 loss = \frac{1}{m}\sum_{i=1}^{m}\frac{1}{2}(ax_i + b-y_i)^2 loss=m1i=1∑m21(axi+b−yi)2
一共有m项累加,我们单拿出来一项来分析。
l o s s i = 1 2 ( a x i + b − y i ) 2 loss_i = \frac{1}{2}(ax_i + b-y_i)^2 lossi=21(axi+b−yi)2
step3:要优化的参数有两个,分别是a和b,我们分别对他们求微分,也就是偏微分
∂ l o s s i ∂ a = ( a x i + b − y i ) x i ∂ l o s s i ∂ b = a x i + b − y i \frac{\partial loss_i}{\partial a} = (ax_i+b-y_i)x_i \qquad \qquad \frac{\partial loss_i}{\partial b} = ax_i+b-y_i ∂a∂lossi=(axi+b−yi)xi∂b∂lossi=axi+b−yi
这里我们看到了loss函数为什么要在前面加一个1/2,目的就是在求偏微分的时候,可以把平方项中和掉,方便后面的计算。
step4:自然地我们将每一个 ∂ l o s s i ∂ a \frac{\partial loss_i}{\partial a} ∂a∂lossi和 ∂ l o s s i ∂ b \frac{\partial loss_i}{\partial b} ∂b∂lossi累加起来得到
∂ l o s s i ∂ a = 1 m ∑ i = 1 m ∂ l o s s i ∂ a ∂ l o s s i ∂ b = 1 m ∑ i = 1 m ∂ l o s s i ∂ b \frac{\partial loss_i}{\partial a} =\frac{1}{m}\sum_{i=1}^{m} \frac{\partial loss_i}{\partial a} \qquad \qquad \frac{\partial loss_i}{\partial b} = \frac{1}{m}\sum_{i=1}^{m}\frac{\partial loss_i}{\partial b} ∂a∂lossi=m1i=1∑m∂a∂lossi∂b∂lossi=m1i=1∑m∂b∂lossi
step5: ∂ l o s s i ∂ a \frac{\partial loss_i}{\partial a} ∂a∂lossi记为 ▽ a \bigtriangledown a ▽a, ∂ l o s s i ∂ b \frac{\partial loss_i}{\partial b} ∂b∂lossi记为 ▽ b \bigtriangledown b ▽b,分别表示loss在a、b方向的梯度,更新参数的方式如下
a n e w = a − α ▽ a b n e w = b − α ▽ b a_{new} = a - \alpha ▽a \qquad \qquad b_{new} = b - \alpha ▽ b anew=a−α▽abnew=b−α▽b
写了这么多公式,是时候直观的看一看梯度下降法是怎么一回事了。下面将绘制四幅图,分别是
我们看到图1和之前二次函数的那个例子很像,只不过是在三维空间内的一个曲面,初始的参数选择a=10,b=10 ,可以看到图1上曲面右侧有一个浅浅的点,就是初始值了。图二是等高线图,俯视更加明显,等高线图主要是为了之后训练的过程中可视化更清晰。图三上方的绿线是根据选择的初始值绘制的,下方是真实的实验数据,可以看出差距很远,需要优化的步骤还很多。将学习率α设置为0.01, 经过200次迭代,结果如下图
图一和图二都可以很直观的看到loss的减小。图三也从模型上给出了最终逼近的过程。图四可以看出下降还是很快的。
值得注意的是,不同的学习率对算法的收敛速度影响很大,下图是α=0.2的结果
基本在前10次迭代就快速收敛。
但是如果学习率设置的太大的话,很容易造成发散。说白了就是步子迈的太大了,一步迈到对面更高的山坡上去了,结果越迈越高,最后就不知道跑到哪里去了,如下图(α=0.3)
所以梯度下降算法中选取适当的学习速率很重要:学习速率过小时,虽然可以收敛,但是收敛速度慢,而过大时导致训练震荡,而且可能会发散。如图所示
理想的学习速率是:
输入参数:rate, x → \overrightarrow{x} x, y → \overrightarrow{y} y,scope
============> rate为设定的学习率
============> x → \overrightarrow{x} x为给定的模拟数据
============> x取值范围
============> scope 步长范围
输出参数:a,b,loss
1):初始化a,b
2):for i in len(x)
A:更新x的值: x[i] = (x[i] - x_min)/(x_max - x_min)
B:更新y的值: y[i] = (y[i] - y_min)/(y_max - y_min)
3):for step in scope
\qquad :for i in len(x)
\qquad \qquad A:累加da:all_da = all_da+ da(i)
\qquad \qquad B:累加db:all_db = all_db+ db(i)
\qquad A:更新a旳值:a = a - rate × all_da
\qquad B:更新b旳值:b = b - rate × all_db
4)end
理想的梯度下降算法要满足两点:
2. 收敛速度要快;
3. 能全局收敛
为了这个理想,出现了很多经典梯度下降算法的变种,下面有时间将分别介绍它们。
代码地址:https://github.com/admin110/s0/blob/master/gradientDescent.py
上一篇:梯度下降法(Gradient Descent)优化函数的详解(0)线性回归问题
下一篇:梯度下降法(Gradient Descent)优化函数的详解(2)随机梯度下降法(SGD Stochastic Gradient Descent)