首页 > 其他 > 详细

非线性优化一个曲线拟合

时间:2020-04-11 12:14:45      阅读:91      评论:0      收藏:0      [点我收藏+]

  将代码和实际理论结合起来才能更好的理解理论上是怎么实现的,参考用高博十四讲的理论加实践亲手试一下,感觉公式和代码才能结合起来。不能做到创新,至少做到了解和理解

曲线拟合问题:

  考虑这样一条曲线:$y = \exp (a{x^2} + bx + c) + w$,其中a,b,c为曲线的参数,w为高斯噪声,满足$w = (0,{\sigma ^2})$,假设有N个关于x,y的观测数据点,想根据这些数据点求出曲线的参数,(误差噪声)最小二乘

\[\mathop {\min }\limits_{a,b,c} \frac{1}{2}\sum\limits_{i = 1}^N {{{\left\| {{y_i} - \exp (ax_i^2 + b{x_i} + c)} \right\|}^2}} \]

  我们首先明确我们要估计的变量是a,b,c这三个系数,思路是先根据模型生成x,y的真值,然后在真值中加入高斯分布的噪声。随后使用高斯牛顿法从带噪声的数据拟合参数模型。定义误差为:${e_i} = {y_i} - \exp (ax_i^2 + b{x_i} + c)$,求取雅克比矩阵:

\[{J_i} = \left[ {\begin{array}{*{20}{c}}
{\frac{{\partial {e_i}}}{{\partial a}} = - x_i^2\exp (ax_i^2 + b{x_i} + c)}\\
{\frac{{\partial {e_i}}}{{\partial b}} = - {x_i}\exp (ax_i^2 + b{x_i} + c)}\\
{\frac{{\partial {e_i}}}{{\partial c}} = - \exp (ax_i^2 + b{x_i} + c)}
\end{array}} \right]\]

高斯牛顿法的增量方程为:

\[\left( {\sum\limits_{i = 1}^{100} {{J_i}{{({\sigma ^2})}^{ - 1}}{J_i}^T} } \right)\Delta {x_k} = \sum\limits_{i = 1}^{100} { - {J_i}{{({\sigma ^2})}^{ - 1}}{e_i}} \]

 1 #include <iostream>
 2 #include <chrono>
 3 #include <opencv2/opencv.hpp>
 4 #include <Eigen/Core>
 5 #include <Eigen/Dense>
 6 using namespace cv;
 7 using namespace std;
 8 using namespace Eigen;
 9 
10 int main(int argc, char **argv) {
11     double ar = 1.0, br = 2.0, cr = 1.0;         // 真实参数值
12     double ae = 2.0, be = -1.0, ce = 5.0;        // 估计参数值,赋给一个初值,然后在这个初值的基础上进行变化量的迭代
13     int N = 100;                                 // 数据点
14     double w_sigma = 1.0;                        // 噪声Sigma值
15     double inv_sigma = 1.0 / w_sigma;           // 后面噪声1/(Sigma^2)值会用
16     cv::RNG rng;                                 // OpenCV随机数产生器
17 
18     vector<double> x_data, y_data;      // 用于拟合的观测数据
19     for (int i = 0; i < N; i++) {
20         double x = i / 100.0;
21         x_data.push_back(x);
22         y_data.push_back(exp(ar * x * x + br * x + cr) + rng.gaussian(w_sigma * w_sigma));
23     }
24 
25     // 开始Gauss-Newton迭代
26     int iterations = 100;    // 迭代次数
27     double cost = 0, lastCost = 0;  // 本次迭代的cost和上一次迭代的cost最小二乘值,通过此值衡量迭代是否到位,进行终止
28 
29     chrono::steady_clock::time_point t1 = chrono::steady_clock::now();//计算迭代时间用
30     for (int iter = 0; iter < iterations; iter++) {
31 
32         Matrix3d H = Matrix3d::Zero();             // Hessian = J^T W^{-1} J in Gauss-Newton
33         Vector3d b = Vector3d::Zero();             // bias
34         cost = 0;
35 
36         for (int i = 0; i < N; i++) {
37             double xi = x_data[i], yi = y_data[i];  // 第i个数据点
38             double error = yi - exp(ae * xi * xi + be * xi + ce);
39             Vector3d J; // 雅可比矩阵
40             J[0] = -xi * xi * exp(ae * xi * xi + be * xi + ce);  // de/da
41             J[1] = -xi * exp(ae * xi * xi + be * xi + ce);  // de/db
42             J[2] = -exp(ae * xi * xi + be * xi + ce);  // de/dc
43 
44             H += inv_sigma * inv_sigma * J * J.transpose();//构造Hx=b
45             b += -inv_sigma * inv_sigma * error * J;
46 
47             cost += error * error;//计算最小二乘结果,看是否是最小的
48         }
49 
50         // 求解线性方程 Hx=b
51         Vector3d dx = H.ldlt().solve(b);
52         if (isnan(dx[0])) {
53             cout << "result is nan!" << endl;
54             break;
55         }
56 
57         if (iter > 0 && cost >= lastCost) {
58             cout << "cost: " << cost << ">= last cost: " << lastCost << ", break." << endl;
59             break;
60         }
61 
62         ae += dx[0];//更新迭代量,继续迭代寻找最优值
63         be += dx[1];
64         ce += dx[2];
65 
66         lastCost = cost;
67 
68         cout << "total cost: " << cost << ", \t\tupdate: " << dx.transpose() <<
69             "\t\testimated params: " << ae << "," << be << "," << ce << endl;
70     }
71 
72     chrono::steady_clock::time_point t2 = chrono::steady_clock::now();
73     chrono::duration<double> time_used = chrono::duration_cast<chrono::duration<double>>(t2 - t1);//给出优化用时
74     cout << "solve time cost = " << time_used.count() << " seconds. " << endl;
75 
76     cout << "estimated abc = " << ae << ", " << be << ", " << ce << endl;
77     waitKey(0);
78     return 0;
79 
80 }

 技术分享图片

 

非线性优化一个曲线拟合

原文:https://www.cnblogs.com/fuzhuoxin/p/12678498.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!