梯度下降
梯度下降(Gradient Descent)又称最速下降(steepest descent),是求解无约束最优化问题的一种常用方法,梯度下降法是一种迭代算法,每一步都需要求解目标函数的梯度向量。
假设
f
(
x
)
f(x)
f(x)是
R
n
R^n
Rn上具有一阶连续偏倒数的函数,要求解以下无约束最优化问题:
min
x
∈
R
n
f
(
x
)
\min_{x \in R^n} f(x)
x∈Rnminf(x)
令
x
∗
x^*
x∗表示要求解的目标函数
f
(
x
)
f(x)
f(x)的极小点,即,目标函数
f
(
x
)
f(x)
f(x)在
x
∗
x^*
x∗处能够取得极小值。
梯度下降法是一种迭代算法。首先选取适当的初始值 x ( 0 ) x^{(0)} x(0),通过不断迭代来更新 x x x的值,进行目标函数的极小化,直到收敛。由于负梯度方向是使函数值下降最快的方向,在迭代的每一步,以负梯度方向更新 x x x的值,从而达到减少函数值的目的。
由于
f
(
x
)
f(x)
f(x)具有一阶连续偏导数,若第
k
k
k次迭代值为
x
(
k
)
x^{(k)}
x(k),则可将
f
(
x
)
f(x)
f(x)在
x
(
k
)
x^{(k)}
x(k)附近进行一阶泰勒展开:
f
(
x
)
=
f
(
x
(
k
)
)
+
g
k
T
(
x
−
x
(
k
)
)
f(x)=f(x^{(k)})+g_k^T(x-x^{(k)})
f(x)=f(x(k))+gkT(x−x(k))
上式中的
g
k
=
g
(
x
(
k
)
)
=
∇
f
(
x
(
k
)
)
g_k=g(x^{(k)})=\nabla f(x^{(k)})
gk=g(x(k))=∇f(x(k))为
f
(
x
)
f(x)
f(x)在点
x
(
k
)
x^{(k)}
x(k)处的梯度。
第
k
+
1
k+1
k+1次的迭代值
x
(
k
+
1
)
x^{(k+1)}
x(k+1)可有以下方式获得:
x
(
k
+
1
)
←
x
(
k
)
+
λ
k
p
k
x^{(k+1)} \leftarrow x^{(k)} + \lambda_k p_k
x(k+1)←x(k)+λkpk
上式中,
p
k
p_k
pk 是搜索方向,取负梯度方向
p
k
=
−
∇
f
(
x
(
k
)
)
p_k = -\nabla f(x^{(k)})
pk=−∇f(x(k)),
λ
k
\lambda_k
λk是步长,由一维搜索确定,即
λ
k
\lambda_k
λk使得
f
(
x
(
k
)
+
λ
k
p
k
)
=
min
λ
≥
0
f
(
x
(
k
)
+
λ
p
k
)
f(x^{(k)} + \lambda_k p_k) = \min_{\lambda \geq 0} f(x^{(k)} + \lambda p_k)
f(x(k)+λkpk)=λ≥0minf(x(k)+λpk)
梯度下降法具体步骤
梯度下降法具体步骤如下:
输入:目标函数
f
(
x
)
f(x)
f(x),梯度函数
g
(
x
)
=
∇
f
(
x
)
g(x) = \nabla f(x)
g(x)=∇f(x),计算精度
ϵ
\epsilon
ϵ;
输出:
f
(
x
)
f(x)
f(x)的极小值点
x
∗
x^*
x∗。
(1) 取初始值
x
(
0
)
∈
R
n
x^{(0)} \in R^n
x(0)∈Rn,令
k
=
0
k=0
k=0。
(2) 计算
f
(
x
(
k
)
)
f(x^{(k)})
f(x(k))。
(3) 计算梯度
g
k
=
g
(
x
(
k
)
)
g_k=g(x^{(k)})
gk=g(x(k)),当
∣
∣
g
k
<
ϵ
∣
∣
||g_k < \epsilon||
∣∣gk<ϵ∣∣时,停止迭代,并令
x
∗
=
x
(
k
)
x^* = x^{(k)}
x∗=x(k);否则,令
p
k
=
−
g
(
x
(
k
)
)
p_k = -g(x^{(k)})
pk=−g(x(k)),求
λ
k
\lambda_k
λk,使
f
(
x
(
k
)
+
λ
k
p
k
)
=
min
λ
≥
0
f
(
x
(
k
)
+
λ
p
k
)
f(x^{(k)} + \lambda_k p_k) = \min_{\lambda \geq 0} f(x^{(k)} + \lambda p_k)
f(x(k)+λkpk)=λ≥0minf(x(k)+λpk)
(4) 令
x
(
k
+
1
)
=
x
(
k
)
+
λ
k
p
k
x^{(k+1)} = x^{(k)} + \lambda_k p_k
x(k+1)=x(k)+λkpk,计算
f
(
x
(
k
)
)
f(x^{(k)})
f(x(k)),当
∣
∣
f
(
x
(
k
+
1
)
)
−
f
(
x
(
k
)
)
∣
∣
<
ϵ
||f(x^{(k+1)})- f(x^{(k)})|| < \epsilon
∣∣f(x(k+1))−f(x(k))∣∣<ϵ或
∣
∣
x
(
k
+
1
)
−
x
(
k
)
∣
∣
<
ϵ
||x^{(k+1)}-x^{(k)}||<\epsilon
∣∣x(k+1)−x(k)∣∣<ϵ时,停止迭代,并令
x
∗
=
x
(
k
+
1
)
x^* = x^{(k+1)}
x∗=x(k+1);
(5) 否则,令
k
=
k
+
1
k = k+1
k=k+1,转至步骤(3)。
当目标函数是凸函数时,梯度下降法的解是全局最优解。一般情况下,其解不保证是全局最优解。梯度下降法的收敛速度也未必是最快的。
示例1-求解一元函数极小值
一元函数 f ( x ) f(x) f(x) 为:
f ( x ) = ( x + 1 ) ( x − 1 ) ( x + 2 ) ( x − 2 ) f(x)=(x+1)(x-1)(x+2)(x-2) f(x)=(x+1)(x−1)(x+2)(x−2)
对 f ( x ) f(x) f(x) 求导可得:
f ′ ( x ) = 4 x 3 − 10 x f'(x)=4x^3-10x f′(x)=4x3−10x
def f(x):
"""
原函数
"""
return (x+1)*(x-1)*(x+2)*(x-2)
def df(x):
"""
导函数
"""
return 4*x**3-10*x
lr = 0.001
x = -3
for i in range(1000):
x -= lr*df(x) # 迭代
if i%100==0:
print("epoch:{},x:{}".format(i,x))
print("epoch:{},x:{}".format(i,x))
输出如下:
epoch:0,x:-2.922
epoch:100,x:-1.6594568957100684
epoch:200,x:-1.5908783935416804
epoch:300,x:-1.5824199959582812
epoch:400,x:-1.5813085551214408
epoch:500,x:-1.5811613357358625
epoch:600,x:-1.5811418147173184
epoch:700,x:-1.5811392259039174
epoch:800,x:-1.5811388825776078
epoch:900,x:-1.5811388370458432
epoch:999,x:-1.581138831026283
示例2-求解二元函数极小值
求解二元函数 f ( x , y ) f ( x , y ) f(x,y)的极小值:
f ( x , y ) = x 3 − y 3 + 3 x 2 + 3 y 2 − 9 x f ( x , y ) = x ^ { 3 } - y ^ { 3 } + 3 x ^ { 2 } + 3 y ^ { 2 } - 9 x f(x,y)=x3−y3+3x2+3y2−9x
对 x x x求偏导数:
∂ f ∂ x = 3 x 2 + 6 x − 9 \frac{\partial f}{\partial x}=3x^2+6x-9 ∂x∂f=3x2+6x−9
对 y y y求偏导数:
∂ f ∂ y = − 3 y 2 + 6 y \frac{\partial f}{\partial y}=-3y^2+6y ∂y∂f=−3y2+6y
def f(x,y):
"""
参数:
x -- x 的值
y -- y 的值
返回:
v -- 当取 x, y 时,该多元函数的值
"""
v = x**3-y**3+3*x**2+3*y**2-9*x
return v
def dx(x, y):
"""
x的偏导数
参数:
x -- x 的值
y -- y 的值
返回:
v -- 当取 x, y 时,该多元函数关于 x 的偏导的值
"""
v = 3*x**2+6*x-9
return v
def dy(x, y):
"""
y的偏导数
参数:
x -- x 的值
y -- y 的值
返回:
v -- 当取 x, y 时,该多元函数关于 y 的偏导的值
"""
v = -3*y**2+6*y
return v
def df(x,y):
"""
f(x,y)的导数
"""
return dx(x, y),dy(x, y)
def gradient_descent(x, y, f, dx, dy, lr, max_iter):
"""
梯度下降法求解二元函数极小值点的计算函数
参数:
x -- 初始变量 x 的值
y -- 初始变量 y 的值
f -- 该数学函数所定义的 Python 函数
dx -- 函数 f 关于 x 的偏导数,Python 函数
dy -- 函数 f 关于 y 的偏导数,Python 函数
lr -- 学习率,即参数更新速度
max_iter -- 最大迭代次数
返回:
x -- 极小值点对应的 x 的值
y -- 极小值点对应的 y 的值
v -- 极小值点的值
"""
for i in range(max_iter):
x -= lr*dx(x,y)
y -= lr*dy(x,y)
v = f(x,y)
return x, y, v
import numpy as np
np.random.seed(10) # 设置随机数种子
# 初始点和学习率
x = np.random.randn(1)
y = np.random.randn(1)
lr = 0.1
max_iter = 1000
gradient_descent(x, y, f, dx, dy, lr, max_iter)
输出如下:
(array([1.]), array([0.]), array([-5.]))
参考:
[1] 李航. 统计学习方法.