(最优化理论与方法)第六章无约束优化算法-第二节:梯度类算法

news2024/11/15 14:07:09

文章目录

  • 一:次梯度算法
    • (1)次梯度算法结构
    • (2)应用举例-LASSO问题求解
  • 二:牛顿法
    • (1)经典牛顿法
    • (2)修正牛顿法
  • 三:拟牛顿法
    • (1)拟牛顿条件
    • (2)DFP算法

一:次梯度算法

对于梯度下降法,其前提是目标函数 f ( x ) f(x) f(x)是一阶可微的,但是在实际应用中经常会遇到不可微的函数,对于这类函数我们无法在每个点处求出梯度,但往往它们的最优值都是在不可微点处取到的,所以为了能够处理这种情形,本节介绍次梯度算法

(1)次梯度算法结构

假设 f ( x ) f(x) f(x)为凸函数,但不一定可微,考虑如下问题

m i n x f ( x ) \mathop{min}\limits_{x} f(x) xminf(x)

  • 一阶充要条件 x ∗ x^{*} x是一个全局极小点<=> 0 ∈ ∂ f ( x ∗ ) 0\in \partial f(x^{*}) 0f(x)
  • 因此可以通过计算凸函数的次梯度集合中包含 0 0 0的点来求解其对应的全局极小点

为了极小化一个不可微的凸函数 f f f,可类似梯度法构造如下次梯度算法的迭代格式

x k + 1 = x k − α k g k , g k ∈ ∂ f ( x k ) x^{k+1}=x^{k}-\alpha_{k}g^{k}, \quad g^{k}\in \partial f(x^{k}) xk+1=xkαkgk,gkf(xk)

其中 α k > 0 \alpha_{k}>0 αk>0,通常有如下4种选择方式

  • 固定步长 α k = α \alpha_{k}=\alpha αk=α
  • 固定 ∣ ∣ x k + 1 − x k ∣ ∣ ||x^{k+1}-x^{k}|| ∣∣xk+1xk∣∣,即 α k ∣ ∣ g k ∣ ∣ \alpha_{k}||g^{k}|| αk∣∣gk∣∣为常数
  • 消失步长 α k → 0 \alpha_{k} \rightarrow 0 αk0,且 ∑ k = 0 ∞ a k = + ∞ \sum\limits_{k=0}^{\infty}a_{k}=+\infty k=0ak=+
  • 选取 α k \alpha_{k} αk使其满足某种线搜索准则

(2)应用举例-LASSO问题求解

考虑LASSO问题:

m i n f ( x ) = 1 2 ∣ ∣ A x − b ∣ ∣ 2 + u ∣ ∣ x ∣ ∣ 1 min \quad f(x)=\frac{1}{2}||Ax-b||^{2}+u||x||_{1} minf(x)=21∣∣Axb2+u∣∣x1

容易得知 f ( x ) f(x) f(x)的一个次梯度为

g = A T ( A x − b ) + u s i g n ( x ) g=A^{T}(Ax-b)+usign(x) g=AT(Axb)+usign(x)

  • s i g n ( x ) sign(x) sign(x)是关于 x x x逐分量的符号函数

因此,LASSO问题的次梯度算法为

x k + 1 = x k − α k ( A T ( A x k − b ) + u s i g n ( x k ) ) x^{k+1}=x^{k}-\alpha_{k}(A^{T}(Ax^{k}-b)+usign(x^{k})) xk+1=xkαk(AT(Axkb)+usign(xk))

  • 步长 a k a_{k} ak可选为固定步长或消失步长

如下,正则化参数 u = 1 u=1 u=1,分别选取固定步长 a k = 0.0005 a_{k}=0.0005 ak=0.0005, a k = 0.0002 a_{k}=0.0002 ak=0.0002, a k = 0.0001 a_{k}=0.0001 ak=0.0001以及消失步长 a k = 0.002 k a_{k}=\frac{0.002}{\sqrt{k}} ak=k 0.002。可以发现,在3000步以内,使用不同的固定步长最终会到达次优解,函数值下降到一定程度便稳定在某个值附近;而使用消失步长算法最终将会收敛;另外次梯度算法本身是非单调方法,因此在求解过程中需要记录历史中最好的一次迭代来作为算法的最终输出

