我有一个较小的稀疏二进制值矩形矩阵 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
答案 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
。