高斯牛顿法非线性优化

  1. 手写高斯牛顿
    原理看十四讲第6讲
    #include<iostream>
    #include<eigen3/Eigen/Core>
    #include<eigen3/Eigen/Dense>
    #include<opencv2/opencv.hpp>
    #include<vector>
    
    using namespace std;
    
    int main(int argc,char** argv)
    {
        /**
         * y = exp(ax^2 + bx + c) + w
         * 带有噪声 w - N(0,1^2)
         * 误差项 e = y-exp(ax^2 + bx + c)
         * */
        //真实参数
        double ar=1,br=2,cr=1;
        //初始估计值,很重要,有可能收敛到局部极小值
        double ae=2,be=-1,ce=5;
        //随机数产生
        cv::RNG rng;
    
        //生成样本 100个 
        int num=100;  
        //相当与100个方程,3个未知数,所以要最小二乘法
        vector<double> X, Y;
        for(int i=0;i<num;i++)
        {
            double x = i*(1.0/100);
            double y = exp(ar*x*x+br*x+cr) + rng.gaussian(1.0);
            X.push_back(x);
            Y.push_back(y);
        }
    
        double cost=0, lastcost=0;
        //跌代
        for(int iter=0;iter<100;iter++)
        {
            Eigen::Matrix<double,3,3> H = Eigen::Matrix<double,3,3>::Zero();
            Eigen::Matrix<double,3,1> g = Eigen::Matrix<double,3,1>::Zero();
            Eigen::Matrix<double,3,1> dx;
            cost = 0;///重要,别忘了,先重置为0
            double err=0;
            for(int i=0;i<num;i++)
            {
                double x=X[i];
                double y=Y[i];
                Eigen::Matrix<double,3,1> J = Eigen::Matrix<double,3,1>::Zero();  //雅可比矩阵
                /** J =d(e)/d(a,b,c) 对要求的量(a,b,c)求导
                 * J[0]  -x*x*exp(a*x*x+b*x+c)
                 * J[1] -x*exp(a*x*x+b*x+c)
                 * J[2] -exp(a*x*x+b*x+c)
                 * */
                J[0] = -x*x*exp(ae*x*x+be*x+ce);
                J[1] = -x*exp(ae*x*x+be*x+ce);
                J[2] = -exp(ae*x*x+be*x+ce);
                err = y-exp(ae*x*x+be*x+ce);
    
                H+=J*J.transpose();  //!!!!! 若干样本的 H 累加起来
                g+=-J*err;     //!!!!! 若干样本的 g 累加起来
                cost+=err*err;
            }
            dx=H.inverse()*g;
            if(iter>0&&cost>=lastcost)
            {
                cout<<"迭代次数: "<<iter<<endl;
                cout<<"cost = "<<lastcost<<endl;
                cout<<"a = "<<ae<<"\tb = "<<be<<"\tc = "<<ce<<endl;
                break;
            }
            cout<<"cost = "<<cost<<"\ta = "<<ae<<"\tb = "<<be<<"\tc = "<<ce<<endl;
            //更新估计量
            ae+=dx[0];be+=dx[1];ce+=dx[2];
            
            lastcost=cost;
        }
    
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值