非线性最小二乘问题的数值方法 —— 从高斯-牛顿法到列文伯格-马夸尔特法 (II, Python 简单实例)

Title: 非线性最小二乘问题的数值方法 —— 从高斯-牛顿法到列文伯格-马夸尔特法 (II, Python 简单实例)

姊妹博文

非线性最小二乘问题的数值方法 —— 从高斯-牛顿法到列文伯格-马夸尔特法 (I)

文章目录

    • 0.前言
    • 1. 最优问题实例
    • 2. 列文伯格-马夸尔特法 (Levenberg-Marquardt Method) 计算
    • 3. 结果显示
    • 4. 结论


0.前言

本篇博文作为对前述 “非线性最小二乘问题的数值方法 —— 从高斯-牛顿法到列文伯格-马夸尔特法 (I)” 的简单实践扩展.

理论部分参见前述博文, 此处不再重复. 这里只是补充一个简单的 Python 实例.


1. 最优问题实例

m i n i m i z e g ( x ) = 1 2 ∥ r ( x ) ∥ 2 2 = 1 2 ∑ i = 1 3 r i ( x ) 2 (I-1) {\rm minimize}\quad {g}(\mathbf{x}) = \frac{1}{2}\|\mathbf{r}(\mathbf{x})\|_2^2 = \frac{1}{2}\sum_{i=1}^{3} r_i(\mathbf{x})^2 \tag{I-1} minimizeg(x)=21r(x)22=21i=13ri(x)2(I-1)

其中

x = [ x 1 , x 2 ] T \mathbf{x} = \begin{bmatrix} x_1, x_2 \end{bmatrix}^{\small\rm T} x=[x1,x2]T

r ( x ) = [ r 1 ( x ) ,   r 2 ( x ) ,   r 3 ( x ) ] T \mathbf{r}(\mathbf{x}) = \begin{bmatrix} r_1(\mathbf{x}), \, r_2(\mathbf{x}) ,\,r_3(\mathbf{x}) \end{bmatrix}^{\small\rm T} r(x)=[r1(x),r2(x),r3(x)]T

r 1 ( x ) = sin ⁡ x 1 − 0.4 r_1(\mathbf{x}) = \sin x_1 -0.4 r1(x)=sinx10.4

r 2 ( x ) = cos ⁡ x 2 + 0.8 r_2(\mathbf{x}) = \cos x_2 + 0.8 r2(x)=cosx2+0.8

r 3 ( x ) = x 1 2 + x 2 2 − 1 r_3(\mathbf{x}) = \sqrt{x_1^2 +x_2^2} -1 r3(x)=x12+x22 1

可以推得

∂ r ( x ) ∂ x = [ cos ⁡ x 1 0 0 − sin ⁡ x 2 x 1 x 1 2 + x 2 2 x 2 x 1 2 + x 2 2 ] \frac{\partial \mathbf{r}(\mathbf{x})}{\partial \mathbf{x}} = \begin{bmatrix}\cos x_1 & 0\\ 0 &-\sin x_2 \\ \frac{x_1}{\sqrt{x_1^2+x_2^2}} & \frac{x_2}{\sqrt{x_1^2+x_2^2}} \end{bmatrix} xr(x)= cosx10x12+x22 x10sinx2x12+x22 x2

g ( x ) = 1 2 [ ( sin ⁡ x 1 − 0.4 ) 2 + ( cos ⁡ x 2 + 0.8 ) 2 + ( x 2 2 + x 1 2 − 1 ) 2 ] g(\mathbf{x})=\frac{1}{2} \left[{ {{\left( \sin{ {x_1} }-0.4\right) }^{2}}+{{\left( \cos{ {x_2} }+0.8\right) }^{2}}+{{\left( \sqrt{{{{x_2}}^{2}}+{{{x_1}}^{2}}}-1\right) }^{2}}}\right] g(x)=21[(sinx10.4)2+(cosx2+0.8)2+(x22+x12 1)2]

∇ g ( x ) = [ x 1 ( x 2 2 + x 1 2 − 1 ) x 2 2 + x 1 2 + cos ⁡ x 1 ( sin ⁡ x 1 − 0.4 ) x 2 ( x 2 2 + x 1 2 − 1 ) x 2 2 + x 1 2 − sin ⁡ x 2 ( cos ⁡ x 2 + 0.8 ) ] \nabla g(\mathbf{x}) = \begin{bmatrix}\frac{{x_1} \left( \sqrt{{{{x_2}}^{2}}+{{{x_1}}^{2}}}-1\right) }{\sqrt{{{{x_2}}^{2}}+{{{x_1}}^{2}}}}+\cos{ {x_1} } \left( \sin{ {x_1} }-0.4\right) \\ \frac{{x_2} \left( \sqrt{{{{x_2}}^{2}}+{{{x_1}}^{2}}}-1\right) }{\sqrt{{{{x_2}}^{2}}+{{{x_1}}^{2}}}}- \sin{ {x_2} } \left( \cos{ {x_2} }+0.8\right) \end{bmatrix} g(x)= x22+x12 x1(x22+x12 1)+cosx1(sinx10.4)x22+x12 x2(x22+x12 1)sinx2(cosx2+0.8)

