本文使用 Zhihu On VSCode 创作并发布

0 前言

自动驾驶开发中经常涉及到多项式曲线拟合,本文详细描述了使用最小二乘法进行多项式曲线拟合的数学原理,通过样本集构造范德蒙德矩阵,将一元 N 次多项式非线性回归问题转化为 N 元一次线性回归问题,并基于线性代数 C++ 模板库——Eigen 进行了实现,最后,比较了几种实现方法在求解速度与求解精度上的差异。

1 最小二乘法概述

最小二乘法(Least Square Method,LSM)通过最小化误差(也叫残差)的平方和寻找数据的最优函数匹配。

假设给定一组样本数据集

内各数据点
来自于对多项式

的多次采样,其中:

  • 为样本维度
  • 为多项式阶数
  • 为多项式的各项系数

针对样本数据集

内各数据点的误差平方和为:

最小二乘法认为,最优函数的各项系数

应使得误差平方和
取得极小值。最小二乘法与

极大似然估计有着密切的联系,关于最小二乘法的数学本质可参考文章《如何理解最小二乘法?》。

2 最小二乘法求解多项式曲线系数向量的数学推导

2.1 代数法

由于最优函数的各项系数

使得误差平方和
取得极小值,因而,对于最优函数而言,其误差平方和
对各多项式系i数
的偏导数应满足:

整理上式,

分别取
时,有:

转化为矩阵形式,令:

则有:

使用样本数据集构造出矩阵

和矩阵
后,便可由上式解得最优函数的系数向量

2.2 矩阵法

在代数法中,构造矩阵

和矩阵
较为繁琐且计算量大,我们尝试直接将误差平方和
拆解为矩阵形式。令:

则误差平方和

可写成:
是一个

范德蒙矩阵(Vandermonde Matrix),

仍然是多项式系数构成的系数向量,
是样本数据集的输出向量。对于最优函数,应满足:

可求得最优函数的多项式系数向量

为:

相比代数法求解中的矩阵

和矩阵
,矩阵法中的矩阵
和矩阵
构造起来更加简单。仔细观察,可以发现:

说明两个解法是相通的。

3 代码实现

通过C++ Eigen库实现了矩阵法中的求解方式,Eigen版本为v3.3.7,运行环境为Windows10,Eigen库安装路径为 D:eigen-3.3.7

函数声明

#ifndef LEAST_SQUARE_METHOD_H
#define LEAST_SQUARE_METHOD_H#include <D:eigen-3.3.7EigenDense>
#include <vector>using namespace std;/*** @brief Fit polynomial using Least Square Method.* * @param X X-axis coordinate vector of sample data.* @param Y Y-axis coordinate vector of sample data.* @param orders Fitting order which should be larger than zero. * @return Eigen::VectorXf Coefficients vector of fitted polynomial.*/
Eigen::VectorXf FitterLeastSquareMethod(vector<float> &X, vector<float> &Y, uint8_t orders);#endif

函数实现

#include "LeastSquareMethod.h"/*** @brief Fit polynomial using Least Square Method.* * @param X X-axis coordinate vector of sample data.* @param Y Y-axis coordinate vector of sample data.* @param orders Fitting order which should be larger than zero. * @return Eigen::VectorXf Coefficients vector of fitted polynomial.*/
Eigen::VectorXf FitterLeastSquareMethod(vector<float> &X, vector<float> &Y, uint8_t orders)
{// abnormal input verificationif (X.size() < 2 || Y.size() < 2 || X.size() != Y.size() || orders < 1)exit(EXIT_FAILURE);// map sample data from STL vector to eigen vectorEigen::Map<Eigen::VectorXf> sampleX(X.data(), X.size());Eigen::Map<Eigen::VectorXf> sampleY(Y.data(), Y.size());Eigen::MatrixXf mtxVandermonde(X.size(), orders + 1);  // Vandermonde matrix of X-axis coordinate vector of sample dataEigen::VectorXf colVandermonde = sampleX;              // Vandermonde column// construct Vandermonde matrix column by columnfor (size_t i = 0; i < orders + 1; ++i){if (0 == i){mtxVandermonde.col(0) = Eigen::VectorXf::Constant(X.size(), 1, 1);continue;}if (1 == i){mtxVandermonde.col(1) = colVandermonde;continue;}colVandermonde = colVandermonde.array()*sampleX.array();mtxVandermonde.col(i) = colVandermonde;}// calculate coefficients vector of fitted polynomialEigen::VectorXf result = (mtxVandermonde.transpose()*mtxVandermonde).inverse()*(mtxVandermonde.transpose())*sampleY;return result;
}

在函数实现中使用了一些Eigen的小技巧:

  • 使用 Eigen::Map 直接将样本数据由 std::vector 映射到 Eigen::VectorXf 参与运算,避免了循环数据读入
  • 通过 array() 方法累乘样本数据的X向量,逐列构造范德蒙矩阵,同样避免了大量的循环数据处理

