牛顿法python 实现

本文详细介绍了牛顿法这一求解无约束最优化问题的高效算法,通过实例演示了算法的迭代过程,对比了牛顿法与最速下降法的优劣,并附带Python代码实现。

有用请点赞,没用请差评。

欢迎分享本文,转载请保留出处。

 

牛顿法也是求解无约束最优化问题的常用方法,有收敛速度快的优点。牛顿法是迭代算法,每一步需要求解目标函数的海赛矩阵的逆矩阵。同时还有拟牛顿法、阻尼牛顿法、修正牛顿法等等。

算法步骤:

 

import random
import numpy as np
import matplotlib.pyplot as plt

def dampnm(fun,gfun,hess,x0):
    # 用牛顿法求解无约束问题
    #x0是初始点,fun,gfun和hess分别是目标函数值,梯度,海森矩阵的函数
    maxk = 500
    rho = 0.55
    sigma = 0.4
    k = 0
    epsilon = 1e-5

    f=open("牛顿.txt","w")
    W = np.zeros((2, 20000))

    while k < maxk:
        W[:, k] = x0
        gk = gfun(x0)
        Gk = hess(x0)
        dk = -1.0*np.linalg.solve(Gk,gk)
        print(k, np.linalg.norm(dk))
        f.write(str(k)+'   '+str(np.linalg.norm(gk))+"\n")
        if np.linalg.norm(dk) < epsilon:
            break

        x0 += dk
        k += 1
    W = W[:, 0:k + 1]  # 记录迭代点
    return x0,fun(x0),k,W

# 函数表达式fun
fun = lambda x:100*(x[0]**2-x[1])**2 + (x[0]-1)**2

# 梯度向量 gfun
gfun = lambda x:np.array([400*x[0]*(x[0]**2-x[1])+2*(x[0]-1), -200*(x[0]**2-x[1])])

# 海森矩阵 hess
hess = lambda x:np.array([[1200*x[0]**2-400*x[1]+2, -400*x[0]],[-400*x[0],200]])

if __name__=="__main__":
    X1 = np.arange(-1.5, 1.5 + 0.05, 0.05)
    X2 = np.arange(-3.5, 2 + 0.05, 0.05)
    [x1, x2] = np.meshgrid(X1, X2)
    f = 100 * (x2 - x1 ** 2) ** 2 + (1 - x1) ** 2  # 给定的函数
    plt.contour(x1, x2, f, 40)  # 画出函数的20条轮廓线

    x0 = np.array([-1.2, 1])
    out=dampnm(fun, gfun, hess, x0)
    print(out[2],out[0])

    W = out[3]
    print(W[:,:])

    plt.plot(W[0, :], W[1, :], 'g*-')
    plt.show()



迭代轨迹(但是一直觉得有问题的是为啥第三个点老是会偏辣么多??):

迭代的轨迹坐标:

 

 每一步迭代对应的误差:

0232.8676878
14.639426214
21370.789849
30.473110379
425.0274456
58.61E-06

 牛顿法是二阶收敛,最速下降是一阶收敛,所以牛顿法就更快。最速下降法每次只从当前所处位置选一个坡度最大的方向走一步,牛顿法在选择方向时,不仅会考虑坡度是否够大,还会考虑走了一步之后,坡度是否会变得更大。所以,可以说牛顿法比最速下降法看得更远一点,能更快地走到最底部。牛顿法目光更加长远,所以少走弯路;相对而言,最速下降法只考虑了局部的最优,没有全局思想。

 

注:内容原创,部分文字来源于网络。

### 解决 Python牛顿法出现的 UnboundLocalError 错误 在使用牛顿法时,`UnboundLocalError` 错误通常是因为函数内部变量的作用域问题导致的。以下是一个详细的分析和解决方案。 #### 错误原因分析 当在函数中定义了一个局部变量,并且在赋值之前尝试引用它时,Python 会抛出 `UnboundLocalError` 错误。例如,在牛顿法实现中,如果在函数中对变量进行了重新赋值,但在赋值之前尝试访问该变量,则会导致此错误[^1]。 以下是一个可能导致错误的代码示例: ```python def newton_method(x0, e): print(x0) # 尝试读取 x0 的值 x0 = x0 - f(x0) / df(x0) # 对 x0 进行重新赋值 if abs(f(x0)) < e: return x0 else: return newton_method(x0, e) ``` 运行上述代码可能会导致以下错误: ``` UnboundLocalError: local variable 'x0' referenced before assignment ``` #### 解决方案 ##### 方法一:确保变量在引用前已正确初始化 通过确保变量在被引用之前已经正确初始化,可以避免 `UnboundLocalError` 错误。以下是修正后的代码: ```python def newton_method(x0, e): x = x0 # 使用一个新的变量名来避免作用域冲突 while abs(f(x)) >= e: x = x - f(x) / df(x) return x ``` ##### 方法二:传递参数以避免局部变量覆盖 通过将变量作为参数传递给递归调用的函数,可以避免局部变量覆盖的问题。以下是修正后的代码: ```python def newton_method(x0, e): if abs(f(x0)) < e: return x0 else: x1 = x0 - f(x0) / df(x0) return newton_method(x1, e) ``` ##### 方法三:使用全局变量(不推荐) 虽然可以通过声明全局变量来解决此问题,但这并不是最佳实践,因为它可能导致代码难以维护和调试。以下是使用全局变量的示例: ```python x0 = 0 def newton_method(e): global x0 if abs(f(x0)) < e: return x0 else: x0 = x0 - f(x0) / df(x0) return newton_method(e) ``` #### 示例代码 以下是一个完整的牛顿法实现,避免了 `UnboundLocalError` 错误: ```python def f(x): return x**2 - 4 def df(x): return 2 * x def newton_method(x0, e): x = x0 while abs(f(x)) >= e: x = x - f(x) / df(x) return x # 调用牛顿法 result = newton_method(3, 1e-6) print(f"Root: {result}") ``` #### 注意事项 - 确保在函数内部正确初始化所有变量。 - 避免在函数内部对参数进行重新赋值,除非明确需要。 - 如果使用递归调用,确保每次递归时传递正确的参数。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值