打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Levenberg–Marquardt算法

算法描述及示例引用自“Machine Learning An Algorithm Perspective 2nd Edition”

使用C++进行浮点数的比较时,一定要注意容差问题。

#include <iostream>#include <math.h>#include <Eigen/Core>#include <Eigen/Dense>using namespace std;double rx(const Eigen::MatrixXd &x,int i){    switch(i)    {        case 0: return 10*(x(1,0) - x(0,0) * x(0,0));        case 1: return 1-x(0,0);     }    return INT_MAX;}double fx(const Eigen::MatrixXd &x){    return 100 *(x(1,0) - x(0,0) * x(0,0)) * (x(1,0) - x(0,0) * x(0,0)) + (1-x(0,0)) * (1-x(0,0));}double Jac(const Eigen::MatrixXd &x,int i,int j){    int index = 2*i+j;    switch(index)    {    case 0: return -20 * x(0,0);    case 1: return 10.0;    case 2: return -1.0;    case 3: return 0.0;    }}void computeRelatedValues(const Eigen::MatrixXd& x,double &fval,Eigen::MatrixXd &r,Eigen::MatrixXd &J,Eigen::MatrixXd &grad){    fval = fx(x);    for (int i = 0;i<2;++i)    {        r(i,0) = rx(x,i);    }    for(int i = 0;i<2;++i)        for(int j = 0;j<2;++j)        {            J(i,j) = Jac(x,i,j);        }    grad = J.transpose() * r;}void LM(){    Eigen::MatrixXd x(2,1);    x(0,0) = -1.92;    x(1,0) = 2.0;    int max_iter = 100;    double func_tol = pow(10.0,-5);    int iter = 0;    double fval = INT_MAX;    Eigen::MatrixXd r(2,1);    Eigen::MatrixXd J(2,2);    Eigen::MatrixXd grad;    computeRelatedValues(x,fval,r,J,grad);    double nu = 0.01;    cout<<fval<<" ["<<x(0,0)<<" "<<x(1,0)<<"] "<<grad.norm()<<" "<<nu<<endl;    while(iter < max_iter && grad.norm() > func_tol)    {        ++iter;        computeRelatedValues(x,fval,r,J,grad);        Eigen::MatrixXd I = Eigen::MatrixXd::Identity(2,2);        Eigen::MatrixXd H = J.transpose() *J + nu*I;        Eigen::MatrixXd x_new = Eigen::MatrixXd::Zero(2,1);        int iter1 = 0;        double diff = (x-x_new).norm();        //注意如何比较两个向量是否相等        while(diff > pow(10.0,-5) && iter1 < max_iter)        {            ++iter1;            Eigen::MatrixXd delta_x = H.colPivHouseholderQr().solve(grad);            cout<<delta_x<<endl;            Eigen::MatrixXd x_new = x - delta_x;            cout<<x_new<<endl;            double fval_new = INT_MAX;            Eigen::MatrixXd r_new(2,1);            Eigen::MatrixXd J_new(2,2);            Eigen::MatrixXd grad_new;            computeRelatedValues(x_new,fval_new,r_new,J_new,grad_new);            double rho = abs(fval - fval_new) / (grad.transpose() * (x_new - x)).norm();            if (rho > 0)            {                x = x_new;                diff = (x - x_new).norm();                cout<<diff<<endl;                if (rho > 0.25)                {                    nu = nu /10;                }            }            else            {                nu = nu *10;            }        }         cout<<fval<<" ["<<x(0,0)<<" "<<x(1,0)<<"] "<<grad.norm()<<" "<<nu<<endl;    }}int main(){    LM();    return 0;}
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
卡尔曼滤波的C++实现
Map a Eigen Matrix to an C array
Eigen 3.2稀疏矩阵入门
Ubuntu安装eigen
(C++)STL中map按照vaule来排序
C++ unordered
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服