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

时间:2019-01-10 19:21:15

标签: python-3.x scipy sparse-matrix linear-algebra

我有一个较小的稀疏二进制值矩形矩阵 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 < n m X n 矩阵如何具有 n的秩?我上面的假设是不正确的,还是我误用了该功能?我真正的 M 是稀疏的,二进制值的,大约是300 X 500。

感谢您的光临!


在@tch的帮助下,我提出了以下建议。要检查rank = m ,我只需要检查最小值,并将其附加到 m -从svds最高值函数获得的1个值。事实证明,svds在达到阈值时不会报告0,因此最小值函数将返回nan < m 的nan。这是修改后的代码:

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

1 个答案:

答案 0 :(得分:1)

您要执行的操作将在精确的算术中起作用(假设矩阵没有重复的奇异值)。但是,由于数字舍入误差,在实践中将无法使用。

要查看此尝试

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,然后看到min(m,n)-k的奇异值非常接近零。但是,根据矩阵的不同,甚至可能没有明确定义的“液滴”。

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

您可以运行最小的奇异值,看看有多少个奇异值使您接近零。大概矩阵至少是rank,因此第一个奇异值将为非零。

作为关于找到test[i,j] > 0位置的说明,您可以直接到test>0,它将给出一个布尔数组,其中非零条目中的True以及其他地方的False。您还可以将随机矩阵的dtype设置为bool,并且只要随机数不为零,它将为True