首页 > 其他分享 >高斯牛顿法

高斯牛顿法

时间:2022-10-06 10:55:05浏览次数:41  
标签:triangle 高斯 gaussNewton 牛顿 1.0 include

高斯牛顿法

主要思想是将\(f(x)\)进行一阶的泰勒展开。然后求解其最小二乘解。

\[f(x_k+\triangle x_k)\approx f(x_k)+J(x_k)^T \triangle x_k \]

求解问题变为:

\[\triangle x^*=argmin _{\triangle x}\frac {1}{2}\lvert f(x)+J(x)^T\triangle x\rvert ^2 \]

\[\frac {1}{2}\lvert {f(x)+J(x)^T\triangle x}\rvert ^2=\frac {1}{2}(\lvert f(x) \rvert ^2+2f(x)J(x)^T\triangle x+\triangle x^TJ(x)J(x)^T\triangle x \]

右侧求导,$$J(x)f(x)+J(x)J^T(x)\triangle x=0$$
则,可得 高斯-牛顿方程:

\[J(x)J^T(x)\triangle x=-J(x)f(x) \]

这个方程是关于变量\(\delta x\)的线性方程组,我们称他为增量方程,也叫做高斯牛顿方程(Gauss-Newton equation)或者正规方程(Normal equation)。
左边的定义为\(H\)右边的定义为\(g\):

\[H\triangle x=g \]

对比牛顿法,其实高斯-牛顿法运用\(JJ^T\)作为牛顿法中二阶Hessian矩阵的近似,从而省略了H的估计
算法流程:
1.给定初始值\(x_0\)
2.对于第k次迭代,求出当前的雅可比矩阵\(J(x_k)\)和误差\(f(x_k)\)
3.求解增量方程:\(H\triangle x_k =g\)
4.若\(\triangle x_k\)足够小则停止。否则,令\(x_{k+1}=x_k+\triangle x_k\),返回第2步

手写高斯牛顿法拟合曲线

#include<iostream>
#include<opencv2/opencv.hpp>
#include<Eigen/Core>
#include<Eigen/Dense>
#include <chrono>

using namespace std;
using namespace Eigen;

int main(int argc,char **argv){
    double ar=1.0,br=2.0,cr=1.0;    //真实参数
    double ae=2.0,be=-1.0,ce=5.0;   //估计参数值
    int N=100;                      //数据点
    double w_sigma=1.0;
    double inv_sigma=1.0/w_sigma;   
    cv::RNG rng;                    //OpenCV随机数生成
    
    vector<double> x_data,y_data;   //生成观测数据
    for(int i=0;i<N;i++){
        double x=i/100.0;
        x_data.push_back(x);
        y_data.push_back(exp(ar*x*x+br*x+cr)+rng.gaussian(w_sigma*w_sigma));
    }
    
    //开始Gauss-Newton迭代
    int iterations=100;  //迭代次数
    double cost=0,lastCost=0;   //本次迭代的cost和上一次的Cost
    
    chrono::steady_clock::time_point t1=chrono::steady_clock::now();
    for(int iter=0;iter<iterations;iter++){
        
        Matrix3d H=Matrix3d::Zero();
        Vector3d b=Vector3d::Zero();
        cost=0;
        
        for(int i=0;i<N;i++){
            double xi=x_data[i],yi=y_data[i];   //第i个数据点
            double error=yi-exp(ae*xi*xi+be*xi+ce);
            Vector3d J;//计算雅可比矩阵
            J[0]=-xi*xi*exp(ae*xi*xi+be*xi+ce);
            J[1]=-xi*exp(ae*xi*xi+be*xi+ce);
            J[2]=-exp(ae*xi*xi+be*xi+ce);
            
            //H+=J*J.transpose();
            //b+=-error*J;//发现两种结果相同,这里应该是因为分母为1 的原因,但是究竟哪一种是对的?
            H+=inv_sigma*inv_sigma*J*J.transpose();
            b+=-inv_sigma*inv_sigma*error*J;
            
            cost+=error*error;
        }
        
        //求解线性方程Hx=b
        Vector3d dx=H.ldlt().solve(b);
        if(isnan(dx[0])){
            cout<<"result is nan!"<<endl;
            break;
        }
        
        if(iter>0&&cost>=lastCost){
            cout<<"cost:"<<cost<<">=last cost:"<<lastCost<<",break"<<endl;
            break;
        }
        
        ae+=dx[0];
        be+=dx[1];
        ce+=dx[2];
        
        lastCost=cost;
        
        cout<<"total cost:"<<cost<<",\t\tupdate:"<<dx.transpose()<<
        "\t\testimated params:"<<ae<<","<<be<<","<<ce<<endl;
    }
    
    chrono::steady_clock::time_point t2=chrono::steady_clock::now();
    chrono::duration<double>time_used=chrono::duration_cast<chrono::duration<double>>(t2-t1);
    cout<<"solve time cost"<<time_used.count()<<"seconds."<<endl;
    cout<<"estimate abc="<<ae<<","<<be<<","<<ce<<endl;
    return 0;
    
}

CMakeLists.txt文件

cmake_minimum_required(VERSION 2.8)
project(gaussNewton)
set(CMAKE_BUILD_TYPE Release)

find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})