H ~ ( x ) = [ x 1 2 x 2 2 + x 1 2 + ( cos ⁡ x 1 ) 2 x 1 x 2 x 2 2 + x 1 2 x 1 x 2 x 2 2 + x 1 2 ( sin ⁡ x 2 ) 2 + x 2 2 x 2 2 + x 1 2 ] \widetilde{\mathbf{H}}(\mathbf{x})=\begin{bmatrix}\frac{{{{x_1}}^{2}}}{{{{x_2}}^{2}}+{{{x_1}}^{2}}}+{{(\cos{ {x_1} })}^{2}} & \frac{{x_1} {x_2}}{{{{x_2}}^{2}}+{{{x_1}}^{2}}}\\ \frac{{x_1} {x_2}}{{{{x_2}}^{2}}+{{{x_1}}^{2}}} & {{(\sin{ {x_2} )}}^{2}}+\frac{{{{x_2}}^{2}}}{{{{x_2}}^{2}}+{{{x_1}}^{2}}}\end{bmatrix} H (x)=[x22+x12x12+(cosx1)2x22+x12x1x2x22+x12x1x2(sinx2)2+x22+x12x22]

具体的符号推导参见非线性最小二乘问题的数值方法 —— 从牛顿迭代法到高斯-牛顿法 (实例篇 V).


2. 列文伯格-马夸尔特法 (Levenberg-Marquardt Method) 计算

基于列文伯格-马夸尔特法的算法流程实现如下简单 Python Demo:

from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np
from numpy.linalg import inv, det, norm
from math import cos
from math import sin
from math import sqrt
from math import pow

# multiplication of two matrixs
def multiply_matrix(A, B):
    if  A.shape[1] == B.shape[0]:
        C = np.zeros((A.shape[0], B.shape[1]), dtype = float)
        [rows, cols] = C.shape
        
        for row in range(rows): 
            for col in range(cols):
                for elt in range(len(B)):
                    C[row, col] += A[row, elt] * B[elt, col]
        return C
    else:
        return "Cannot multiply A and B. Please check whether the dimensions of the inputs are compatible."

# g(x) = (1/2) ||r(x)||_2^2
def g(x_1, x_2):
    return ( pow(sin(x_1)-0.4, 2)+ pow(cos(x_2)+0.8, 2) + pow(sqrt(pow(x_2,2)+pow(x_1,2))-1, 2) ) /2

# r(x) = [r_1, r_2, r_3]^{T}
def r(x_1, x_2):
    return np.array([[sin(x_1)-0.4],
                     [cos(x_2)+0.8],
                     [sqrt(pow(x_1,2)+pow(x_2,2))-1]], dtype=object)

# \partial r(x) / \partial x
def dr(x_1, x_2):
    if sqrt(pow(x_2,2)+pow(x_1,2)) < 1e-3:  ## 人为设置
        return np.array([[cos(x_1),	0], 
                         [0, -sin(x_2)],
                         [0, 0]], dtype=object)
    else:
        return np.array([[cos(x_1),	0],
                         [0,	-sin(x_2)],
                         [x_1/sqrt(pow(x_2,2)+pow(x_1,2)), x_2/sqrt(pow(x_2,2)+pow(x_1,2))]], dtype=object)

# Simplified Hessian matrix in Gauss-Newton method
# refer to eq. ​(I-1-2) in blog "非线性最小二乘问题的数值方法 —— 从高斯-牛顿法到列文伯格-马夸尔特法 (I)"
def sH(x_1, x_2):
    return multiply_matrix(np.transpose(dr(x_1, x_2)), dr(x_1, x_2)) 


# \nabla g(x_1, x_2)
# refer to eq. ​(I-1-3) in blog "非线性最小二乘问题的数值方法 —— 从高斯-牛顿法到列文伯格-马夸尔特法 (I)"
def dg(x_1, x_2):
    return multiply_matrix(np.transpose(dr(x_1, x_2)), r(x_1, x_2))


