设置分解阈值(容差)Eigen::JacobiSVD

Setting decomposition threshold (tolerance) Eigen::JacobiSVD

我正在尝试使用 Eigen 的 JacobiSVD 进行实验。特别是我试图从奇异值分解中重建输入矩阵。 http://eigen.tuxfamily.org/dox/classEigen_1_1JacobiSVD.html.

Eigen::MatrixXf m = Eigen::MatrixXf::Random(3,3);
Eigen::JacobiSVD<Eigen::MatrixXf, Eigen::NoQRPreconditioner> svd(m, Eigen::ComputeFullU | Eigen:: ComputeFullV);
Eigen::VectorXf SVec = svd.singularValues();
Eigen::MatrixXf S = Eigen::MatrixXf::Identity(3,3);
S(0,0) = SVec(0);
S(1,1) = SVec(1);
S(2,2) = SVec(2);

Eigen::MatrixXf recon = svd.matrixU() * S * svd.matrixV().transpose();
cout<< "diff : \n"<< m - recon << endl;

我知道SVD在内部是通过迭代方法计算的,永远无法得到完美的重构。错误按 10^-7 的顺序排列。使用上面的代码,输出是 --

diff : 
 9.53674e-07   1.2517e-06 -2.98023e-07
-4.47035e-08   1.3113e-06   8.9407e-07
 5.96046e-07 -9.53674e-07  -7.7486e-07

对于我的应用程序,这个错误太高了,我的目标是 10^-10 - 10^-12 范围内的错误。我的问题是如何设置分解的阈值。

注意:在文档中我注意到有一种方法 setThreshold() 但它明确指出这不会为分解设置阈值,而是为奇异值与零进行比较。

注意:我尽可能不希望双打。甚至可以用 float 吗?

一个单精度浮点数(32 位 float)有六到九个有效的 十进制 数字,所以你对 10^{-10} 的要求是不可能(假设值在 0.5f 左右)。双精度浮点数(64 位 double)有 15-17 个有效 小数 数字,所以只要值不是 10^6 就应该工作。