使用SVD方法时Matlab与Eigen的结果差异排查
Eigen SVD与Matlab结果差异排查
先确认SVD计算模式匹配
Matlab的svd默认输出完全SVD结果,而Eigen的SVD类默认可能只生成精简版的V矩阵。你需要显式指定计算完整的V,比如用JacobiSVD<MatrixXd> svd(A, ComputeFullU | ComputeFullV),或者用BDCSVD时加上对应选项。核对奇异值排序
确保Eigen和Matlab的奇异值都是按降序排列的。直接输出两边的奇异值数组对比,要是顺序不一样,那V矩阵的列对应关系肯定错了。排查数值精度与算法差异
Matlab用的是LAPACK的dgesvd,Eigen的JacobiSVD是雅可比迭代,BDCSVD是分治法,不同算法处理接近奇异的矩阵(比如DLT里的A,秩亏1)时,最小奇异值对应的右奇异向量可能有小差异,但应该在浮点精度范围内(比如1e-6左右)。要是差异远超这个范围,绝对是代码问题,不是单纯的精度误差。死磕矩阵输入的一致性
别想当然认为两边的矩阵A一样:- 检查数据类型:Matlab是double,Eigen必须用
MatrixXd,别用MatrixXf单精度 - 检查行列顺序:Eigen和Matlab都是列优先,但手动赋值时别搞反行和列
- 清理无效值:原矩阵里的“无效零值”如果是NaN或者Inf,直接会把SVD算崩,先把这些值处理掉
- 检查数据类型:Matlab是double,Eigen必须用
检查代码细节
举个常见错误:// 错:没指定ComputeFullV,默认只生成精简V JacobiSVD<MatrixXd> svd(A); MatrixXd V = svd.matrixV();正确写法:
// 显式要求计算完整的U和V JacobiSVD<MatrixXd> svd(A, ComputeFullU | ComputeFullV); MatrixXd V = svd.matrixV();另外DLT里要取V的最后一列当解,得确认Eigen的
matrixV()列顺序对应奇异值降序——也就是最后一列确实对应最小奇异值。用重构误差验证
两边都用SVD结果重构矩阵:A ≈ U*S*V^T,计算重构后的误差。如果Matlab的误差远小于C++,说明C++的SVD计算有问题;要是误差量级差不多,那可能是右奇异向量的多解性导致的,这时候可以把V的最后一列归一化后再对比,方向一致就没问题。
内容的提问来源于stack exchange,提问作者plebs
相关产品推荐
相关产品推荐

