Eigen學習筆記22:求解線性最小二乘系統

一個超定方程組,例如Ax = b,沒有解。

在這種情況下,在令Ax - b儘可能小的意義上,搜索最接近解的向量x是有意義的。該x稱爲最小二乘解(如果使用歐幾里得範數)。

這裏討論三種方法: the SVD decomposition, the QR decomposition and normal equations.

當然, the SVD decomposition 通常最準確但最慢, normal equations 最快但最不準確, and the QR decomposition 介於兩者之間。

使用SVD分解

The solve() method in the BDCSVD class can be directly used to solve linear squares systems. 

僅計算奇異值(此類的默認值)是不夠的。您還需要 the singular vectors ,但是 the singular vectors 足以計算最小二乘解:

#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.680375   0.59688
-0.211234  0.823295
 0.566198 -0.604897
Here is the right hand side b:
-0.329554
 0.536459
-0.444451
The least-squares solution is:
-0.669626
 0.314253

使用QR分解

QR分解類中的solve()方法還計算最小二乘解。有3種QR分解類: There are three QR decomposition classes: HouseholderQR (no pivoting, so fast but unstable), ColPivHouseholderQR (column pivoting, thus a bit slower but more accurate) and FullPivHouseholderQR (full pivoting, so slowest and most stable). 

#include <iostream>
#include <Eigen/Dense>

using namespace std;
using namespace Eigen;

int main()
{
    MatrixXf A = MatrixXf::Random(3, 2);
    VectorXf b = VectorXf::Random(3);
    cout << "The solution using the QR decomposition is:\n"
         << A.colPivHouseholderQr().solve(b) << endl;
}

輸出:

The solution using the QR decomposition is:
-0.669626
 0.314253

使用 normal equations

找到Ax = b的最小二乘解等效於求解法線方程A^{^{T}}Ax = A^{T}b

#include <iostream>
#include <Eigen/Dense>

using namespace std;
using namespace Eigen;

int main()
{
    MatrixXf A = MatrixXf::Random(3, 2);
    VectorXf b = VectorXf::Random(3);
    cout << "The solution using normal equations is:\n"
         << (A.transpose() * A).ldlt().solve(A.transpose() * b) << endl;
}

輸出:

The solution using normal equations is:
-0.669626
 0.314253

如果矩陣A是病態的,那麼這不是一個好方法,因爲A^{^{T}}A的條件數是A的條件數的平方。This means that you lose twice as many digits using normal equation than if you use the other methods.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章