在这里插入图片描述

对于 u = 1 0 − 2 , 1 0 − 3 u=10^{-2},10^{-3} u=102,103,我们采用连续化次梯度算法进行求解

在这里插入图片描述

二:牛顿法

使用梯度下降法,我们给出的迭代格式为

x k + 1 = x k − α k ∇ f ( x k ) x^{k+1}=x^{k}-\alpha_{k}\nabla f(x^{k}) xk+1=xkαkf(xk)

由于梯度下降的基本策略是沿一阶最速下降方向迭代。当 ∇ 2 f ( x ) \nabla^{2}f(x) 2f(x)的条件数较大时,它的收敛速度比较缓慢(只用到了一阶信息)。因此如果 f ( x ) f(x) f(x)足够光滑,我们可以利用 f ( x ) f(x) f(x)二阶信息改进下降方向,以加速算法的迭代

(1)经典牛顿法

经典牛顿法:对于可微二次函数 f ( x ) f(x) f(x),对于第 k k k步迭代,我们考虑目标函数 f f f在点 x k x_{k} xk的二阶泰勒近似

在这里插入图片描述

忽略高阶项 o ( ∣ ∣ d k ∣ ∣ 2 ) o(||d^{k}||^{2}) o(∣∣dk2),并将等式右边视作 d k d^{k} dk的函数并极小化,则
∇ 2 f ( x k ) d k = − ∇ f ( x k ) \nabla^{2}f(x^{k})d^{k}=-\nabla f(x^{k}) 2f(xk)dk=f(xk)

上式称其为牛顿方程 d k d^{k} dk叫做牛顿方向

∇ 2 f ( x k ) \nabla^{2}f(x^{k}) 2f(xk)非奇异,则可得到迭代格式

x k + 1 = x k − ∇ 2 f ( x k ) − 1 ∇ f ( x k ) x^{k+1}=x^{k}-\nabla^{2}f(x^{k})^{-1}\nabla f(x^{k}) xk+1=xk2f(xk)1f(xk)

  • 注意:步长 α k = 1 \alpha_{k}=1 αk=1

此迭代格式称之为经典牛顿法

经典牛顿法收敛速度很快,但是在使用中会有一些限制因素

  • 初始点 x 0 x^{0} x0需要距离最优解充分近(也即牛顿法只有局部收敛性)。当 x 0 x^{0} x0距离最优解较远时,牛顿法在多数情况下会失效
  • 海瑟矩阵 ∇ 2 f ( x ∗ ) \nabla^{2}f(x^{*}) 2f(x)正定,半正定条件下可能退化到 Q Q Q-线性收敛
  • ∇ 2 f ( x ∗ ) \nabla^{2}f(x^{*}) 2f(x)条件系数较高时,将对初值的选择作出较为严格的要求
  • 海瑟矩阵 ∇ 2 f ( x ∗ ) \nabla^{2}f(x^{*}) 2f(x)需要为正定矩阵。应用时常常以梯度类算法先求得较低精度的解,然后用牛顿法加速

在这里插入图片描述

(2)修正牛顿法

在实际应用中 x k + 1 = x k − ∇ 2 f ( x k ) − 1 ∇ f ( x k ) x^{k+1}=x^{k}-\nabla^{2}f(x^{k})^{-1}\nabla f(x^{k}) xk+1=xk2f(xk)1f(xk)几乎是不能使用的,这是因为

  • 每一步迭代需要求解一个 n n n维线性方程组,这导致在高维问题中计算量很大,而且海瑟矩阵又不容易存储
  • 当海瑟矩阵不正定时,又牛顿方程给出的解 d k d^{k} dk的性质较差
  • 当迭代点距最优值较远时,直接选取步长 a k = 1 a_{k}=1 ak=1会使迭代极其不稳定,在有些情况下迭代点会发散

修正牛顿法:为了克服上述缺陷,我们对经典牛顿法做出某种修正或者变形,提出了修正牛顿法,使其成为真正可以使用的算法。这里介绍带线搜索的修正牛顿法,其基本思想是对牛顿方程中的海瑟矩阵 ∇ 2 f ( x k ) \nabla^{2}f(x^{k}) 2f(xk)进行修正,使其变为正定矩阵,同时引入线搜索以改善算法稳定性,其算法框架如下

