按顺序获取NumPy数据列的奇异值

时间:2019-04-20 20:56:21

标签: python numpy scipy linear-algebra svd

我想计算矩阵的奇异值分解,奇异值的顺序很重要。默认情况下,似乎numpy.linalg.svd(和scipy.linalg.svd)对奇异值进行排序,这使我无法分辨哪一列对应于每个奇异值。

示例:

import numpy as np

X = np.array([[-74, 80, 18, -56, -112],
              [14, -69, 21, 52, 104],
              [66, -72, -5, 764, 1528],
              [-12, 66, -30, 4096, 8192],
              [3, 8, -7, -13276, -26552],
              [4, -12, 4, 8421, 16842]])

U, D, V = np.linalg.svd(X)
print(D)

返回:

array([3.63684045e+04, 1.70701331e+02, 6.05331879e+01, 7.60190176e+00,
        1.17158094e-12])

当我需要时:

array([1.70701331e+02, 6.05331879e+01, 7.60190176e+00, 3.63684045e+04, 
        1.17158094e-12])

是否有一种方法可以获取未排序的奇异值(D)?关系X = UDV ^ T也必须保留。

编辑:此处需要一些上下文来阐明我的误解。我试图在this paper中重现第2.3节,方差分解方法。

1 个答案:

答案 0 :(得分:2)

当你说:

  

默认情况下,似乎numpy.linalg.svd(和scipy.linalg.svd)对奇异值进行排序,这使我无法分辨哪一列对应于每个奇异值。

我认为您在弄错,“奇异值分解”中的奇异值没有唯一的顺序,重要的是U,D和V的列向量的顺序如下: U * D * V == X

这就是为什么按照惯例将它们按降序排列的原因,但是很明显,the基U和共轭转置V的垂直矢量也按上述公式成立的顺序进行设置。

如果要证明,要根据U,D和V计算X,则必须执行以下操作:

from scipy import linalg

#decompose
U, D, V = np.linalg.svd(X)

# get dim of X
M,N = X.shape

# Construct sigma matrix in SVD (it simply adds null row vectors to match the dim of X 
Sig = linalg.diagsvd(D,M,N)

# Now you can get X back:
assert np.sum(np.dot(U, np.dot(Sig, V)) - X) < 0.00001