多变量函数极值-牛顿法

简介

之前我们已经采用过牛顿法进行一维搜索,这次我们将牛顿法推广到多维。利用牛顿法来求解多变量极值问题。跟一维问题类似,在局部采用二次函数 φ ( x ) \varphi(\bm{x}) φ(x)来近似替代目标函数 f ( x ) f(\bm{x}) f(x),然后用 φ ( x ) \varphi(\bm{x}) φ(x)的极小点作为 f ( x ) f(\bm{x}) f(x)的近似极小点。设 x k \bm{x}^{k} xk f ( x ) f(x) f(x)的一个近似极小点,将 f ( x ) f(\bm{x}) f(x) x k \bm{x}^{k} xk点利用Taylor公式展开,并略去高于二次的项,则可得:
f ( x ) ≈ φ ( x ) = f ( x k ) + ( ▽ f ( x k ) ) T ( x − x k ) + 1 2 ( x − x k ) T ▽ 2 f ( x k ) ( x − x k ) f(\bm{x})\approx\varphi(\bm{x})=f(\bm{x}^{k})+(\bigtriangledown f(\bm{x}^{k}))^{T}(\bm{x}-\bm{x}^{k})+\frac{1}{2}(\bm{x}-\bm{x}^{k})^{T}\bigtriangledown^{2}f(\bm{x}^{k})(\bm{x}-\bm{x}^{k}) f(x)φ(x)=f(xk)+(f(xk))T(xxk)+21(xxk)T2f(xk)(xxk)
f ( x ) f(\bm{x}) f(x)的极小点迭代公式如下:
x k + 1 = x k − ( ▽ f ( x k ) ) − 1 ▽ 2 f ( x k ) \bm{x}^{k+1}=\bm{x}^k-(\bigtriangledown f(\bm{x}^{k}))^{-1}\bigtriangledown^2 f(\bm{x}^{k}) xk+1=xk(f(xk))12f(xk)
牛顿法优点是收敛速度很快,对于二次函数只需要一次迭代就能找到极小值点,缺点是 f ( x ) f(\bm{x}) f(x)必须是二阶连续可微的,并且初始点不能离极小点太远否则迭代可能不收敛。

优化问题

求解 f ( x 1 , x 2 ) = x 1 2 + 2 x 2 2 − 4 x 1 − 2 x 1 x 2 f(x_1, x_2)=x_1^{2}+2x_2^{2}-4x_1-2x_1x_2 f(x1,x2)=x12+2x224x12x1x2的极小值点,设置初始点 x 0 = [ 0 , 0 ] x_0=[0, 0] x0=[0,0],收敛精度 ε = 1 e − 3 \varepsilon=1e^{-3} ε=1e3,计算程序如下:

import numpy as np


def cal_fun_f(x1, x2):
    """
    函数值计算函数
    """
    return x1**2+2*x2**2-4*x1-2*x1*x2

def partial_derivative_x1(x1, x2):
    """
    求解函数对x1的偏导数
    :param x1:
    :param x2:
    """
    return 2*x1-4-2*x2

def partial_derivative_x2(x1, x2):
    """
    求解函数对x2的偏导数
    :param x1:
    :param x2:
    """
    return 4*x2-2*x1

def partial_derivative_x1x2(x1, x2):
    """
    求解对x1和x2的二阶偏导数
    :param x1:
    :param x2:
    """
    return -2

def partial_derivative_x1x1(x1, x2):
    """
    对x1的二阶偏导数
    :param x1:
    :param x2:
    """
    return 2

def partial_derivative_x2x2(x1, x2):
    """
    对x2的二阶偏导数
    :param x1:
    :param x2:
    """
    return 4

def get_derivative_matrix1(x1, x2):
    """
    计算一阶偏导数矩阵
    :param x1:
    :param x2:
    """
    derivative_matrix1 = np.full((2, 1), np.nan, dtype=float)
    derivative_matrix1[0, 0] = partial_derivative_x1(x1, x2)
    derivative_matrix1[1, 0] = partial_derivative_x2(x1, x2)
    return derivative_matrix1

def get_derivative_matrix2(x1, x2):
    """
    计算二阶偏导数矩阵
    :param x1:
    :param x2:
    """
    derivative_matrix2 = np.full((2, 2), np.nan, dtype=float)
    derivative_matrix2[0, 0] = partial_derivative_x1x1(x1, x2)
    derivative_matrix2[0, 1] = partial_derivative_x1x2(x1, x2)
    derivative_matrix2[1, 0] = partial_derivative_x1x2(x1, x2)
    derivative_matrix2[1, 1] = partial_derivative_x2x2(x1, x2)
    return derivative_matrix2

def newton_method(x, gap):
    i = 0
    while True:
        derivative_matrix1 = get_derivative_matrix1(x[0, 0], x[1, 0])
        derivative_matrix2 = get_derivative_matrix2(x[0, 0], x[1, 0])
        x = x-np.linalg.inv(derivative_matrix2)@derivative_matrix1
        i += 1
        print(f"第{i}次迭代极小值点", (x[0, 0], x[1, 0]))
        if np.sum(np.abs(get_derivative_matrix1(x[0, 0], x[1, 0])), axis=0) < gap:
            break

if __name__ == "__main__":
    newton_method(np.array([0, 0]).reshape(-1, 1), 1e-3)

计算结果如下:

1次迭代极小值点 (4.0, 2.0)

可以看到仅仅经过一次迭代就找到了极小值点。

  • 15
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

知情人士黄某

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

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

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

打赏作者

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

抵扣说明:

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

余额充值