SciPy.sparse.linalg.svds 是否给出矩阵秩?

Does SciPy.sparse.linalg.svds give matrix rank?

我有一个较大的稀疏二进制值矩形矩阵,M,其中 n > m.我对矩阵秩的理解表明最大可能的秩是 m,而我对 SVD 的理解表明可以通过识别非零奇异值的数量来找到矩阵的秩。

我正在尝试使用 SciPy.sparse.linalg.svds 来确定 M 的排名。第一个问题是我无法计算 m 奇异值,因为 k 只能达到 p = m - 1. 所以我认为我会很聪明并计算 p 最高值,p 最低值值,组合它们,运行 set 以找到唯一值,并最终得到最多 m 个值的列表。这没有按计划进行。

这是一个 MWE:

import scipy.sparse
import scipy.sparse.linalg
import numpy
import itertools  

m = 6
n = 10

test = scipy.sparse.rand(m, n, density=0.25, format='lil', dtype=None, random_state=None)

for i, j in itertools.product(list(range(m)), list(range(n))):
     test[i, j] = 1 if test[i, j] > 0 else 0

U1, S1, VT1 = scipy.sparse.linalg.svds(test, k = min(test.shape) - 1, ncv = None, tol = 1e-5, which = 'LM', v0 = None, maxiter = None, 
                                    return_singular_vectors = True)

U2, S2, VT2 = scipy.sparse.linalg.svds(test, k = min(test.shape) - 1, ncv = None, tol = 1e-5, which = 'SM', v0 = None, maxiter = None, 
                                    return_singular_vectors = True)

S = list(set(numpy.concatenate((S1, S2), axis = 0)))

len(S)

这是一个示例输出:

10

其中 S

[0.5303120147925737,
 1.0725314055439354,
 2.7940865631779643,
 1.5060744813473148,
 1.8412737686034186,
 0.3208993522030293,
 0.5303120147925728,
 1.072531405543936,
 1.5060744813473153,
 1.841273768603419]

m X n 矩阵如何 m < n 的排名是 n?我的上述假设不正确,还是我误用了该功能?我的真实 M 是稀疏的二进制值,大约 300 X 500。

感谢观看!


在@tch 的帮助下,我想出了以下技巧。要检查 rank = m,我只需要检查最小值,并将其附加到从 svds 最高值获得的 m - 1 值功能。事实证明,svds 在阈值化时不报告 0,因此最低值函数将为 return nan for rank < m。这是修改后的代码:

import scipy.sparse
import scipy.sparse.linalg
import numpy
import itertools

m = 6
n = 10

test = scipy.sparse.rand(m, n, density=0.25, format='lil', dtype=None, random_state=None)

test = test > 0
test = test.astype('d')

U1, S1, VT1 = scipy.sparse.linalg.svds(test, k = min(test.shape) - 1, ncv = None, tol = 1e-5, which = 'LM', v0 = None, maxiter = None, 
                                    return_singular_vectors = True)

U2, S2, VT2 = scipy.sparse.linalg.svds(test, k = 1, ncv = None, tol = 1e-5, which = 'SM', v0 = None, maxiter = None, 
                                    return_singular_vectors = True)

S = list(set(numpy.concatenate((S1, S2), axis = 0)))

print(sum(x > 1e-10 for x in S))
S

你正在尝试做的事情将在精确的算术中起作用(假设矩阵没有重复的奇异值)。但是,由于数值舍入误差,它在实践中不起作用。

要看这个试试

C = np.random.randn(10,3)
u,s,vt = np.linalg.svd(C@C.T)

请注意,C@C.T 是一个 10x10 矩阵,秩为 3。但是,您会看到 none 的奇异值恰好为零(但有 7 个接近于 0)。

在以数值方式查找矩阵的秩时,通常使用阈值来确定奇异值 0 的含义。例如,1e-10 以下的所有内容都可能设置为零。

如果矩阵具有精确秩 k,希望您会看到 k 个奇异值远离 0,然后 min(m,n)-k 个奇异值非常接近零。但是,根据矩阵,甚至可能没有明确定义的 "drop".

因此,对于您的示例,您可以尝试删除彼此之间某个阈值内的元素。但是,如果矩阵具有重复的奇异值,这当然会 运行 成为问题。

你可以只 运行 最小的奇异值,看看有多少让你接近于零。据推测矩阵至少是秩 ` 所以第一个奇异值将是非零的。

作为关于查找 test[i,j] > 0 位置的注释,您可以只输入 test>0,它将给出一个布尔数组,其中非零条目为 True,其他条目为 False .您还可以将随机矩阵的 dtype 设置为 bool,只要随机数非零,它就会 True