拟合测试

#include <iostream>
#include "LeastSquareMethod.h"using namespace std;int main()
{float x[5] = {1, 2, 3, 4, 5};float y[5] = {7, 35, 103, 229, 431};vector<float> X(x, x + sizeof(x) / sizeof(float));vector<float> Y(y, y + sizeof(y) / sizeof(float));Eigen::VectorXf result(FitterLeastSquareMethod(X, Y, 3));cout << "nThe coefficients vector is: n" << endl;for (size_t i = 0; i < result.size(); ++i)cout << "theta_" << i << ": " << result[i] << endl;return 0;
}

运行编译后的可执行程序,得到如下结果:

$ ./LSM.exeThe coefficients vector is: theta_0: 1.30698
theta_1: 0.924561
theta_2: 2.0032
theta_3: 2.99976

点击这里下载完整的工程Demo,工程使用了 cmake 编译链,你也可以下载工程后使用其中的程序文件创建符合自己开发习惯的工程。

4 总结

本文中的矩阵法本质在于,通过样本集构造范德蒙德矩阵,将一元 N 次多项式非线性回归问题转化为 N 元一次线性回归问题(即多元线性回归)。对于线性回归问题的求解,Eigen 库中有多种实现:

  • LU 分解
  • 基于 Householder 变换的 QR 分解
  • 完全正交分解(Complete Orthogonal Decomposition,COD)
  • 标准 Cholesky 分解(LLT)
  • 改进型 Cholesky 分解(LDLT)
  • SVD 分解

不同方法在对矩阵

的需求、求解速度、求解精度上有所差异,Eigen 官网对几种方法进行了对比总结,查看原文请移步 Linear algebra and decompositions 。
Eigen 库中线性问题的几种求解方法对比

Eigen 官网在 Solving linear least squares systems 章节中讨论了 SVD 分解、QR 分解和正规方程(即使用 LDLT 解法)三种方法在求解线性最小二乘问题上的差异,并指出:SVD 分解通常精度最高但速度最慢,正规方程速度最快但精度最差,QR 分解性能介于两种方法之间。相比 SVD 分解和 QR 分解,当矩阵

病态时,正规方程解法所得结果将损失两倍精度。

利用上文所述的工程 Demo 中的小样本(三次多项式

附近的 5 个点)构造出范德蒙德矩阵(即矩阵
)后,对矩阵法(文中方法)、正规方程、householderQr 分解和 bdcSvd 分解进行了拟合实验对比:
几种求解线性最小二乘问题方法的对比

从结果可以看出,在求解速度方面:

在求解精度方面:

householderQr 分解综合性能较优,矩阵法综合性能较差,且有

可逆的要求。

对于线性回归问题,还可通过梯度下降法进行求解,梯度下降法具体使用中还会涉及一些工程细节,例如数据的特征缩放(归一化)、步长

(学习率)的选择、迭代次数的设置等,具体不再展开,后面会另开一篇文章。

参考

  1. 如何理解最小二乘法?
  2. 最小二乘法拟合多项式原理以及c++实现
  3. 最小二乘法多项式曲线拟合原理与实现
  4. 最小二乘法多项式曲线拟合原理与实现(数学公式详细推导,代码方面详细注释)
  5. c++ 曲线拟合的最小二乘法 公式 二次多项式和三次多项式
  6. 最小二乘法
  7. 最小二乘法(least sqaure method)
  8. Linear algebra and decompositions
  9. Solving linear least squares systems
  10. 机器学习:用梯度下降法实现线性回归
  11. 机器学习:最小二乘法、最大似然估计、梯度下降法
  12. 最小二乘法和梯度下降法有哪些区别?
  13. 最小二乘法与梯度下降的区别
  14. 最小二乘法与梯度下降法的区别?
  15. 从线性回归到最小二乘法和梯度下降法
  16. 如何直观形象的理解方向导数与梯度以及它们之间的关系?
  17. 使用最小二乘法和梯度下降法进行线性回归分析

如果觉得文章对你有所帮助的话,欢迎点赞/评论/收藏/关注,相互交流,共同进步~

