使用scipy.sparse.linalg中的svds按降序排序的奇异值
我正在用Python对一个很大的稀疏矩阵应用奇异值分解(SVD)。我使用的是scipy.sparse.linalg包里的svds函数。这个函数输出的奇异值是按从小到大的顺序排列的,所以对应的奇异向量也是按照这个顺序排列的。我想知道有没有办法让奇异值按从大到小的顺序输出,这样奇异向量也能对应到这个顺序?下面是一个示例代码:
from scipy.sparse.linalg import svds
from scipy import sparse
X = numpy.random.uniform(size = [40, 20])
X = scipy.sparse.csc_matrix(X)
u, s, vt = svds(X, 10, which = 'LM')
我试过sparsesvd这个Python库,但它的运行时间比svds要长很多,所以我不打算使用sparsesvd。scipy里的常规svd包对稀疏矩阵不适用。谢谢!
1 个回答
5
你现在想找出最大的10个奇异值,并且希望它们按从小到大的顺序排列,同时还要得到左奇异向量和右奇异向量。如果你想要最小的n个值,只需要把which
这个关键词改成SM
就可以了。
不过,我明白你得到的奇异值是正确的,但顺序不对。这个函数里没有直接的选项可以改变顺序,但你可以按照以下规则来重新排列向量和数值:u的前n列和vt的前n行必须和奇异值保持相同的顺序。
所以,要反转奇异值:
n = len(s)
# reverse the n first columns of u
u[:,:n] = u[:, n-1::-1]
# reverse s
s = s[::-1]
# reverse the n first rows of vt
vt[:n, :] = vt[n-1::-1, :]
这非常简单(正如pv在评论中提到的),但关键是不要重新排列整个矩阵,只需要调整相关的行和列。而且,当然,任何排列方式都可以,所以一般来说(perm
是排列向量):
u[:,:n] = u[:, perm]
s = s[perm]
vt[:n, :] = vt[perm, :]