无约束优化算法-第二节:梯度类算法

Posted 快乐江湖

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了无约束优化算法-第二节:梯度类算法相关的知识,希望对你有一定的参考价值。

文章目录

梯度类算法:梯度类算法本质是使用函数的一阶导数信息选取下降方向 d k d^k dk,这其中最基本的算法是梯度下降法,也即直接选择负梯度作为下降方向 d k d^k dk,此外还有BB方法,是一种梯度法的变形,虽然理论性质目前仍不完整,但由于它有优秀的数值表现,也是在实际应用中使用较多的一种算法

一:梯度下降法

(1)梯度下降法概述

梯度下降法(Gradient descent,GD):使用梯度下降法寻找函数极小值时,会沿着当前点对应梯度(或近似梯度)的反方向 d d d所规定的步长 α \\alpha α内进行迭代搜索。当然如果沿着梯度正方向搜索,就会接近函数的局部最大值,此时对应梯度上升法

我们经常会用下山这个例子来理解梯度下降法:现在你可以想象自己站在一座高山上的某一位置,需要下山,那么此时最快的下山策略就是环顾四周、哪里最陡峭就沿着哪个方向下山,每到一个新的地方后再次执行这个策略

  • 在机器学习中,上面的初始位置就相当于损失函数的初始值,山体的陡峭程度则是梯度,对应于损失函数的导数后偏导数

可以看出梯度下降有时得到的是局部最优解,如果损失函数是凸函数,梯度下降法得到的解就是全局最优解

因此,梯度下降法公式为

θ i = θ i − α ∂ J ( θ 0 , θ 1 , . . . , θ n ) ∂ θ i \\theta_i=\\theta_i-\\alpha \\frac\\partial J(\\theta_0,\\theta_1,...,\\theta_n)\\partial \\theta_i θi=θiαθiJ(θ0,θ1,...,θn)

(2)梯度下降法求解步骤

梯度下降法求解步骤:如下

  • 确定当前位置的损失函数梯度,对于 θ i \\theta_i θi,其梯度表达式为 ∂ J ( θ 0 , θ 1 , . . . , θ n ) ∂ θ i \\frac\\partial J(\\theta_0,\\theta_1,...,\\theta_n)\\partial \\theta_i θiJ(θ0,θ1,...,θn)
  • 用步长乘以损失函数梯度,得到当前位置下降的距离,也即 α ∂ J ( θ 0 , θ 1 , . . . , θ n ) ∂ θ i \\alpha \\frac\\partial J(\\theta_0,\\theta_1,...,\\theta_n)\\partial \\theta_i αθiJ(θ0,θ1,...,θn)
  • 确定是否所有的 θ i \\theta_i θi梯度下降的距离都小于 ξ \\xi ξ,如果小于则算法终止,当前所有的 θ i \\theta_i θi即为最终结果。否则转入下一步
  • 更新所有的 θ i \\theta_i θi,即 θ i = θ i − α ∂ J ( θ 0 , θ 1 , . . . , θ n ) ∂ θ i \\theta_i=\\theta_i-\\alpha \\frac\\partial J(\\theta_0,\\theta_1,...,\\theta_n)\\partial \\theta_i θi=θiαθiJ(θ0,θ1,...,θn),更新完毕后转入第一步

(3)Python实现

  • 注意 a l p h a alpha alpha的选择可以参照前文,这里固定 a l p h a alpha alpha为0.01
import numpy as np
import torch
from sympy import *

# 计算梯度函数
def cal_grad_funciton(function):
    res = []
    x = []
    x.append(Symbol('x1'))
    x.append(Symbol('x2'))
    for i in range(len(x)):
        res.append(diff(function, x[i]))
    return res

# 定义目标函数
def function_define():
    x = []
    x.append(Symbol('x1'))
    x.append(Symbol('x2'))
    # y = 2 * (x[0] - x[1] ** 2) ** 2 + (1 + x[1]) ** 2
    # Rosenbrock函数
    y = 100 * (x[1] - x[0] ** 2) ** 2 + (1 - x[0]) ** 2
    
    return y

