高斯牛顿法
主要思想是将\(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
#include
#include
#include
#include
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 x_data,y_data; //生成观测数据
for(int i=0;i0&&cost>=lastCost){
cout<<"cost:"<=last cost:"<time_used=chrono::duration_cast>(t2-t1);
cout<<"solve time cost"<
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})