3

优化算法系列(1):梯度下降算法与推导

 2 years ago
source link: https://allenwind.github.io/blog/8312/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

优化算法系列(1):梯度下降算法与推导

深度学习(机器学习)算法 = 模型表征 + 模型评估 + 优化算法,而基本上所有的机器学习算法都在损失函数下转化为某种形式的优化问题,可以说模型训练就是一个数值优化过程。

当前,常见的深度学习优化算法大部分都是在梯度下降算法的思路上改进。可以说,梯度下降算法是优化算法的基础。本文打算从若干思路理解梯度下降算法,以便对机器学习的优化过程有更深刻的理解。

此外,还有组合优化中涉及到的算法,如模拟退火、遗传算法、蚁群算法等,它们不能在深度学习上流行的大概率原因是效率。基于梯度思想的二价优化算法同样也是效率和计算问题的原因并没有在深度学习中流行起来。

假设θ=(θ1,…,θn),那么多元函数L(θ)的梯度可以表示为,

∇θL(θ)=(∂L∂θ1,…,∂L∂θn)

有些书籍上会写成这种形式,

∇xf(x)=[∂f(x)∂x1,∂f(x)∂x2,…,∂f(x)∂xd]⊤

本质上是一致的,只不过在不同的数学符号环境下的不同形式而已。

当n=3时,还可以如下表示,

∇θL(θ)=∂L∂θ1i+∂L∂θ2j+∂L∂θ3k

对于每个分量,

∂L∂θi=limΔθ→0L(θi+Δθ)−L(θi)Δθ

以上就是梯度的简单介绍。当然,在实践中,深度学习框架由于涉及复杂函数的梯度,一般会使用自动微分的方式,可查阅相关资料,如Tensorflow的官方文档。

梯度下降算法

首先我们还是来谈谈梯度下降算法的使用场景。传统的机器学习算法的优化离不开梯度下降算法,就连深度学习场景,很多优化器都是以梯度下降算法作为基础而衍生。

损失函数用来度量一次预测的代价或差异,假设有样本 (x,y) ,那么损失可以表示为 L(y,fθ(x)),θ 为模型 f 的参数。如果有训练样本数据集 D=(x1,y1),…,(xn,yn) ,那么整体的损失为

L(θ)=1|D|∑(x,y)∈DL(y,fθ(x))

使用梯度下降算法求解参数 θ ,如下

θn+1=θn−γ∇θL(θn)

如果每次计算整体损失 L(θ) 只从 D​ 中选出一个样本,那么优化过程称为随机梯度下降。 如果每次只取部分(批量),则称为批量梯度下降。随机梯度下降、批量梯度下降本质上都是通过部分样本来估计梯度,这也就是随机的本意。

梯度下降的导出 (思路1)

从优化角度看,全局最优点 θ∗ 处一定有

dL(θ∗)dθ∗=0

使用假设法容易证明这一点。然而,通常情况下 θn 难以直接求解,我们需要迭代的方法逐步逼近它。假定有一系列的变量:θ0,θ1,…,θn ,满足

L(θ0)>L(θ1)>...>L(θ∗)

更一般地,可以表示为

L(θt)>L(θt+1)

其中 t=0,1,2,3,… 可以化为如下形式

L(θt+1)−L(θt)<0

损失函数L一阶连续可微(具体的数学性质取决于我们选择的损失函数 L),使用泰勒公式有

L(θt+1)=L(θt+Δθ)≈L(θt)+ΔθT∇θL(θt)

把上式代入到(2.4)中,有

Δθ⊤∇θL(θt)<0

选择恰当的 γ>0,只需要取

Δθ=−γ∇θL(θt)

此处γ>0就是我们所谓的学习率,在凸优化中γ可以通过一维搜索确定,但是深度学习应用中,通常是重要的炼丹参数,需要根据个人经验调整。结合(2.5)中的 θt+1=θt+Δθ,有

θt+1=θt−γ∇θL(θt)

这就是我们所说的梯度下降算法。如果优化的目标函数是凸函数,那么局部极小点为全局最小点,但是如果目标函数非凸,梯度下降无法保证全局最优。以上的推导有点冗余,但看起来还是相当清晰。

梯度下降的导出(思路2)

从整个模型训练过程看,参数的取值可以看作是步数的函数,即,考虑优化过程的损失 θ(t),那么损失函数可以表示为 L(θ(t))。优化的目标是期望L(θ(t))以最快的速度下降。根据链式法则有

dL(θ(t))dt=dL(θ)dθdθ(t)dt

要使L(θ(t))​下降最快,要求上式越小越好。上述可以改为如下形式,

dL(θ(t))dt=dL(θ)dθdθ(t)dt=|dL(θ)dθ||dθ(t)dt|cosα

为让损失最大,要求 α=2π ,于是有

dθ(t)dt=−γ∇θL(θt)

这个思路相当几何化。

在机器学习中,γ>0 称为学习率。此式就是我们所说的梯度下降法。此外,其收敛速度也不是最快的。当n足够大时,θn 足够接近 θn,根据以上推导,我们可以设计如下算法,

θn+1=θn−γ∇θL(θn)

梯度下降的导出(思路3)

以上两种思路都是从一阶出发,那么能不能从二阶出发来逼近原函数,并从中导出梯度下降思路。首先我们对原始函数进行二阶泰勒展开,即通过抛物线来局部逼近原函数,由于计算过程设计到 hessian 矩阵求逆,自然地, 我们会把二次部分取常数。

我们使用抛物线来局部逼近函数 f(x) ,使用二价泰勒展开

f(x)≈f(xn)+f′(xn)(x−xn)+12f′′(xn)(x−xn)2=h(x)

不难求出抛物线的极值点的迭代形式,

xn+1=xn−f′(xn)f′′(xn)

事实上,这种思路和思路(1)类似,只不过使用了二价泰勒级数展开。这就是牛顿法的迭代公式,可以参考历史文章牛顿迭代法的导出。令α=1f″(x),有

xn+1=xn−αf′(xn)

这里的α可以理解为步速因子,即以多大的速度更新xn​。牛顿法则是使用f″(x)的倒数来控制步速。为化简步速,我们把它改为常数也可以,

xn+1=xn−γf′(xn)

推广到一般形式就是,

xn+1=xn−γ∇xf(x)

于是得到梯度下降的一般形式。

梯度下降算法在深度学习中有个致命的缺点,就是每个都使用全量的数据估算梯度,即

∇θL(θ)=∇θ[1|D|∑(x,y)∈DL(y,fθ(x))]

每一轮的迭代都要对上万甚至百万的样本计算梯度,这个计算力是支撑不起的,即便计算里足够,也要消耗巨大的内存(显存)。

以上我们谈了梯度下降算法的三种导出(理解)思路。这三种思路均在欧几里得空间上的推导,其实梯度下降算法并不止于欧几里得空间,还可以是黎曼空间。有兴趣的读者可以查阅相关文献。同时也指出单纯的GD方案消耗非常大的计算力且耗费内存(显存)。下篇深入分析GD的改进版本SGD。

[1] How Does Batch Normalization Help Optimization?

[2] https://tensorflow.google.cn/api_docs/python/tf/keras/optimizers/Optimizer

[3] https://tensorflow.google.cn/api_docs/python/tf/keras/optimizers


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK