2013-08-07 48 views
2

我正在寻找Mathnet.Iridium和Mathnet.Numerics之间的非回归。这里是我的代码,使用Mathnet.Numerics:与Mathnet数值库Svd重新编译似乎是错误的

double[][] symJaggedArray = new double[5][]; 
symJaggedArray[0] = new double[] { 3, 0, 0, 0, 0 }; 
symJaggedArray[1] = new double[] { 0, 2, 4, 0, 0 }; 
symJaggedArray[2] = new double[] { 0, 4, 5, -4, 5 }; 
symJaggedArray[3] = new double[] { 0, 0, -4, -8, 12 }; 
symJaggedArray[4] = new double[] { 0, 0, 5, 12, -5 }; 
symDenseMatrix = DenseMatrix.OfArray(new Matrix(symJaggedArray).CopyToArray());// not optimal but it's not the point 

Svd svd = new UserSvd(symDenseMatrix , true); 
Matrix<double> recompo = svd.U().Multiply(svd.W()).Multiply(svd.VT()); 

当我比较recompo和初始矩阵,他们是不同的。 我发现这个差异各分解矩阵与以前的实现比较时:

  • U和singularValueDecomposition.LeftSingularVectors相等
  • W和sin​​gularValueDecomposition.S相等
  • VT和Matrix.Transpose(singulaValueDecomposition.RightSingularVectors )不同

最后,用旧API重新编译是正确的。使用

MathNet.Numerics版本:Math.NET Numerics的V2.5.0

所以我的问题是:哪里是我的错误与新的API重建初始矩阵时?

RecompoMatrix =

  • 0 -1.216846655456 2.83903817786199 1.4472680220698 2.89215520227421
  • 0 -2.46695399700557 0.92863757484644 8.657344064164 -0.31963101527516
  • 0 0.349540484418384 8.20515629935223 -2.26741625715781 -12.3049605878983
  • 0 -0.402667067831389 -6.32914150795323 9.13315298351198 8.3884053064068

回答

1

我很快试图重现这一点,但我失败了。我已经使用了Math.NET Numerics v2.6(NuGet包),但是在这个版本中对SVD分解没有任何改变。这是我的代码:

var m = DenseMatrix.OfArray(new double[,] { 
    { 3, 0, 0, 0, 0 }, 
    { 0, 2, 4, 0, 0 }, 
    { 0, 4, 5, -4, 5 }, 
    { 0, 0, -4, -8, 12}, 
    { 0, 0, 5, 12, -5 }}); 

var svd = m.Svd(true); 
//var svd = new UserSvd(m, true); 

svd.U() * svd.W() * svd.VT() 

当最后一行的计算结果为:

DenseMatrix 5x5-Double 
      3   0   0   0   0 
      0   2   4 -1.23512E-15 -3.747E-16 
      0   4   5   -4   5 
      0 3.26128E-16   -4   -8   12 
      0 -1.15186E-15   5   12   -5 

VT在这种情况下是:

DenseMatrix 5x5-Double 
      0 -0.0449147  0.249507  0.718099 -0.648123 
      0  0.466822  0.823535 0.0324572  0.320646 
      0  0.208479  0.176729 -0.670706 -0.689534 
      -1   0   0   0   0 
      0  0.858252 -0.477811  0.182848 -0.0408292 

我不知道为什么你会得到完全不同的结果? 你可以用我上面发布的相同代码再试一次吗?

+0

你会得到一个有趣的观点: 它会得到与你的方法m.Svd(true)相同的结果,但是如果替换为: // var svd = m.Svd(true); var svd = new UserSvd(m,true); – FabricePA

+0

无论如何,我标记你的答案,因为它保存了我的回归。非常感谢。我打算使用Matrix.Svd()。不过,我真的认为在UserSvd和DenseSvd中有一个问题,或者我不明白它是如何使用的。 – FabricePA

+0

谢谢! 当我尝试使用这两种方法(在LINQPad中)时,我实际上得到了与DenseSvd和UserSvd完全相同的结果。所以我仍然有兴趣找出问题所在,确保没有隐藏的漏洞。 –

0

你有没有考虑过在SVD之前将矩阵对中?在计算特征向量之前它可能已经居中。