2015-12-21 70 views
0

我想用Eigen来计算SVD(奇异值分解)。 C是27x18矩阵秩15.Eigen Jacobi SVD

JacobiSVD<MatrixXd> svd(C, ComputeFullV | ComputeFullU); 
cout << svd.computeU() << endl; 
cout << svd.computeV() << endl; 

MatrixXd Cp = svd.matrixU() * svd.singularValues().asDiagonal() * svd.matrixV().transpose(); 
MatrixXd diff = Cp - C; 
PRINT_MAT("diff", diff); 

PRINT_MAT只是一个cout。 令人惊讶的是,我看到diff的一些值非常大,例如4.0733184565807887e+250

我可能做错了什么?

+0

你能后的值'C'? –

+0

https://www.dropbox.com/s/mubch99z6jo9k0a/c?dl=0 – mkuse

+0

在偶尔运行时,我也看到'nan' – mkuse

回答

4

如果你看矩阵元素的大小,你会注意到svd.matrixU()是18x18,svd.singularValues()是18,svd.matrixV()是27x27。当你写svd.matrixU() * svd.singularValues().asDiagonal()时,结果是一个18×18的矩阵,它不能乘以svd.matrixV()。您已经定义了禁用边界检查的-DNDEBUG。你看到的随机数是分配前的内存。你可以解决这个得到使用下面的代码:

MatrixXd res(C.rows(), C.cols()); 
res.setZero(); 
res.topLeftCorner(C.rows(), C.rows()) = (svd.matrixU() * svd.singularValues().asDiagonal()); 

MatrixXd Cp = res * svd.matrixV().transpose(); 
MatrixXd diff = Cp - C; 
cout << "diff:\n" << diff.array().abs().sum(); 

由于ggael指出的那样,你可以问,只有薄矩阵来计算,这将是这样的:

#include <Eigen/Core> 
#include <Eigen/SVD> 
#include <iostream> 

using namespace Eigen; 
using std::cout; 

int main() 
{ 
    MatrixXd C; 
    C.setRandom(27,18); 
    JacobiSVD<MatrixXd> svd(C, ComputeThinU | ComputeThinV); 
    MatrixXd Cp = svd.matrixU() * svd.singularValues().asDiagonal() * svd.matrixV().transpose(); 
    MatrixXd diff = Cp - C; 
    cout << "diff:\n" << diff.array().abs().sum() << "\n"; 
    return 0; 
} 
+0

'C'的大小是27x18,所以'U'是27x27,'V'是27x18 – mkuse

+0

不,请阅读[wikipedia]的第一段(https://en.wikipedia.org/维基/ Singular_value_decomposition)。唯一需要注意的是,在我们的例子中,西格玛是一个向量长度为​​18的“asDiagonal”方法,将它变成一个18x18的矩阵。 –

+0

我明白你的观点。解决了..!谢谢! – mkuse