梯度下降法

梯度下降

梯度下降(Gradient Descent)又称最速下降(steepest descent),是求解无约束最优化问题的一种常用方法,梯度下降法是一种迭代算法,每一步都需要求解目标函数的梯度向量
假设f(x)f(x)f(x)RnR^nRn上具有一阶连续偏倒数的函数,要求解以下无约束最优化问题:
min⁡x∈Rnf(x) \min_{x \in R^n} f(x) xRnminf(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),通过不断迭代来更新xxx的值,进行目标函数的极小化,直到收敛。由于负梯度方向是使函数值下降最快的方向,在迭代的每一步,以负梯度方向更新xxx的值,从而达到减少函数值的目的。

由于f(x)f(x)f(x)具有一阶连续偏导数,若第kkk次迭代值为x(k)x^{(k)}x(k),则可将f(x)f(x)f(x)x(k)x^{(k)}x(k)附近进行一阶泰勒展开:
f(x)=f(x(k))+gkT(x−x(k)) f(x)=f(x^{(k)})+g_k^T(x-x^{(k)}) f(x)=f(x(k))+gkT(xx(k))
上式中的gk=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+1k+1k+1次的迭代值x(k+1)x^{(k+1)}x(k+1)可有以下方式获得:
x(k+1)←x(k)+λkpk x^{(k+1)} \leftarrow x^{(k)} + \lambda_k p_k x(k+1)x(k)+λkpk
上式中,pkp_kpk 是搜索方向,取负梯度方向pk=−∇f(x(k))p_k = -\nabla f(x^{(k)})pk=f(x(k))λk\lambda_kλk是步长,由一维搜索确定,即λk\lambda_kλk使得
f(x(k)+λkpk)=min⁡λ≥0f(x(k)+λpk) 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)∈Rnx^{(0)} \in R^nx(0)Rn,令k=0k=0k=0
(2) 计算f(x(k))f(x^{(k)})f(x(k))
(3) 计算梯度gk=g(x(k))g_k=g(x^{(k)})gk=g(x(k)),当∣∣gk<ϵ∣∣||g_k < \epsilon||gk<ϵ时,停止迭代,并令x∗=x(k)x^* = x^{(k)}x=x(k);否则,令pk=−g(x(k))p_k = -g(x^{(k)})pk=g(x(k)),求λk\lambda_kλk,使
f(x(k)+λkpk)=min⁡λ≥0f(x(k)+λpk) 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)+λkpkx^{(k+1)} = x^{(k)} + \lambda_k p_kx(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)})|| < \epsilonf(x(k+1))f(x(k))<ϵ∣∣x(k+1)−x(k)∣∣<ϵ||x^{(k+1)}-x^{(k)}||<\epsilonx(k+1)x(k)<ϵ时,停止迭代,并令x∗=x(k+1)x^* = x^{(k+1)}x=x(k+1)
(5) 否则,令k=k+1k = k+1k=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)(x1)(x+2)(x2)

f(x)f(x)f(x) 求导可得:

f′(x)=4x3−10x f'(x)=4x^3-10x f(x)=4x310x

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)=x3−y3+3x2+3y2−9x f ( x , y ) = x ^ { 3 } - y ^ { 3 } + 3 x ^ { 2 } + 3 y ^ { 2 } - 9 x f(x,y)=x3y3+3x2+3y29x

xxx求偏导数:

∂f∂x=3x2+6x−9 \frac{\partial f}{\partial x}=3x^2+6x-9 xf=3x2+6x9

yyy求偏导数:

∂f∂y=−3y2+6y \frac{\partial f}{\partial y}=-3y^2+6y yf=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] 李航. 统计学习方法.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

great-wind

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值