# model for the cost function g
def L_model(h_vector, g_i, dg_i, sH_i):
    return g_i + multiply_matrix( dg_i.transpose(), h_vector) + 0.5 * multiply_matrix(multiply_matrix(h_vector.transpose(), sH_i), h_vector)


def levenberg_marquardt_method(x_1, x_2, epsilon_1, epsilon_2, max_iter):
    iter = 0
    tau = 1
    found = False
    sH_i = sH(x_1, x_2)
    dg_i = dg(x_1, x_2)
    mu_i = tau * np.max(np.diag(sH_i))
    # if np.max(np.abs(dg_i)) < epsilon_1:
    if norm(dg_i, np.inf) < epsilon_1:
        found = True

    x_current_1 = x_1
    x_current_2 = x_2
    x_current_vector = np.array([[x_current_1], [x_current_2]], dtype=object)
    g_current = g(x_current_1, x_current_2)
    array_x_1 = []
    array_x_2 = []
    array_x_3 = []
    array_x_1.append(x_current_1)
    array_x_2.append(x_current_2)
    array_x_3.append(g_current)
    # new_x = np.matrix([[0],[0]])
    x_new_1 = 0
    x_new_2 = 0
    g_new = np.inf
    while (found == False) and (iter < max_iter):
        iter += 1
        inv_sH_i =  inv(sH_i + mu_i * np.diag(np.diag(sH_i)))
        h_step = - multiply_matrix(inv_sH_i, dg_i)
        if norm(h_step, 2) <= epsilon_2*(norm(x_current_vector) + epsilon_2):
            found = True
        else:
            x_new_1 = x_current_1 + h_step[0]
            x_new_2 = x_current_2 + h_step[1]
            if g_new != np.inf:
                g_current = g_new
            g_new = g(x_new_1, x_new_2)
            rho = (g_current - g_new) / (g_current - L_model(h_step, g_current, dg_i, sH_i))

            if rho > 0:   # step acceptable
                x_current_1 = x_new_1
                x_current_2 = x_new_2
                x_current_vector = np.array([[x_current_1], [x_current_2]], dtype=object)
                sH_i = sH(x_current_1, x_current_2)
                dg_i = dg(x_current_1, x_current_2)
                if norm(dg_i, np.inf) < epsilon_1:
                    found = True
                mu_i = mu_i * np.max( np.array([1/3, 1-pow(2*rho-1,3)], dtype=object))
                v_i = 2
                array_x_1.append(x_new_1)
                array_x_2.append(x_new_2)
                array_x_3.append(g_new)
            else:      # step unacceptable
                mu_i = mu_i * v_i
                v_i = 2* v_i
    return array_x_1, array_x_2, array_x_3
      

def result_plot(trajectory):
    fig = plt.figure()
    ax3 = plt.axes(projection='3d')
    xx = np.arange(-5,5,0.1)
    yy = np.arange(-4,4,0.1)
    X, Y = np.meshgrid(xx, yy)
    Z = np.zeros((X.shape[0], Y.shape[1]), dtype = float)
    for i in range(X.shape[0]):
        for j in range(Y.shape[1]):
            Z[i,j] = g(X[0,j], Y[i,0])

    ax3.plot_surface(X, Y, Z, rstride = 1, cstride = 1, cmap='rainbow', alpha=0.25)
    ax3.contour(X, Y, Z, offset=-1, cmap = 'rainbow')

    ax3.plot(trajectory[0], trajectory[1], trajectory[2], "r--")

    offset_data = -1*np.ones(len(trajectory[0]))
    ax3.plot(trajectory[0], trajectory[1], offset_data,'k--')
    ax3.set_title('Levenberg-Marquardt Method (Initial point [%.1f, %.1f])' %(trajectory[0][0], trajectory[1][0]))
    ax3.set_xlabel("r_1")
    ax3.set_ylabel("r_2")
    ax3.set_zlabel("g")

    file_name_prefix = "./Levenberg_Marquardt"
    file_extension = ".png"
    file_name = f"{file_name_prefix}_{trajectory[0][0]}_{trajectory[1][0]}{file_extension}"
    print(file_name)
    plt.draw()
    plt.savefig(file_name)



if __name__ == "__main__":
   test_data = np.array([[4.9, 3.9], [-2.9, 1.9], [0.1, -0.1], [-0.1, 0.1], [0,-3.8],[1,2.5], [0,0]], dtype=object)
   for inital_data in test_data:
        print("\nInitial point:")
        print(inital_data)
        x_1 = inital_data[0]
        x_2 = inital_data[1]
        epsilon_1 = 1e-6
        epsilon_2 = 1e-5
        max_iter = 1000
        trajectory = levenberg_marquardt_method(x_1, x_2, epsilon_1, epsilon_2, max_iter)
        result_plot(trajectory)


