Python 3.x SciPy.sparse.linalg.SVD是否给出矩阵秩?

Python 3.x SciPy.sparse.linalg.SVD是否给出矩阵秩?,python-3.x,scipy,sparse-matrix,linear-algebra,Python 3.x,Scipy,Sparse Matrix,Linear Algebra,我有一个较大的稀疏二值矩形矩阵M,其中n>M。我对矩阵秩的理解表明,最大可能的秩是m,而我对奇异值分解的理解表明,矩阵的秩可以通过识别非零奇异值的数量来找到 我试图使用SciPy.sparse.linalg.svds来确定m的秩。第一个问题是我无法计算m的奇异值,因为k只能上升到p=m-1。所以我认为我应该聪明点,计算p个最高值,p个最低值,组合它们,运行set来找到唯一的值,最后得到最多m个值的列表。这并没有按计划进行 这里有一个MWE: import scipy.sparse import

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

我试图使用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
因为

一个m 谢谢你的关注

在@tch的帮助下,我想出了以下方法。要检查rank=m,我只需要检查最小值,并将其附加到从svds highest values函数获得的m-1值。事实证明,svds在设置阈值时不会报告0,因此,对于秩
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是秩为3的10x10矩阵。但是,您将看到,没有一个奇异值完全为零,但是7接近于0

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

如果矩阵有精确的秩k,希望你能看到k个奇异值远离0,然后minm,n-k奇异值非常接近零。但是,根据矩阵的不同,甚至可能没有明确的下降

因此,对于您的示例,您可以尝试删除彼此在某个阈值内的元素。然而,如果矩阵具有重复的奇异值,这当然会遇到问题

你可以只运行最小的奇异值,看看有多少接近零。假设矩阵至少为秩`所以第一个奇异值将为非零


作为关于查找test[i,j]>0的注意事项,您只需测试>0,它将给出一个布尔数组,在非零条目中为True,在其他地方为False。您还可以将随机矩阵的数据类型设置为bool,当随机数为非零时,该值将为真。

感谢您的回复。为了避免机器错误,我将阈值tol选项设置为1e-5。我运行了你的代码,谢谢你,你有接近零的值,这会低于一个阈值,但我的S中的所有值甚至都不接近零!同时也感谢你提供了二进制转换的快捷方式。我将使用它。这个例子是为了说明没有什么是精确的,所以如果你想使用一个集合来消除重复元素,你还必须设置这些比较的阈值。但是,您仍然有删除重复奇异值的风险。是的,我可以使用阈值运行set!看看我的S,有许多价值观非常接近。谢谢我刚刚编辑了我的帖子,但你真的只需要找到最低的奇异值并计算有多少是零。我认为最好避免设置,否则你可以删除重复的奇异值。不想删除重复。
C = np.random.randn(10,3)
u,s,vt = np.linalg.svd(C@C.T)