高斯牛顿法在具体工程中的应用——C++版
说明:本文章没有用大量篇幅来讲述高斯牛顿的原理和数学中的应用,而是用具体的代码来说明,具体是怎么应用的。 如果对高斯牛顿法的原理比较感兴趣,可以阅读以下链接中的内容: https://zhuanlan.zhihu.com/p/42383070
概述:高斯牛顿法解决的是工程中的非线性最小二乘问题,如SLAM。具体代码如下:
首先我们需要定义以下参数:
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 = 0.01;
cv::RNG rng;
其次,我们要设置一个数据集,每一个问题的数据集是不一样的,自己设置
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));
}
第三,开始具体的应用:
int iterations = 100;
double cost = 0, lastCost = 0;
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];
double error = 0;
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);
cout<<"J"<<i<<": "<<J.transpose()<<endl;
H += J * J.transpose();
cout<<"H:"<<H.transpose()<<endl;
b += J*(-error) ;
cout<<"b: "<<b.transpose()<<endl;
cost += error * error;
}
Vector3d dx;
cout<<"H:"<< H<<endl;
cout<<"B:"<< b<<endl;
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 << endl;
break;
}
ae += dx[0];
be += dx[1];
ce += dx[2];
lastCost = cost;
cout << "total cost: " << cost << endl;
}
cout << "estimated abc = " << ae << ", " << be << ", " << ce << endl;
return 0;
}
|