在这里插入图片描述
上述算法中, B k B^{k} Bk(即 E k E^{k} Ek)的选取较为关键,需要注意

  • B k B^{k} Bk应该具有较低的条件数
  • ∇ 2 f ( x ) \nabla^{2}f(x) 2f(x)的改动较小,以保存二阶信息
  • B k B^{k} Bk本身的计算代价不应该太高

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

import numpy as np
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 Hessian_define(function):
    x = []
    x.append(Symbol('x1'))
    x.append(Symbol('x2'))
    H = zeros(2, 2)
    function = sympify([function])
    for i, fi in enumerate(function):
        for j, r in enumerate(x):
         for k, s in enumerate(x):
                H[j ,k] = diff(diff(fi, r), s)
    
    H = np.array(H)
    return H

#  海瑟矩阵计算
def cal_hessian_ret(hessian_function, x):
    res = []
    for i in range(2):
        temp = []
        for j in range(2):
            temp.append(hessian_function[i][j].subs([('x1', x[0]), ('x2', x[1])]))
        res.append(temp)      
    return res

# armijo-goldstein准则
def armijo_goldstein(function, grad_function, x0, d, c = 0.3):
    # 指定初始步长
    alpha = 1.0
    # 回退参数
    gamma = 0.333
    # 迭代次数
    k = 1.0

    # fd 表示 f(x + alpha * d)
    fd = cal_function_ret(function, np.add(x0, np.dot(alpha, d))) 
    # fk 表示 f(x) + c * alpha * gradf(x) * d
    fk = cal_function_ret(function, x0) + c * alpha * np.dot(cal_grad_ret(grad_function, x0), d)
    # fp 表示 f(x) + (1-c) * alpha * gradf(x) * d
    fp = cal_function_ret(function, x0) + (1-c) * alpha * np.dot(cal_grad_ret(grad_function, x0), d)
    while fd > fk or fd < fp:
        alpha *= gamma
        fd = cal_function_ret(function, np.add(x0, np.dot(alpha, d))) 
        fk = cal_function_ret(function, x0) + c * alpha * np.dot(cal_grad_ret(grad_function, x0), d)
        fp = cal_function_ret(function, x0) + (1-c) * alpha * np.dot(cal_grad_ret(grad_function, x0), d)
        k += 1.0
    print("迭代次数:", k)
    return alpha


# armijo-wolfe准则
def armijo_wlofe(function, grad_function, x0, d, c = 0.3):
    # wolfe准则参数
    c2 = 0.9
    # 指定初始步长
    alpha = 1.0
    # 二分法确定alpah
    a, b = 0, np.inf
    # 迭代次数
    k = 1.0
    
    # gk表示gradf(x)
    gk = cal_grad_ret(grad_function, x0)
    # fd 表示 f(x + alpha * d)
    fd = cal_function_ret(function, np.add(x0, np.dot(alpha, d))) 
    # fk 表示 f(x) + c * alpha * gradf(x) * d
    fk = cal_function_ret(function, x0) + c * alpha * np.dot(cal_grad_ret(grad_function, x0), d)
    # gp表示gradf(x + alpha * d)
    gp = cal_grad_ret(grad_function, np.add(x0, np.dot(alpha, d)))
    while True:
        if fd > fk:
            b = alpha
            alpha = (a + b) / 2
            fd = cal_function_ret(function, np.add(x0, np.dot(alpha, d))) 
            fk = cal_function_ret(function, x0) + c * alpha * np.dot(cal_grad_ret(grad_function, x0), d)
            gp = cal_grad_ret(grad_function, np.add(x0, np.dot(alpha, d)))
            k = k + 1
            continue
        if np.dot(gp, d) < c2 * np.dot(gk, d):
            a = alpha
            alpha = np.min(2 * alpha, (a + b) / 2)
            fd = cal_function_ret(function, np.add(x0, np.dot(alpha, d))) 
            fk = cal_function_ret(function, x0) + c * alpha * np.dot(cal_grad_ret(grad_function, x0), d)
            gp = cal_grad_ret(grad_function, np.add(x0, np.dot(alpha, d)))
            k = k + 1
            continue
        break
    return alpha

#  范数计算
def norm(x):
    return sqrt(np.dot(x, x))

# 牛顿法
def Newton(function, hessian_function ,grad_function, x0, delta):
    k = 0  # 迭代次数
    xk = x0  # 初始迭代点
    gk = cal_grad_ret(grad_function, xk)
    
    while norm(gk) > 0.00001 and k < 10000:
        gk2 = cal_hessian_ret(hessian_function, xk)  # 海瑟矩阵
        dk = np.dot(-1, np.dot(np.linalg.inv(np.array(gk2, dtype=float)), gk)) # 下降方向
        alpha = 0.01
        #  如果delta为0,利用wolf准则求步长
        if delta == 0:
            alpha = armijo_wlofe(function, grad_function, xk, dk)
        #  如果delta为1,利用glodstein准则求步长
        if delta == 1:
            alpha = armijo_goldstein(function, grad_function, xk, dk)
        xk = np.add(xk , np.dot(alpha, dk))  # 步长为1
        k = k + 1
        gk = cal_grad_ret(grad_function, xk)  # 更新梯度
        
    print("xk", xk)
    print("迭代次数", k)
    
    return cal_function_ret(function, xk)
            
if __name__ == '__main__':
    function = function_define()
    grad_function = cal_grad_funciton(function)
    Hessian_function = Hessian_define(function)
    print("函数", function)
    print("梯度函数", grad_function)
    print("海瑟矩阵", Hessian_function)
    
    #  计算(0, 0)处的函数值
    print("函数值:", cal_function_ret(function, [1, 1]))
    #  计算(0, 0)处的梯度值
    print("梯度值:", cal_grad_ret(grad_function, [1, 1]))
    #  计算(0, 0)处海瑟矩阵
    print("海瑟矩阵值:", cal_hessian_ret(Hessian_function, [1, 1]))
    #  
    print("最小值:", Newton(function, Hessian_function ,grad_function, [1, 1], 3))

在这里插入图片描述

三:拟牛顿法

拟牛顿法:牛顿法虽然收敛速度快,但是计算过程中需要计算目标函数的二阶偏导数计算复杂度较大,而且有时目标函数的海瑟矩阵无法保持正定,从而使得牛顿法失效,因此拟牛顿法提出用不含二阶导数的矩阵 U t U_{t} Ut替代牛顿法中的 H t − 1 H_{t}^{-1} Ht1,然后沿搜索方向 − U t g t -U_{t}g_{t} Utgt做一维搜索,在“拟牛顿”的条件下优化目标函数不同的构造方法就产生了不同的拟牛顿法

(1)拟牛顿条件

拟牛顿条件:对海瑟矩阵的逆在做近似时不能随便乱来,需要一定的理论指导,而拟牛顿条件则是用来提供理论指导的,指出了用来近似的矩阵应该满足的条件

  • B B B表示对海瑟矩阵 H H H本身的近似,即 B ≈ H B\approx H BH
  • D D D表示对海瑟矩阵的逆 H − 1 H^{-1} H1的近似,即 B ≈ H − 1 B\approx H^{-1} BH1

设经过 k + 1 k+1 k+1次迭代后得到 x k + 1 x_{k+1} xk+1,此时将目标函数 f ( x ) f(x) f(x) x k + 1 x_{k+1} xk+1附近作泰勒展开,取二阶近似,得

在这里插入图片描述

在上式两边同时作用一个梯度算子 ∇ \nabla ,可得

∇ f ( x ) ≈ ∇ f ( x k + 1 ) + H k + 1 ⋅ ( x − x k + 1 ) \nabla f(x) \approx \nabla f(x_{k+1})+H_{k+1}·(x-x_{k+1}) f(x)f(xk+1)+Hk+1(xxk+1)

上式中取 x = x k x=x_{k} x=xk,整理后可得

g k + 1 − g k ≈ H k + 1 ⋅ ( x k + 1 − x k ) g_{k+1}-g_{k}\approx H_{k+1}·(x_{k+1}-x_{k}) gk+1gkHk+1(xk+1xk)

引入记号

s k = x k + 1 − x k , y k = g k + 1 − g k s_{k}=x_{k+1}-x_{k},y_{k}=g_{k+1}-g_{k} sk=xk+1xk,yk=gk+1gk

则上式可写为

y k ≈ H k + 1 ⋅ s k ① y_{k}\approx H_{k+1}·s_{k}\quad ① ykHk+1sk

s k ≈ H k + 1 − 1 ⋅ y k ② s_{k}\approx H_{k+1}^{-1}·y_{k}\quad ② skHk+11yk

①,② ①,② 两式便是拟牛顿条件,它对迭代过程中的海瑟矩阵 H k + 1 H_{k+1} Hk+1作约束,因此对 H k + 1 H_{k+1} Hk+1做近似的 B k + 1 B_{k+1} Bk+1以及对 H k + 1 − 1 H^{-1}_{k+1} Hk+11做近似的 D k + 1 D_{k+1} Dk+1可以将 y k = B k + 1 ⋅ s k y_{k}= B_{k+1}·s_{k} yk=Bk+1sk s k = D k + 1 ⋅ y k s_{k}= D_{k+1}·y_{k} sk=Dk+1yk作为指导

(2)DFP算法

DFP算法:是最早的拟牛顿法,会以以下迭代方法,对 H k + 1 − 1 H_{k+1}^{-1} Hk+11作近似

D k + 1 = D k + △ D k , k = 0 , 1 , 2.... D_{k+1}=D_{k}+△ D_{k},\quad k=0,1, 2.... Dk+1=Dk+Dk,k=0,1,2....

  • D 0 D_{0} D0通常取为单位矩阵 I I I

其中校正矩阵 △ D k △ D_{k} Dk

△ D k = s k s k T s k T y k − D k y k y k T D k y k T D k y k △ D_{k}=\frac{s_{k}s_{k}^{T}}{s_{k}^{T}y_{k}}-\frac{D_{k}y_{k}y_{k}^{T}D_{k}}{y_{k}^{T}D_{k}y_{k}} Dk=skTykskskTykTDkykDkykykTDk

其算法逻辑如下

在这里插入图片描述

import numpy as np
import math
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 Hessian_define(function):
    x = []
    x.append(Symbol('x1'))
    x.append(Symbol('x2'))
    H = zeros(2, 2)
    function = sympify([function])
    for i, fi in enumerate(function):
        for j, r in enumerate(x):
         for k, s in enumerate(x):
                H[j ,k] = diff(diff(fi, r), s)
    
    H = np.array(H)
    return H

#  海瑟矩阵计算
def cal_hessian_ret(hessian_function, x):
    res = []
    for i in range(2):
        temp = []
        for j in range(2):
            temp.append(hessian_function[i][j].subs([('x1', x[0]), ('x2', x[1])]))
        res.append(temp)      
    return res

# armijo-goldstein准则
def armijo_goldstein(function, grad_function, x0, d, c = 0.3):
    # 指定初始步长
    alpha = 1.0
    # 回退参数
    gamma = 0.333
    # 迭代次数
    k = 1.0

    # fd 表示 f(x + alpha * d)
    fd = cal_function_ret(function, np.add(x0, np.dot(alpha, d))) 
    # fk 表示 f(x) + c * alpha * gradf(x) * d
    fk = cal_function_ret(function, x0) + c * alpha * np.dot(cal_grad_ret(grad_function, x0), d)
    # fp 表示 f(x) + (1-c) * alpha * gradf(x) * d
    fp = cal_function_ret(function, x0) + (1-c) * alpha * np.dot(cal_grad_ret(grad_function, x0), d)
    while fd > fk or fd < fp:
        alpha *= gamma
        fd = cal_function_ret(function, np.add(x0, np.dot(alpha, d))) 
        fk = cal_function_ret(function, x0) + c * alpha * np.dot(cal_grad_ret(grad_function, x0), d)
        fp = cal_function_ret(function, x0) + (1-c) * alpha * np.dot(cal_grad_ret(grad_function, x0), d)
        k += 1.0
    print("迭代次数:", k)
    return alpha


