Eigen求解数学问题(三)-- 最小二乘法直线拟合

有这样一个问题:

     实现一个算法:对一系列点拟合出一条线。

最小二乘法

最小二乘法(又称最小平方法)是一种数学优化技术。它通过最小化误差的平方和寻找数据的最佳函数匹配。利用最小二乘法可以简便地求得未知的数据,并使得这些求得的数据与实际数据之间误差的平方和为最小。

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 与原先设定的目标直线非常接近。

总结:

最小二乘法在现实中有很多具体的应用,不但可以拟合直线,还可以曲线等。符合Ax = b 的超定方程组一般都可以最小二乘法来求。

原创文章 41 获赞 0 访问量 2065

猜你喜欢

转载自blog.csdn.net/qq_21291397/article/details/103400192