3. 结果显示

测试显示测试显示
Levenberg_Marquardt_4.9_3.9Levenberg_Marquardt_-2.9_1.9
Levenberg_Marquardt_0.1_-0.1Levenberg_Marquardt_-0.1_0.1
Levenberg_Marquardt_0_-3.8Levenberg_Marquardt_1_2.5

4. 结论

此处结果显示对比非线性最小二乘问题的数值方法 —— 从牛顿迭代法到高斯-牛顿法 (实例篇 V) 中应用高斯-牛顿法得到的结果显示可以看出,

- 列文伯格-马夸尔特法逐步收敛于极小值点的过程, 迭代步更加平滑, 较少振荡;

- 高斯-牛顿法在迭代过程中有点 “横冲直撞” 的意味.

所以列文伯格-马夸尔特法在实际中应用更广,

但高斯-牛顿法是后面这些更优方法的源头.


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Mindspore 公开课 - CodeGeeX

CodeGeeX: 多语言代码生成模型 CodeGeeX 是一个具有130亿参数的多编程语言代码生成预训练模型。CodeGeeX采用华为MindSpore框架实现&#xff0c;在鹏城实验室“鹏城云脑II”中的192个节点&#xff08;共1536个国产昇腾910 AI处理器&#xff09;上训练而成。截至2022年6月22日&…

非常好用的Mac清理工具CleanMyMac X 4.14.7 如何取消您对CleanMyMac X的年度订购

CleanMyMac X 4.14.7是Mac平台上的一款非常著名同时非常好用的Mac清理工具。全方位扫描您的Mac系统&#xff0c;让垃圾无处藏身&#xff0c;您只需要轻松单击2次鼠标左键即可清理数G的垃圾&#xff0c;就这么简单。瞬间提升您Mac速度。 CleanMyMac X 4.14.7下载地址&#xff1a…

WEB 3D技术 three.js 3D贺卡(1) 搭建基本项目环境

好 今天 我也是在网上学的 带着大家一起来做个3D贺卡 首先 我们要创建一个vue3的项目、 先创建一个文件夹 装我们的项目 终端执行 vue create 项目名称 例如 我的名字想叫 greetingCards 就是 vue create greetingcards因为这个名录 里面是全部都小写的 然后 下面选择 vue3 …

CSS实现平行四边形

1、为什么实现平行四边形 在日常开发过程中&#xff0c;有些时候我们可以会遇到一种情况&#xff0c;如可视化大屏中要求我们横线实现对应的进度条&#xff0c;但进度条的内容是由无数个平行四边形组装类似于进度条的形式&#xff0c;那么我们就需要使用CSS来进行对应的实现。 …

Python: vars()详细解释

vars() 是一个内置函数&#xff0c;用于返回一个对象的 __dict__ 属性。它接受一个对象作为参数&#xff0c;如果省略参数&#xff0c;它返回当前局部作用域的字典。 具体而言&#xff0c;vars() 的行为取决于参数的类型&#xff1a; 1. 没有参数&#xff1a; 如果没有提供参…

【MATLAB】EEMD+FFT+HHT组合算法

代码原理 EEMD&#xff08;经验模态分解&#xff09;FFT&#xff08;快速傅里叶变换&#xff09;HHT&#xff08;希尔伯特-黄变换&#xff09;组合算法是一种常用的信号处理和分析方法。这个组合算法包含了EEMD、FFT和HHT三个步骤&#xff0c;可以用于处理非线性和非平稳信号。…

【网络取证篇】Windows终端无法使用ping命令解决方法

【网络取证篇】Windows终端无法使用ping命令解决方法 以Ping命令为例&#xff0c;最近遇到ping命令无法使用的情况&#xff0c;很多情况都是操作系统"环境变量"被改变或没有正确配置导致—【蘇小沐】 目录 1、实验环境&#xff08;一&#xff09;无法ping命令 &a…

嵌入式学习-网络编程-Day2

思维导图 tcp通信流程 udp通信流程 作业1 写一个基于TCP协议的客户端来控制RobArm机械臂 代码 #include <myhead.h> #define SER_PORT 8888 #define SER_IP "192.168.122.71" #define CLI_PORT 6666 #define CLI_IP "192.168.122.36"int main(int…

FPN网络的实现原理详解

1 前言 FPN网络是一种常见的特征融合模块&#xff0c;在很多模型中都有运用&#xff0c;今天我们就结合代码和论文详细的搞清楚它到底是怎么一回事。 2 原理 原理直接看这一张图就可以了&#xff0c;很直观主要就是把对不同层的特征进行融合&#xff0c;重点还是在于代码的理…