# armijo-wolfe准则
def armijo_wlofe(function, grad_function, x0, d, c = 0.3):
    # wolfe准则参数
    c2 = 0.9
    # 指定初始步长
    alpha = 1.0
    # 二分法确定alpah
    a, b = 0, np.inf
    # 迭代次数
    k = 1.0
    
    # gk表示gradf(x)
    gk = cal_grad_ret(grad_function, x0)
    # fd 表示 f(x + alpha * d)
    fd = cal_function_ret(function, np.add(x0, np.dot(alpha, d))) 
    # fk 表示 f(x) + c * alpha * gradf(x) * d
    fk = cal_function_ret(function, x0) + c * alpha * np.dot(cal_grad_ret(grad_function, x0), d)
    # gp表示gradf(x + alpha * d)
    gp = cal_grad_ret(grad_function, np.add(x0, np.dot(alpha, d)))
    while True:
        if fd > fk:
            b = alpha
            alpha = (a + b) / 2
            fd = cal_function_ret(function, np.add(x0, np.dot(alpha, d))) 
            fk = cal_function_ret(function, x0) + c * alpha * np.dot(cal_grad_ret(grad_function, x0), d)
            gp = cal_grad_ret(grad_function, np.add(x0, np.dot(alpha, d)))
            k = k + 1
            continue
        if np.dot(gp, d) < c2 * np.dot(gk, d):
            a = alpha
            alpha = np.min(2 * alpha, (a + b) / 2)
            fd = cal_function_ret(function, np.add(x0, np.dot(alpha, d))) 
            fk = cal_function_ret(function, x0) + c * alpha * np.dot(cal_grad_ret(grad_function, x0), d)
            gp = cal_grad_ret(grad_function, np.add(x0, np.dot(alpha, d)))
            k = k + 1
            continue
        break
    return alpha

#  范数计算
def norm(x):
    return math.sqrt(np.dot(x, x))

# 牛顿法
def Newton(function, hessian_function ,grad_function, x0, delta):
    k = 0  # 迭代次数
    xk = x0  # 初始迭代点
    gk = cal_grad_ret(grad_function, xk)
    
    while norm(gk) > 0.0001 and k < 10000:
        gk2 = cal_hessian_ret(hessian_function, xk)  # 海瑟矩阵
        dk = np.dot(-1, np.dot(np.linalg.inv(np.array(gk2, dtype=float)), gk)) # 下降方向
        alpha = 0.01
        #  如果delta为0,利用wolf准则求步长
        if delta == 0:
            alpha = armijo_wlofe(function, grad_function, xk, dk)
        #  如果delta为1,利用glodstein准则求步长
        if delta == 1:
            alpha = armijo_goldstein(function, grad_function, xk, dk)
        xk = np.add(xk , np.dot(alpha, dk))  
        k = k + 1
        gk = cal_grad_ret(grad_function, xk)  # 更新梯度
        
    print("xk", xk)
    print("迭代次数", k)
    
    return cal_function_ret(function, xk)

# 拟牛顿法(DFP)
def DFP_Newton(function, grad_function, x0):
    xk = x0
    
    alpha = 0.001 # 初始步长
    gk = cal_grad_ret(grad_function, xk)
    D = np.eye(2)  # 初始化正定矩阵 
    k = 1
    
    while k < 10000:
        dk = np.dot(-1, np.dot(D, gk)) # 下降方向
        xk_new = np.add(xk , np.dot(alpha, dk))  
        gk_new = cal_grad_ret(grad_function, xk_new)  # 更新梯度

        if norm(gk_new) < 0.0001:
            break
        
        # 计算y和s
        y = np.array(gk_new) - np.array(gk)
        s = np.array(xk_new) - np.array(xk)
        
        # 更新正定矩阵D
        D = D + np.dot(s, s.T)/np.dot(s.T, y) - np.dot(D, np.dot(y, np.dot(y.T, D))) / np.dot(y.T, np.dot(D, y))
        
        k = k + 1 
        
        gk = gk_new  
        xk = xk_new  # 更新xk
        
    print("xk", xk)
    print("迭代次数", k)
    
    return cal_function_ret(function, xk)