include_directories("/usr/include/eigen3")

add_executable(gaussNewton gaussNewton.cpp)
target_link_libraries(gaussNewton ${OpenCV_LIBS})

标签:triangle,高斯,gaussNewton,牛顿,1.0,include
From: https://www.cnblogs.com/code-fun/p/16757063.html

相关文章

  • 异或方程组高斯消元模板
    inlinevoidsolve(intn){for(inti=1,top=1;i<=n;i++,top++){intcur=0;for(intj=top;j<=n;j++)if(m......
  • 详解线性回归-最小二乘法及其几何意义&最小二乘法-概率视角-高斯噪声-MLE【白板推导系
    $$\begin{gathered}D=\left{(x_{1},y_{1}),(x_{2},y_{2}),\cdots,(x_{N},y_{N})\right}\x_{i}\in\mathbb{R}^{p},y_{i}\in\mathbb{R},i=1,2,\cdots,N\X=\begin{pmat......
  • [补档]高斯消元做题记录/或曰 学习笔记
    早就退役啦!乍一看挺水的。P2455[SDOI2006]线性方程组板子题。codeP4035[JSOI2008]球形空间产生器给定一个\(n\)维的球体上\(n+1\)个点的坐标\(a_{i,j}\)。求......
  • [数值分析]牛顿迭代法Newton!!!
    牛顿迭代法Newton!!!牛顿迭代法的基本思想牛顿迭代法是一种用来求解方程的方法,它的基本思想是:如果一个函数在某一点的切线是直线,那么迭代下一次产生的值就是切线与x轴的......
  • 高斯消元详解
    高斯消元一,什么是高斯消元?用来解决需要解方程组的题目时所用的一种算法。适用于以下该种形式的式子:\[\begin{cases}a_1=k_{1,1}*x_{1,1}+k_{1,2}*x_{1,2}+\cdots+k_{1......
  • 实例92 高斯消去法
    #include<stdio.h>#include<stdlib.h>#include<malloc.h>#include<math.h>intGS(int,double**,double*,double);double**TwoArrayAlloc(int,int);voidTwo......
  • 实例85 牛顿迭代法求解方程
    #include<stdio.h>#include<math.h>#include<stdlib.h>intFunction(double,double*,double*);intNewton(double*,double,int);intFunction(x,f,dy)dou......
  • 高斯消去
    importjava.util.Scanner;publicclassGaoSi{/***列主元高斯消去法*/staticdoubleA[][];staticdoubleb[];staticdoublex[];sta......
  • 高斯消去法(Gauss-Jordan方法)的Python实现
    高斯消去法的改进形式为Gauss-JordanEliminationMethod,要求每一行的主元素所在列元素全部消去为0,除了主元素本身。区别如下:代码实现如下:#-*-coding:utf-8-*-#@......
  • 【瞎口胡】多项式牛顿迭代
    前言如果完全不会求导和积分,以及泰勒展开,这里有一个实用性很强的教程3blue1brown-微积分的本质。多项式牛顿迭代给定函数\(G(x)\),求多项式\(F(x)\)使得\(G(F(x))......