代码编织梦想

1. 梯度下降法的引入和介绍

我们之前已经定义了代价函数 J ( θ ) J(\theta) J(θ),在实现我们的优化目标            θ m i n i m i z e \large_{\;\;\;\;\;\theta}^{minimize} θminimize J ( θ ) J(\theta) J(θ)时,我们希望通过一种高效的、软件可实现的算法,来自动找寻代价函数 J ( θ ) J(\theta) J(θ)的最小值对应的参数 θ \theta θ

所以我们引入可以将代价函数 J ( θ ) J(\theta) J(θ)最小化的梯度下降法,它不仅被用在线性回归问题上,还被广泛运用于机器学习的诸多领域。
问题描述
上图是一个简单的问题描述,假设现在我们有一个代价函数 J ( θ 0 , θ 1 ) J(\theta_0,\theta_1) J(θ0,θ1),我们可以将它对应于之前介绍的线性回归模型,我们希望通过一种算法来最小化代价函数 J ( θ 0 , θ 1 ) J(\theta_0,\theta_1) J(θ0,θ1)。当然,我们也可以将问题推广到一般情况上,例如 J ( θ 0 , θ 1 , … … , θ n ) J(\theta_0,\theta_1,……,\theta_n) J(θ0,θ1,……,θn),此时,我们的优化目标就是 θ 0 , θ 1 , … , θ n   m i n i m i z e \large_{\theta_0,\theta_1,…,\theta_n}^{\,minimize} θ0,θ1,,θnminimize J ( θ 0 , θ 1 , … … , θ n ) J(\theta_0,\theta_1,……,\theta_n) J(θ0,θ1,……,θn),但为了简洁起见,我们先介绍参数较少时的情况。

下面就是梯度下降的思路:首先,我们要给定参数 θ 0 , θ 1 \theta_0,\theta_1 θ0,θ1的初始值,通常的选择是将 θ 0 设为 0 \theta_0设为0 θ0设为0,将 θ 1 设为 0 \theta_1设为0 θ1设为0;然后,我们要不断改变 θ 0 , θ 1 \theta_0,\theta_1 θ0,θ1使 J ( θ 0 , θ 1 ) J(\theta_0,\theta_1) J(θ0,θ1)减小直到我们找到 J ( θ 0 , θ 1 ) J(\theta_0,\theta_1) J(θ0,θ1)的最小值或者局部最小值。

接下来,我们通过一些图片来了解一下梯度下降是如何工作的
梯度下降
假设我们希望让上图中的代价函数最小化,我们将上面的图像想象成是一座座山,将最小化问题想象成是如何快速的下山,按照梯度下降的思路,我们首先要对参数进行初始化,这里的参数就相当于我们的坐标,也就是我们在山上的初始位置,那么,当我们在山上环顾四周时,我们朝哪个方向行进才能够快速地下山呢?梯度下降法就是来帮助我们解决这个问题的。

同时,要注意到梯度下降法的一个特点,当我们设定的参数初始值不同时,最后得到代价函数的最小值对应的参数取值可能会不同。简单来说,去爬过山的都清楚,有时候上山的路不只有一条,所以自然下山的路也不只一条,我们会选择走哪条路下山,往往取决于我们准备下山时所处的位置离哪条下山的路更近。 当然,在梯度下降里面,问题并没有这么简单,我们在之后还会讨论。

2. 梯度下降法的数学定义

梯度下降的数学定义
在梯度下降算法中,我们将会反复做这一步 θ j : = θ j − α ∂ ∂   θ j J ( θ 0 , θ 1 ) \theta_j:=\theta_j-\alpha{\large\frac {\partial} {\partial\,\theta_j}}J(\theta_0,\theta_1) θj:=θjαθjJ(θ0,θ1),直到收敛。

这个公式中有几点需要注意一下,首先,它使用 : = := :=来表示赋值,这是一个赋值运算符,如果我们使用 = = =,则表示判定相等;其次,我们称 α \alpha α为学习率, α \alpha α用来控制在梯度下降时,我们每次迈出多大的步子,所以如果 α \alpha α很大,那么梯度下降就会很快,反之如果 α \alpha α很小,那么梯度下降就会很慢,显然,如何设置学习率 α \alpha α也是一个问题,不过现在我们先不讨论它;最后,对于这个方程,你需要同时更新参数 θ 0 , θ 1 \theta_0,\theta_1 θ0,θ1