if __name__ == '__main__':
    function = function_define()
    grad_function = cal_grad_funciton(function)
    Hessian_function = Hessian_define(function)
    print("函数", function)
    print("梯度函数", grad_function)
    print("海瑟矩阵", Hessian_function)
    
    #  计算(0, 0)处的函数值
    print("函数值:", cal_function_ret(function, [1, 1]))
    #  计算(0, 0)处的梯度值
    print("梯度值:", cal_grad_ret(grad_function, [1, 1]))
    #  计算(0, 0)处海瑟矩阵
    print("海瑟矩阵值:", cal_hessian_ret(Hessian_function, [1, 1]))
    #  
    print("最小值:", DFP_Newton(function, grad_function, [1, 1]))
    
    

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/98745.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

知到/智慧树——英语听说:实境主题与技能(参考答案)

目录 第一章测试 第二章测试 第三章测试 第四章测试 第五章测试 第六章测试 第七章测试 第八章测试 第九章测试 第十章测试 第一章测试 第1部分总题数: 10 1 【多选题】 (10分) What does this chapter mainly teach &#xff08; &#xff09;&#xff1f; A. T…

生成树(基础)

目录 一、生成树的相关概念 二、最小生成树的相关概念 最小生成树的性质(MST性质)&#xff1a; MST性质解释&#xff1a; 三、Prim算法&#xff08;普里姆算法&#xff09; 动态演示 关键算法&#xff1a; 完整代码&#xff1a; 四、Kruskal(克鲁斯卡尔)算法 动态演示&…

mysql主从复制架构

MySQL的主从复制架构的分布机制&#xff0c;是通过将MySQL的某一台主机(master)的数据复制到其他主机(slave)上。 在复制过程中一台主机作为主服务器&#xff0c;其他服务器则为从服务器。主服务器将更新写入到日志文件中&#xff0c;日志被从服务器的 I/O线程读取&#xff0c;…

逻辑回归 预测癌症数据

目录 一&#xff1a;加载数据 二&#xff1a;数据集划分 三&#xff1a;选择算法 四&#xff1a;网格模型 超参调优 五&#xff1a;模型预测 六&#xff1a;模型保存和使用 七&#xff1a;完整源码分享 八&#xff1a;预测与实际比对 一&#xff1a;加载数据 from sk…

C语言—变量与常量

想存储一个数据时&#xff0c;都会在内存中开辟一个空间&#xff0c;这个空间会有一个地址&#xff1b; 这个地址是一串数字&#xff0c;为了方便记忆&#xff0c;所以要对这个地址起一个名字&#xff0c;也就是变量名&#xff1b; 通过这个变量名就可以找到内存中存放这个数…

java高校学生电器报修系统ssm高校后勤报修系统小程序源码和论文

随着高校每年的扩大招生&#xff0c;学校人数越来越多&#xff0c;学校后勤报修管理的工作量也越来越繁重。使用传统的管理手段和方法&#xff0c;很难完成大量的信息分析和处理。因此&#xff0c;充分利用网络资源和信息化技术&#xff0c;建设一套基于校园网的学校后勤报修管…

fpga实操训练(uart串口)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 如果说led灯、按键、数码管这些都只能算是基础的话&#xff0c;那么学习fpga遇到的第一个门槛就是uart。要做好uart&#xff0c;首先需要了解串口的…

Thymeleaf 预处理表达式__${表达式}__之国际化使用案例

目录一. 前期准备1.1 国际化项目获取类1.2 国际化配置文件类1.3 项目配置文件1.4 国际化资源文件二. __${表达式}__预处理表达式2.1 在Thymeleaf中使用Spring的Bean2.2 通过#{}获取国际化资源2.3 预处理表达式__${表达式}__的使用三. 效果一. 前期准备 1.1 国际化项目获取类 …

linux系统中RGBLCD的基本操作和实现方法

大家好&#xff0c;今天主要来聊一聊&#xff0c;如何控制RGBLCD屏的方法。 目录 第一&#xff1a;LCD基本简介 第二&#xff1a;LCD屏的要点 第三&#xff1a;LCD屏具体配置步骤 第四&#xff1a;LCD屏具体的代码实现 第一&#xff1a;LCD基本简介 LCD液晶屏是常用的外设&…

Linux常用命令,能解决工作中99%的Linux操作问题

