SVD求解矩阵伪逆过程
-
首先对矩阵
A
进行SVD
分解得到U, D, V
三个矩阵,其中D
为列矩阵,是从上到下,由大到小排列的A矩阵的奇异值。 -
若
D
矩阵中元素个数为n
则原矩阵有n
个奇异值,构建大小为V.cols() * U.cols()
的S
矩阵,其中S
矩阵的前n
个对角线的各元素为各奇异值,即D
矩阵各元素的倒数。需注意D矩阵元素非负, 且是由大到小的顺序进行取倒数。 -
最后利用公式构建
A
矩阵的伪逆矩阵。p
i
n
v
A
=
V
∗
S
∗
U
T
pinv_A = V * S * U^T
pinvA=V∗S∗UT
C++代码
#include <iostream>
#include <Eigen/SVD>
#include <Eigen/Core>
using namespace std;
// 利用Eigen库,采用SVD分解的方法求解矩阵伪逆,默认误差er为0
Eigen::MatrixXd pinv_eigen_based(Eigen::MatrixXd & origin, const float er = 0) {
// 进行svd分解
Eigen::JacobiSVD<Eigen::MatrixXd> svd_holder(origin,
Eigen::ComputeThinU |
Eigen::ComputeThinV);
// 构建SVD分解结果
Eigen::MatrixXd U = svd_holder.matrixU();
Eigen::MatrixXd V = svd_holder.matrixV();
Eigen::MatrixXd D = svd_holder.singularValues();
// 构建S矩阵
Eigen::MatrixXd S(V.cols(), U.cols());
S.setZero();
for (unsigned int i = 0; i < D.size(); ++i) {
if (D(i, 0) > er) {
S(i, i) = 1 / D(i, 0);
} else {
S(i, i) = 0;
}
}
// pinv_matrix = V * S * U^T
return V * S * U.transpose();
}
int main() {
// 设置矩阵行数、列数
const int ROW = 3;
const int COL = 4;
// 生成大小 ROW * COL 的随机矩阵
Eigen::MatrixXd A;
A = Eigen::MatrixXd::Random(ROW, COL);
// 打印矩阵A
cout << "矩阵A为:" << endl;
cout << A << endl;
// 打印矩阵A的伪逆矩阵
cout << "矩阵A的伪逆为:" << endl;
cout << pinv_eigen_based(A) << endl;
}
C++伪逆计算结果
矩阵A为:
-0.999984 -0.0826997 -0.905911 0.869386
-0.736924 0.0655345 0.357729 -0.232996
0.511211 -0.562082 0.358593 0.0388327
矩阵A的伪逆为:
-0.312319 -0.919805 0.00626524
-0.406429 -0.350652 -1.37477
-0.245582 0.79061 0.573503
0.496441 -0.267508 0.474029
Matlab伪逆计算结果
矩阵A为
-0.999984000000000 -0.0826997000000000 -0.905911000000000 0.869386000000000
-0.736924000000000 0.0655345000000000 0.357729000000000 -0.232996000000000
0.511211000000000 -0.562082000000000 0.358593000000000 0.0388327000000000矩阵A的伪逆为:
-0.312319329541589 -0.919806223588993 0.00626485031867355
-0.406429539737511 -0.350652955757283 -1.37477343275610
-0.245581499008346 0.790610522532372 0.573502890310835
0.496441264538540 -0.267507910015611 0.474028770291387