Levenberg-Marquardt 的 MATLAB 代码

Posted 菠菜僵尸

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Levenberg-Marquardt 的 MATLAB 代码相关的知识,希望对你有一定的参考价值。

参考资料:

1,《精通MATLAB最优化计算(第2版)》作者:龚纯 等 的 第9章 9.3 小节 L-M 法

2,《数值分析》 作者:Timothy Sauer 的 第4章 4.4节 非线性最小二乘的 例子

 

第一本书里头虽然有代码,然而有错误,修正了错误之处

% opti_LM_test1
% 测试了 MATLAB最优化 书中的 L-M 的例子,结果是正确的
clear all;clc;close all;

syms t;
f = ...
    [t^2+t-1;
     2*t^2-3];
S = transpose(f)*f;

f_var = symvar(f);

t_init = -5  % 自变量的初始值
%%
u = 2
v = 1.5
beta = 0.4
eps = 1.0e-6

x = t_init;
x = transpose(x);% 删

jacobian_f = jacobian(f,f_var);
tol = 1;
%%  subs以后居然不是数值,而是符号!还要转换成double类型!!!
while tol>eps
    fxk = double(subs(f,f_var,x));
    Sxk = double(subs(S,f_var,x));  % step2: 计算 fxk Sxk
    
    delta_fxk = double(subs(jacobian_f,f_var,x));  % step3: 计算 delta_fxk
    
    delta_Sxk = transpose(delta_fxk)*fxk;   % step4: 计算 delta_Sxk

    while 1
        % step5: 计算Q,并解方程(Q+uI)delta_x = -delta_Sxk
        Q = transpose(delta_fxk)*delta_fxk;
        dx = -(Q+u*eye(size(Q)))\delta_Sxk;
        
        x1 = x + dx;
        
        fxk = double(subs(f,f_var,x1));
        Sxk_new = double(subs(S,f_var,x1));
        
        tol = norm(dx);   % step6: 计算中止条件 norm(dx)<eps 是否满足,不满足转step 7
        if tol<=eps
            break;
        end

        % step7: 
        if Sxk_new < Sxk+beta*transpose(delta_Sxk)*dx
            u = u/v;
            break;
        else
            u = u*v;
            continue;
        end
    end
    
    x = x1;
end

t = x1
minf = double(subs(S,f_var,t))

测试的结果是正确的。

 

参考第二本书中的例子把上述算法改成了一个多变量的程序,基本上没什么改动

% opti_LM_test2
% 测试了 数值分析 Timothy Sauer 中 4.4节中的 4.19例
clear all;clc;close all;

x1 = -1; y1 = 0;
x2 = 1; y2 = 1/2;
x3 = 1; y3 = -1/2;

R1 = 1; R2 = 1/2; R3 = 1/2;
%
syms x y;
r1 = sqrt( (x-x1)^2 + (y-y1)^2 )-R1;
r2 = sqrt( (x-x2)^2 + (y-y2)^2 )-R2;
r3 = sqrt( (x-x3)^2 + (y-y3)^2 )-R3;

r = ...
    [r1;
     r2;
     r3]
%
f = r
clear r1 r2 r3 R1 R2 R3 x1 x2 x3 y1 y2 y3 x y r;
%% 
S = transpose(f)*f
f_var = symvar(f)

t_init = [0 0]    %  初始值,要给出
u = 2
v = 1.5
beta = 0.4
eps = 1.0e-6
tol = 1
%% 
x = t_init

jacobian_f = jacobian(f,f_var)
%% 
while tol>eps
    fxk = double(subs(f,f_var,x));
    Sxk = double(subs(S,f_var,x));  % step2: 计算 fxk Sxk
    
    delta_fxk = double(subs(jacobian_f,f_var,x));  % step3: 计算 delta_fxk
    
    delta_Sxk = transpose(delta_fxk)*fxk;   % step4: 计算 delta_Sxk

    while 1
        % step5: 计算Q,并解方程(Q+uI)delta_x = -delta_Sxk
        Q = transpose(delta_fxk)*delta_fxk;
        dx = -(Q+u*eye(size(Q)))\delta_Sxk;
        
        x1 = x + dx‘; % 注意转置
        
        fxk = double(subs(f,f_var,x1));
        Sxk_new = double(subs(S,f_var,x1));
        
        tol = norm(dx);   % step6: 计算中止条件 norm(dx)<eps 是否满足,不满足转step 7
        if tol<=eps
            break;
        end

        % step7: 
        if Sxk_new < Sxk+beta*transpose(delta_Sxk)*dx
            u = u/v;
            break;
        else
            u = u*v;
            continue;
        end
    end
    
    x = x1;
end
%% 
format short;
opti_var_value = x1
minf = double(subs(S,f_var,opti_var_value))

结果也是正确的

细节和原理以后再补充

以上是关于Levenberg-Marquardt 的 MATLAB 代码的主要内容,如果未能解决你的问题,请参考以下文章

Levenberg-Marquardt迭代(LM算法)-改进Newton法

Levenberg-Marquardt 的 MATLAB 代码

是否可以将 Tensorflow Graphics 的 Levenberg-Marquardt 优化器与 Tensorflow 2.0 模型集成?

如何估计 Encog 使用 Levenberg-Marquardt 算法用特定样本集训练特定网络所需的 RAM 量?

V-rep学习笔记:机器人逆运动学数值解法(Damped Least Squares / Levenberg-Marquardt Method)

使用 levenberg-marquardt 优化 欧式空间中的三维点变换关系