有这样一个问题:
实现一个算法:对一系列点拟合出一条线。
最小二乘法
最小二乘法(又称最小平方法)是一种数学优化技术。它通过最小化误差的平方和寻找数据的最佳函数匹配。利用最小二乘法可以简便地求得未知的数据,并使得这些求得的数据与实际数据之间误差的平方和为最小。
Eigen 库中 BDCSVD类中的solve()方法可以直接用于求解线性平方系统。具体的例子如下:
#include <iostream>
#include <Eigen/Dense>
using namespace std;
using namespace Eigen;
int main()
{
MatrixXf A = MatrixXf::Random(3, 2);
cout << "Here is the matrix A:\n" << A << endl;
VectorXf b = VectorXf::Random(3);
cout << "Here is the right hand side b:\n" << b << endl;
cout << "The least-squares solution is:\n"
<< A.bdcSvd(ComputeThinU | ComputeThinV).solve(b) << endl;
}
输出:
Here is the matrix A:
0.68 0.597
-0.211 0.823
0.566 -0.605
Here is the right hand side b:
-0.33
0.536
-0.444
The least-squares solution is:
-0.67
0.314
既然有参照的实例了,不妨也自己动手实现一个最小二乘的求解吧!
看这样一个小例子:
线代的求解过程是这样的:
现在我们用Eigen 来实现下吧
MatrixXf Al(3,2) ;
Al<<4,0,
0,2,
1,1;
cout << "Here is the matrix A:\n" << Al << endl;
Vector3f b;
b<<2,0,11;
cout << "Here is the right hand side b:\n" << b << endl;
cout << "The least-squares solution is:\n"
<< Al.bdcSvd(ComputeThinU | ComputeThinV).solve(b) << endl;
输出:
接着,我们来做直线拟合
比如我们要拟合的目标直线为 y = 3x + 4;
该直线附近,我们取5个测试点 (1,8),(2,9),(3,13),(4,15),(7,25)
构造方程 y = ax+b, 将上方的测试点代入,得到一个矩阵方程Ax = b,其中A<<1,1,
2,1,
3,1,
4,1,
7,1;
b<<8,9,13,15,25 ;
编写代码:
MatrixXd A(5,2) ;
A<<1,1,
2,1,
3,1,
4,1,
7,1;
cout << "Here is the matrix A:\n" << A << endl;
VectorXd b(5);
b<<8,9,13,15,25;
cout << "Here is the right hand side b:\n" << b << endl;
cout << "The least-squares solution is:\n"
<< A.bdcSvd(ComputeThinU | ComputeThinV).solve(b) << endl;
输出:
OK!拟合得到的参数a =2.92 ; b=4.05 与原先设定的目标直线非常接近。
扫描二维码关注公众号,回复:
11150623 查看本文章
![](/qrcode.jpg)
总结:
最小二乘法在现实中有很多具体的应用,不但可以拟合直线,还可以曲线等。符合Ax = b 的超定方程组一般都可以最小二乘法来求。