c++ 三次多项式拟合_最小二乘法多项式曲线拟合数学原理及其C++实现相关推荐

  1. 最小二乘法多项式曲线拟合数学原理及其C++实现

    目录 0 前言 1 最小二乘法概述 2 最小二乘法求解多项式曲线系数向量的数学推导 2.1 代数法 2.2 矩阵法 3 代码实现 4 总结 参考 0 前言 自动驾驶开发中经常涉及到多项式曲线拟合,本文 ...

  2. c++ 三次多项式拟合_从寻找谷神星的过程,谈最小二乘法实现多项式拟合

    科学史上众星云集,璨若星河.这些牛人基本上都是天才,但也不乏无名之辈凭借匪夷所思.骇世惊俗的猜想而跻身于巨星之列.比如,门捷列夫,整了一张留空的元素周期表,引得全世界的化学家去做填空题.还有一位德国的 ...

  3. python多项式拟合_最小二乘法—多项式拟合非线性函数

    本章涉及到的知识点清单: 1.函数的近似表示-高次多项式 2.误差函数-最小二乘法 3.引出案例函数曲线 4.目标函数 5.优化目标函数 6.优化目标函数-梯度下降法 7.优化目标函数-求解线性方程组 ...

  4. c++ 三次多项式拟合_线性回归进阶版,多项式线性回归讲解与实现(附完整代码)...

    每天给小编五分钟,小编用自己的代码,带你轻松学习深度学习!本文将会带你做完一个深度学习进阶版的线性回归---多项式线性回归,带你进一步掌握线性回归这一深度学习经典模型,然后在此基础上,小编将在下篇文章 ...

  5. c++ 三次多项式拟合_非线性回归模型(一)--多项式回归

    在许多实际问题分析中,回归分析的应用十分广泛,它是处理变量之间相关关系最常用的一种统计方法.回归分析可分为线性回归和非线性回归. 线性回归分析相信大家都已经非常熟悉了,它主要分析有线性回归趋势的两个变 ...

  6. 最小二乘法多项式曲线拟合原理与实现--转

    原文地址:http://blog.csdn.net/jairuschan/article/details/7517773/ 概念 最小二乘法多项式曲线拟合,根据给定的m个点,并不要求这条曲线精确地经过 ...

  7. 最小二乘法多项式曲线拟合原理与实现

    概念 最小二乘法多项式曲线拟合,根据给定的m个点,并不要求这条曲线精确地经过这些点,而是曲线y=f(x)的近似曲线y= φ(x). 原理 [原理部分由个人根据互联网上的资料进行总结,希望对大家能有用] ...

  8. 最小二乘法多项式曲线拟合原理与实现(错误地方已经修改底层补充自己写的java实现)

    目录(?) [-] 概念 原理 运行前提 代码 运行效果 概念 最小二乘法多项式曲线拟合,根据给定的m个点,并不要求这条曲线精确地经过这些点,而是曲线y=f(x)的近似曲线y= φ(x). 原理 [原 ...

  9. 最小二乘法多项式曲线拟合及其python实现

    最小二乘法多项式曲线拟合及其python实现 多项式曲线拟合问题描述 最小二乘法 针对overfitting,加入正则项 python实现 运行结果 多项式曲线拟合问题描述 问题描述:给定一些数据点, ...

最新文章

  1. 盐为什么能使冰熔化得更快
  2. python绘制3d图形-Python基于matplotlib实现绘制三维图形功能示例
  3. 【设计模式】责任链模式
  4. Kafka是如何实现高吞吐率的
  5. STM32F7xx —— FatFS(W25QXX)
  6. linux创建vnc服务器,五步建立一个VNC Linux服务器
  7. 46 - 算法 -Leetcode 168 -位运算 类型模拟倒序利用vector
  8. 1018. 可被 5 整除的二进制前缀
  9. java mongodb_MongoDB Java Servlet Web应用程序示例教程
  10. Matplotlib Toolkits:地图绘制工具
  11. 2021-09-13Top-N 推荐系统,通常指的是个性化推荐系统,有别于热门推荐。
  12. 关于Revit API修改元素参数的问题?
  13. JAVA计算机毕业设计大学生旅游拼团网站Mybatis+源码+数据库+lw文档+系统+调试部署
  14. unity让物体做圆周运动、椭圆运动、双曲线运动
  15. 《数据库系统概论》复习
  16. SQL Server Always Encrypted加密使用
  17. 上海税前12000税后多少_税前12000元月工资,税后能拿多少
  18. matlab示波器有功功率,巧用示波器计算功率
  19. 唯冠和苹果的官司打得热闹
  20. 喇叭音圈是大一点好还是小一点好

热门文章

  1. ABP启动后发现前端没有样式
  2. 【文献阅读】用对比学习做弱监督语义分割(Sung-Hoon Yoon等人,ArXiv,2021)
  3. 泛微E-Cology SQL注入漏洞复现(QVD-2023-15672)
  4. java人脸识别api_【Java-人脸识别API】人脸库管理 核心类
  5. 大屏幕更爽 iPhone4/iPad2视频输出实测
  6. MATLAB选择结构之if语句
  7. 拜耳阵列(Bayer Pattern)简介
  8. Tether印刷8月已发行价值4.15亿美元代币
  9. 【图普科技】边界框的数据增强:对目标检测图像变换的再思考(一)
  10. STM32F765IGK6【ARM微控制器】STM32F765ZIT6/STM32F765ZGT6引脚配置