梯度下降
上图左侧是实现了同步更新的做法,可以看到,我们定义了两个临时变量 t e m p 0 temp0 temp0 t e m p 1 temp1 temp1来分别得到参数 θ 0 , θ 1 \theta_0,\theta_1 θ0,θ1的更新值,之后再一起进行赋值操作。而在右侧的做法中,我们在得到一个参数的更新值之后就立马更新了对应的参数,这样会导致我们在计算下一个参数的更新值时,微分项 ∂ ∂   θ j J ( θ 0 , θ 1 ) {\large\frac {\partial} {\partial\,\theta_j}}J(\theta_0,\theta_1) θjJ(θ0,θ1)的值发生变化,此时就不再是同步更新了,这种非同步的做法在一些时候也能够得到正确的结果,但右边的做法并不是我们所指的梯度下降法,这里要注意一下,其中会表现出微小的差别。

3. 梯度下降法的工作原理

为了更好地展示出梯度下降法的工作原理,我们对原来的代价函数再做进一步的简化,将参数的数量设置为一个,即 J ( θ 1 ) J(\theta_1) J(θ1),此时的目标函数就变为了            θ 1 m i n i m i z e \large_{\;\;\;\;\;\theta_1}^{minimize} θ1minimize J ( θ 1 ) J(\theta_1) J(θ1)

可以知道,此时代价函数 J ( θ 1 ) J(\theta_1) J(θ1)对应的函数图像是二维平面上的一条曲线,横轴表示参数 θ 1 \theta_1 θ1,纵轴表示 J ( θ 1 ) J(\theta_1) J(θ1)
代价函数图像
假设我们从图中的某一点出发(即设定的 θ 1 \theta_1 θ1初始值),此时更新方程中的微分项 ∂ ∂   θ 1 J ( θ 1 ) {\large\frac {\partial} {\partial\,\theta_1}}J(\theta_1) θ1J(θ1)就相当于该点处切线的斜率
更新过程
显然,在黑点处的切线斜率为正,所以根据更新方程 θ 1 : = θ 1 − α ∂ ∂   θ 1 J ( θ 1 ) \theta_1:=\theta_1-\alpha{\large\frac {\partial} {\partial\,\theta_1}}J(\theta_1) θ1:=θ1αθ1J(θ1)可知, θ 1 \theta_1 θ1会减去一个正数(学习率 α \alpha α是正数)导致更新值小于原始值,从图像上看, θ 1 \theta_1 θ1会向左下移动到绿点处,也就是在逼近我们代价函数 J ( θ 1 ) J(\theta_1) J(θ1)的最小值。

前面,我们说到学习率 α \alpha α的设置问题,上面的更新过程应该让我们对学习率的影响有了一定的认识,接下来,我们讨论一下学习率设置过小或者过大时会导致哪些问题。
学习率的影响
从上面的图片中,我们可以很清楚的看出来,当学习率设置过小时,梯度下降每次只会移动一小步,导致收敛非常慢;而当学习率设置过大时,我们可以看到,参数会在最小值的附近反复横跳,这就可能会导致梯度无法收敛,甚至发散。
到达优化目标时
如上图所示,当参数的更新值刚好达到代价函数最小值或者局部最小值时,可知该点的切线会是一条水平线,即斜率为0,所以根据更新方程 θ 1 : = θ 1 − α ∂ ∂   θ 1 J ( θ 1 ) \theta_1:=\theta_1-\alpha{\large\frac {\partial} {\partial\,\theta_1}}J(\theta_1) θ1:=θ1αθ1J(θ1)可知, θ 1 \theta_1 θ1的值不会发生变化,也就是说,在接下来更新的过程中,不会再改变参数的值,这正是我们想要的,因为它使我们的解始终保持在局部最优点。

即使没有学习率
其实,即使学习率 α \alpha α是固定的,梯度下降法也可以收敛到局部最小值。
因为,当我们越来越接近最小值时,对应切线的斜率也就会越来越小,也就是说,移动的幅度会自动变得越来越小,这就是梯度下降的运行方式,所以说,我们没有必要再另外去减小学习率 α \alpha α,比如随时间减小学习率的做法。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/PL_hfc/article/details/130903312