有没有一种方法可以防止numpy.linalg.svd耗尽内存?

6

我有一百万个3D点要传递给numpy.linalg.svd,但它很快就会耗尽内存。有没有办法将此操作分解成更小的块?

我不知道它在做什么,但我只能传递代表3x3、4x4矩阵的数组吗?因为我在网上看到过使用任意数量元素的数组的用法。


1
从文档中可以看出,svd需要输入2-D arrays。如果传递full_matrices=False,似乎需要更少的内存... - Saullo G. P. Castro
那很有帮助,但它是否会给出完全相同的结果呢?我得到了相同的结果,但参数的描述对我来说没有意义。 - Joan Venge
2个回答

1
如果您的情况下有一个MxN矩阵,例如1000000x3矩阵,则numpy.linalg.svd不需要M==N。实际上,这正是SVD用于计算诸如秩和伪逆之类的东西的地方。而像linalg.inv这样的方法需要一个定义结果的正方形(和满秩)矩阵。@Saullo Castro是正确的。full_matrices=False可以使棘手的问题变得易于处理,因为U矩阵的元素变为1Mx3,大大节省了空间。我不确定numpy使用哪种缩减SVD算法(我认为它可能是紧凑型SVD或薄型SVD),维基百科上的3种广泛使用的算法在Reduced SVDs部分中简要描述:http://en.wikipedia.org/wiki/Singular_value_decomposition。它们都围绕将完整的U矩阵的计算缩减为一种缩减形式,并且这对于某些问题甚至许多问题来说已经足够了。当numberObservations>>numberFeatures时,节省最多。
关于是否获得相同结果的问题。简短的答案可能是肯定的,具体取决于您将如何使用SVD结果。例如,您将获得与原始矩阵相同(在浮点容差水平下)的缩减形式,如下面的代码所示。请注意,在顶部情况下,U的大小为numberObservations x numberObservations,而在full_matrices=False的情况下,U的大小为numberObservations x numberFeatures。
这个代码是从numpy.linalg.svd文档中改编的,可以让人们尝试任意的行/列、奇异值进行选择。
我们总是可以将U矩阵的大小减少到M x min(M,N)。根据数据的结构和存在多少噪音,可能还可以进一步减少。仅因为numpy.isclose为false并不意味着计算出的SV对于所有情况都是不好的。您可以使用mostSignificantSingularValues变量进行实验,该变量从完整的SVD中选择前面的顶级SV。
numberObservations = 900
numberFeatures = 600
mostSignificantSingularValues = 600

a = np.random.randn( numberObservations, numberFeatures) + 1j*np.random.randn(numberObservations, numberFeatures)

#Reconstruction based on full SVD:

U, s, V = np.linalg.svd(a, full_matrices=True)
print(U.shape, V.shape, s.shape)
S = np.zeros((numberObservations, numberFeatures), dtype=complex)
S[:mostSignificantSingularValues, :mostSignificantSingularValues] = np.diag(s[:mostSignificantSingularValues])
print(np.allclose(a, np.dot(U, np.dot(S, V))))
d1 = a - np.dot(U, np.dot(S, V))#
#True

#Reconstruction based on reduced SVD:

U, s, V = np.linalg.svd(a, full_matrices=False)
print(U.shape, V.shape, s.shape)
S = np.diag(s)
print(np.allclose(a, np.dot(U, np.dot(S, V))))

d2 = a - np.dot(U, np.dot(S, V))#

0
尝试使用scipy.linalg.svd而不是numpy的函数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接