MOS管驱动电流计算以及分立器件驱动电路

自记&#xff1a; 1.先根据mos数据手册查找参数&#xff0c;计算电流&#xff1b; 2.分立器件驱动电路图&#xff1b; 3.分立器件选择 仔细学&#xff0c;能看懂&#xff01; 1.计算电流&#xff1a; 2.分立器件驱动电流&#xff1a;两种&#xff0c;第一种反向&#xff0c…

实践学习PaddleScience飞桨科学工具包

实践学习PaddleScience飞桨科学工具包 动手实践&#xff0c;在实践中学习&#xff01;本项目可以在AIStudio平台一键运行&#xff01;地址&#xff1a;https://aistudio.baidu.com/projectdetail/4278591 本项目第一次执行会报错&#xff0c;再执行一次即可。若碰到莫名其妙的…

Linux操作系统——重定向与缓冲区

1.理解一下struct file内核对象 上一篇文章&#xff08;文件详解&#xff09;我们一直在谈&#xff0c;一个文件要被访问就必须要先被打开&#xff0c;打开之前就必须要先把文件加载到内存&#xff0c;同时呢我们的操作系统为了管理文件也会为我们的文件创建相对应的struct fi…

低频信号发生器

前言 最近我快期末考试了&#xff0c;有点忙着复习。没时间写文章&#xff0c;不过学会了焊接 挺开心的所以买几套。 焊得怎么样这就是我们今天故事的主角“低频信号发生器”&#xff08;由于要用到所以这是购买链接&#xff09; 好&#xff0c;故事开始&#xff1a; 如何将…

基于Java (spring-boot)的社团管理系统

一、项目介绍 系统管理员的功能概述&#xff1a; ①用户管理 a.注册用户账户 当一个新用户注册时&#xff0c;用户填写基本信息并上传。用户基本信息包括账号、 姓名、密码、手机、地址等信息。 b.用户信息管理 管理员可以查看系统所有用户的基本信息&#xff0c;并修改和…

乡镇景区外卖需求的上涨,现在下场做外卖平台服务晚不晚?

如今&#xff0c;在田间地头点外卖已经变成了现实。随着外卖市场的发展&#xff0c;外卖消费的多样化场景逐渐显现&#xff0c;不仅在田间可以订餐外卖&#xff0c;出门旅行的任何地方都可以点上一份热腾腾的外卖送到面前。特别是从去年开始旅游经济恢复之后&#xff0c;外卖也…

【C初阶——内存函数】鹏哥C语言系列文章,基本语法知识全面讲解

本文由睡觉待开机原创&#xff0c;转载请注明出处。 本内容在csdn网站首发 欢迎各位点赞—评论—收藏 如果存在不足之处请评论留言&#xff0c;共同进步&#xff01; 这里写目录标题 1.memcpy使用和模拟实现2.memmove的使用和模拟实现3.memset函数的使用4.memcpy函数的使用 1.m…

电阻表示方法和电路应用

电阻 电阻的表示方法 直标法 直标法是将电阻器的类别及主要技术参数的数值直接标注在电阻器表面上 通常用3位阿拉伯数字来标注片状电阻的阻值&#xff0c;其中第1位数代表阻值的第1位有效数&#xff1b;第2位数代表阻值的第二位有效数字&#xff1b;第3位数代表阻值倍率&…

力扣-刷MySQL(详细解析)

&#x1f389;欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克&#x1f379; ✨博客主页&#xff1a;小小恶斯法克的博客 &#x1f388;该系列文章专栏&#xff1a;重拾MySQL &#x1f379;文章作者技术和水平很有限&#xff0c;如果文中出现错误&am…

DataX的安装使用

DataX概述&#xff1a; DataX 是阿里巴巴集团内被广泛使用的离线数据同步工具/平台&#xff0c;实现包括 MySQL、Oracle、HDFS、Hive、OceanBase、HBase、OTS、ODPS 等各种异构数据源之间高效的数据同步功能。DataX采用了框架 插件 的模式&#xff0c;目前已开源&#xff0c;代…

救赎之道,就在其中

时光荏苒&#xff0c;不知不觉距离我踏入职场的第一天已经快一年了。最近也是看到平台举办年度征文活动&#xff0c;借此契机重新审视自己这两年来的成长历程&#xff0c;也希望对正在迷茫的人提供一些精神上的慰藉。 1.对未来的迷茫 如果要给两年前的自己打上标签&#xff0…