当前位置: 首页 > ops >正文

Eigen实现非线性最小二乘拟合 + Gauss-Newton算法

下面是使用 Eigen 实现的 非线性最小二乘拟合 + Gauss-Newton 算法 的完整示例,拟合模型为:


拟合目标模型:

y = exp ⁡ ( a x 2 + b x + c ) y = \exp(a x^2 + b x + c) y=exp(ax2+bx+c)

已知一组带噪声数据点 ( x i , y i ) (x_i, y_i) (xi,yi),使用 高斯-牛顿法 求最优参数 ( a , b , c ) (a, b, c) (a,b,c)


所需库

  • Eigen:矩阵运算
  • cmath:指数函数

高斯-牛顿迭代步骤(简要)

  1. 初始猜测参数 ( a , b , c ) (a, b, c) (a,b,c)

  2. 对每个点计算残差:

    r i = y i − exp ⁡ ( a x i 2 + b x i + c ) r_i = y_i - \exp(a x_i^2 + b x_i + c) ri=yiexp(axi2+bxi+c)

  3. 构造雅可比矩阵 J i J_i Ji(每个点对参数的偏导数):

    J i = [ − x i 2 ⋅ exp ⁡ ( f ) , − x i ⋅ exp ⁡ ( f ) , − exp ⁡ ( f ) ] J_i = \left[ -x_i^2 \cdot \exp(f), -x_i \cdot \exp(f), -\exp(f) \right] Ji=[xi2exp(f),xiexp(f),exp(f)]

    其中 f = a x i 2 + b x i + c f = a x_i^2 + b x_i + c f=axi2+bxi+c

  4. 累加构建 H = J T J H = J^T J H=JTJ b = − J T r b = -J^T r b=JTr

  5. 解线性系统 H ⋅ Δ x = b H \cdot \Delta x = b HΔx=b

  6. 更新参数 θ ← θ + Δ x \theta \leftarrow \theta + \Delta x θθ+Δx,判断是否收敛


示例代码:非线性拟合 + 高斯牛顿

#include <iostream>
#include <vector>
#include <cmath>
#include <Eigen/Dense>using namespace std;
using namespace Eigen;// 生成数据
void generateData(vector<double>& x_data, vector<double>& y_data, double a, double b, double c, int N = 100) {x_data.reserve(N);y_data.reserve(N);for (int i = 0; i < N; ++i) {double x = i / 100.0;double y = exp(a * x * x + b * x + c) + 0.05 * ((rand() % 100) / 100.0 - 0.5);  // 加噪声x_data.push_back(x);y_data.push_back(y);}
}int main() {// 模拟数据double true_a = 1.0, true_b = 2.0, true_c = 1.0;vector<double> x_data, y_data;generateData(x_data, y_data, true_a, true_b, true_c);// 初始估计值double a = 0.0, b = 0.0, c = 0.0;const int iterations = 100;double lastCost = 0;for (int iter = 0; iter < iterations; ++iter) {Matrix3d H = Matrix3d::Zero();    // 海森矩阵 H = J^T * JVector3d g = Vector3d::Zero();    // 梯度向量 g = -J^T * rdouble cost = 0;for (size_t i = 0; i < x_data.size(); ++i) {double x = x_data[i], y = y_data[i];double fx = exp(a * x * x + b * x + c);double error = y - fx;cost += error * error;// 构造雅可比矩阵 J_iVector3d J;J[0] = -x * x * fx;  // ∂f/∂aJ[1] = -x * fx;      // ∂f/∂bJ[2] = -fx;          // ∂f/∂cH += J * J.transpose();   // 累加 J^T * Jg += -error * J;          // 累加 -J^T * r}// 求解 H Δx = gVector3d dx = H.ldlt().solve(g);if (isnan(dx[0])) {cout << "Update is NaN, stopping." << endl;break;}if (iter > 0 && cost >= lastCost) {cout << "Cost increased, stopping." << endl;break;}a += dx[0];b += dx[1];c += dx[2];lastCost = cost;cout << "Iteration " << iter << ": cost = " << cost << ", update = " << dx.transpose() << ", parameters = "<< a << " " << b << " " << c << endl;}cout << "\nFinal result: a = " << a << ", b = " << b << ", c = " << c << endl;return 0;
}

输出结果(收敛示意):

Iteration 0: cost = 3.94, update = 0.57 1.85 0.95, parameters = 0.57 1.85 0.95
...
Iteration 9: cost = 0.00017, update = 1.2e-6 1.7e-6 9.1e-7, parameters = 0.9999 2.0001 1.0000Final result: a = 0.9999, b = 2.0001, c = 1.0000

小结

  • 高斯牛顿适合残差函数是非线性的情形(比如指数、多项式等)
  • 可替换为 Levenberg-Marquardt 算法处理奇异或非收敛情况
  • 更复杂系统可迁移至 Ceres Solver / GTSAM

http://www.xdnf.cn/news/10693.html

相关文章:

  • RabbitMQ如何保证消息可靠性
  • python中可以对数组使用的所有方法
  • 工作自动化——工作自动提炼--智能编程——仙盟创梦IDE
  • B站缓存视频数据m4s转mp4
  • 从零开始,搭建一个基于 Django 的 Web 项目
  • django入门-orm数据库操作
  • unity UI Canvas“高”性能写法
  • 如何轻松地将数据从 iPhone传输到iPhone 16
  • 【JSON-to-Video】设置背景视频片断
  • 【OCCT+ImGUI系列】011-Poly-Poly_Triangle三角形面片
  • GIC v3 v4 虚拟化架构
  • 业态即战场:零售平台的生意模型与系统设计解构
  • Elasticsearch集群最大分片数设置详解:从问题到解决方案
  • [特殊字符] Unity UI 性能优化终极指南 — ScrollRect篇
  • spring-boot-admin实现对微服务监控
  • 提升四级阅读速度方法
  • python学习(一)
  • git checkout C1解释
  • Windows 下彻底删除 VsCode
  • 开疆智能Profinet转Profibus网关连接CMDF5-8ADe分布式IO配置案例
  • RequestRateLimiterGatewayFilterFactory
  • 亚马逊Woot提报常见问题第一弹
  • es 的字段类型(text和keyword)
  • PostgreSQL的扩展 passwordcheck
  • 深入剖析物联网边缘计算技术:架构、应用与挑战
  • 学习threejs,交互式神经网络可视化
  • 基于Java的OPCDA采集中间件
  • Vue.js教学第十八章:Vue 与后端交互(二):Axios 拦截器与高级应用
  • Windows 下部署 SUNA 项目:虚拟环境尝试与最终方案
  • 下载并运行自制RAG框架