原文:Eigen官网–Solving linear least squares systems
对于超定线性方程系统(An overdetermined system of equations):Ax = b,其是没有解的。在这种情况下,可以寻找一个接近于方程解的向量x,那么Ax-b的差值将会足够小。向量x就被称为least square solution。
本篇文章将讨论三种线性方程求解方法:
- SVD decomposition
- QR decomposition
- norm equations
其中,SVD
分解通常是最准确的,但也是最慢的;norm equations
是最快的,但也是最不准确的;QR
分解则位于上述两种方法之间。
1. SVD decomposition
BDCSVD
类中的solve()
方法可以直接用于求解线性系统。
2. QR decomposition
QR
分解类中的solve()
方法也计算最小二乘解。
有三个QR decomposition
类:
HouseholderQR
(不旋转,速度很快但不稳定)。ColPivHouseholderQR
(列旋转,因此速度较慢但更准确)FullPivHouseholderQR
(完全旋转,因此速度最慢且最稳定)。
3. normal equations
求解 Ax = b的最小二乘解,等价于求解normal equation AT Ax=ATb,因此引申出使用normal equations的求解方法。
如果矩阵A是病态的(ill-conditioned),那么这不是一个好的方法,因为ATA的条件数是A的条件数的平方,这意味着使用normal equations比使用其他方法减少两倍的位数。
示例如下:
#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;
// SVD decomposition
cout << "The least-squares solution is:\n"
<< A.bdcSvd(ComputeThinU | ComputeThinV).solve(b) << endl;
// QR decomposition
cout << "The solution using the QR decomposition is:\n"
<< A.colPivHouseholderQr().solve(b) << endl;
// normal equations
cout << "The solution using normal equations is:\n"
<< (A.transpose() * A).ldlt().solve(A.transpose() * 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
The solution using the QR decomposition is:
-0.67
0.314
The solution using normal equations is:
-0.67
0.314