# 计算函数返回值
def cal_function_ret(function, x):
    res = function.subs([('x1', x[0]), ('x2', x[1])])
    return res

# 计算梯度
def cal_grad_ret(grad_function, x):
    res = []
    
    for i in range(len(x)):
        res.append(grad_function[i].subs([('x1', x[0]), ('x2', x[1])]))
    return res

def norm(x):
    return sqrt(np.dot(x, x))

def gradient_descent(function, grad_function, x):
    k = 1
    
    d = cal_grad_ret(grad_function, x)
    d = np.dot(-1, d).tolist()
    alpha = 0.01
    while norm(d) > 0.00001 and k < 1000:
        d = cal_grad_ret(grad_function, x)
        d = np.dot(-1, d).tolist()
        # armijo_goladstein准则选择步长
        # alpha = armijo_goldstein(function, grad_function, x, d)
        # armijo_wlofe准则选择步长
        # alpha = armijo_wlofe(function, grad_function, x, d)
        x = np.add(x, np.dot(alpha, d))
        k = k + 1
    
    # 返回最小值点,函数最小值和迭代次数
    return x, cal_function_ret(function, x), k


if __name__ == '__main__':
    function = function_define()
    grad_function = cal_grad_funciton(function)
    print("函数为:", function)
    print("梯度函数为:", grad_function)

    x0 = [-10, 10]
    Min, MinValue, Iterator = gradient_descent(function, grad_function, x0)
    print("最小值点为:", Min)
    print("最小值为:", MinValue)
    print("迭代次数为:", Iterator)

(4)常见梯度下降算法

A:全梯度下降算法(FGD)

全梯度下降算法(FGD):计算训练集所有样本误差,对其求和再取平均值作为目标函数。权重向量沿其梯度相反的方向移动,从而使当前目标函数减少得最多。因为在执行每次更新时,需要在整个数据集上计算所有的梯度,所以速度会很慢,同时,其在整个训练数据集上计算损失函数关于参数θ的梯度

θ = θ − η ⋅ ∇ θ J ( θ ) \\theta = \\theta -\\eta \\cdot \\nabla_\\thetaJ(\\theta) θ=θηθJ(θ)

B:随机梯度下降算法(SGD)

随机梯度下降算法(SGD):由于FGD每迭代更新一次权重都需要计算所有样本误差,而实际问题中经常有上亿的训练样本,故效率偏低,且容易陷入局部最优解,因此提出了随机梯度下降算法。其每轮计算的目标函数不再是全体样本误差,而仅是单个样本误差,即每次只代入计算一个样本目标函数的梯度来更新权重,再取下一个样本重复此过程,直到损失函数值停止下降或损失函数值小于某个设定的阈值。此过程简单,高效,通常可以较好地避免更新迭代收敛到局部最优解。其迭代形式为

θ = θ − η ⋅ ∇ θ J ( θ ; x ( i ) ; y ( i ) ) \\theta = \\theta -\\eta \\cdot \\nabla_\\thetaJ(\\theta;x^(i);y^(i)) θ=θηθJ(θ;x(i);y(i))

  • x ( i ) x^(i) x(i):表示一条训练样本的特征值
  • x ( i ) x^(i) x(i):表示一条训练样本的标签值

C:小批量梯度下降算法

小批量梯度下降算法:小批量梯度下降算法是FG和SG的折中方案,在一定程度上兼顾了以上两种方法的优点。每次从训练样本集上随机抽取一个小样本集,在抽出来的小样本集上采用FGD迭代更新权重。被抽出的小样本集所含样本点的个数称为batch_size,通常设置为2的幂次方,更有利于GPU加速处理

  • batch_size=1,则变成了SGD
  • batch_size=n,则变成了FGD

θ = θ − η ⋅ ∇ θ J ( θ ; x ( i : i + n ) ; y ( i : i + n ) ) \\theta = \\theta -\\eta \\cdot \\nabla_\\thetaJ(\\theta;x^(i:i+n);y^(i:i+n)) θ=θη无约束优化算法-第三节:次梯度类算法

无约束优化问题

运筹学(最优化理论)学习笔记 | 共轭梯度法

最优化算法

梯度下降无约束最优化问题

无约束梯度算法