目录 一、ls 二、pwd 三、cd 四、touch 五、mkdir 六、rmdir&rm 七、man 八、cp 九、mv 九、cat 十、move 十一、less 十二、head 十三、tail 十四、时间 十五、cal 十六、find 十七、grep 十八、zip/unzip 十九、tar 二十、计算器 二十一、uname 二…

SpringBoot 整合Netty自定义消息协议

本文主要介绍springboot项目&#xff0c;配置netty进行消息通信&#xff0c;自定义的netty消息协议&#xff0c;本文消息主要以表格中进行 消息头消息体长度加密标识&#xff08;可选&#xff09;加密类型&#xff08;可选&#xff09;消息体标识消息体校验码2字节2字节1字节&…

SAP ABAP——SAP简介(一)【SAP发展历程】

&#x1f482;作者简介&#xff1a; THUNDER王&#xff0c;一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学会计学专业大二本科在读&#xff0c;同时任汉硕云&#xff08;广东&#xff09;科技有限公司ABAP开发顾问。在学习工作中&#xff0c;我通常使用偏后…

研究必备的 5 个外文文献检索网站

1. Google scholar 网址&#xff1a; https://scholar.google.com.hk/?hlzh-CN 如今搜索论文的首选&#xff0c;可以在这里查看论文统计和引用参考文献&#xff0c;还能通过关注作者或者论文获得新论文更新提醒&#xff0c;以及利用自动化推荐来提供一个基本库 2. DBLP 网址…

MSVC C++ UTF-8编程

除windows平台外大部分其他平台&#xff0c;编译器默认使用的编码都是UTF-8编码&#xff0c;最新版本的Clang编译器只支持UTF-8编码。如果程序需要在多个平台编译运行&#xff0c;则代码必须使用UTF-8。使用UTF-8可以更容易的在多字节字符串(char, std::string)和宽字符(wchar_…

Java+SSM汽车租赁系统汽车出租(含源码+论文+答辩PPT等)

项目功能简介: 该项目采用的技术实现如下 后台框架&#xff1a;Spring、SpringMVC、MyBatis UI界面&#xff1a;jQuery 、JSP 数据库&#xff1a;MySQL 系统功能 系统分为前台用户租车和后台系统管理&#xff1a; 1.前台用户租车 用户注册、用户登录、用户中心、浏览车辆、车辆…

Java项目:SSM在线二手图书交易商城网站平台

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 用户角色包含以下功能&#xff1a; 用户登录,查看商品详情,按分类查看,查看我的书架,上传二手书等功能。 由于本程序规模不大&#xff0c;可供课…

三、CAM可解释性分析——可解释性机器学习(DataWhale组队学习)

文章目录前言CAM算法的精妙之处相关工作CAM算法其它相关问题为什么不用池化操作&#xff1f;CAM的优点CAM算法的缺点扩展阅读和思考题前言 CAM算法奠定了可解释分析的基石 CAM算法的精妙之处 对深度学习实现可解释性分析、显著性分析可扩展性强&#xff0c;后续衍生出各种…

域名备案怎么查?怎么批量查询域名备案

ICP备案&#xff0c;是为了防止在网上从事非法的网站经营活动&#xff0c;打击不良互联网信息的传播&#xff0c;国家对互联网信息服务实行的备案制度。 备案的目的就是为了防止在网上从事非法的网站经营活动&#xff0c;打击不良互联网信息的传播&#xff0c;如果网站不备…

Android TP驱动模型框架分析

本文主要是对TP驱动框架的学习。 一、概述 1、触摸IC的工作原理 tp与主控间的通信接口一般是i2c&#xff0c;即scl、sda、gnd、vcc。在正常工作时需要加上rst、int脚。 整个过程是&#xff1a;通过点击屏幕&#xff0c;tp ic端会将int 脚电平拉低&#xff0c;等待主控的读取。…

【技术分享】Anaconda下载、安装、pip切换镜像源、conda切换镜像、conda创建指定Python版本虚拟环境教程

文章目录1.下载Anaconda1.1.下载最新版本Anaconda1.2.下载历史版本的Anaconda2.安装Anaconda3.conda切换镜像源4.pip切换镜像源5.conda创建指定版本Python环境1.下载Anaconda 1.1.下载最新版本Anaconda 步骤&#xff1a; 进入Anaconda官网&#xff0c;点击Download按钮下载最…