应用SVD瞬间抛出内存错误?

7 投票
2 回答
7583 浏览
提问于 2025-04-17 00:05

我正在尝试对一个矩阵(3241行 x 12596列)应用奇异值分解(SVD),这个矩阵是经过一些文本处理得到的,最终目的是进行潜在语义分析。但是我不明白为什么会出现错误,因为我的64位机器有16GB的内存。当我调用svd(self.A)时,它就报错了。具体的错误信息如下:

Traceback (most recent call last):
  File ".\SVD.py", line 985, in <module>
    _svd.calc()
  File ".\SVD.py", line 534, in calc
    self.U, self.S, self.Vt = svd(self.A)
  File "C:\Python26\lib\site-packages\scipy\linalg\decomp_svd.py", line 81, in svd
    overwrite_a = overwrite_a)
MemoryError

于是我尝试使用

self.U, self.S, self.Vt = svd(self.A, full_matrices= False)

这次,它又报了以下错误:

Traceback (most recent call last):
  File ".\SVD.py", line 985, in <module>
    _svd.calc()
  File ".\SVD.py", line 534, in calc
    self.U, self.S, self.Vt = svd(self.A, full_matrices= False)
  File "C:\Python26\lib\site-packages\scipy\linalg\decomp_svd.py", line 71, in svd
    return numpy.linalg.svd(a, full_matrices=0, compute_uv=compute_uv)
  File "C:\Python26\lib\site-packages\numpy\linalg\linalg.py", line 1317, in svd
    work = zeros((lwork,), t)
MemoryError

这个矩阵是不是太大了,以至于Numpy处理不了?在不改变方法的情况下,我能做些什么呢?

2 个回答

13

是的,scipy.linalg.svd中的full_matrices参数很重要:你的输入矩阵的秩非常低(最大秩为3,241),所以你不想为V分配一个12,596 x 12,596的完整矩阵!

更重要的是,来自文本处理的矩阵通常是非常稀疏的。scipy.linalg.svd是针对密集矩阵的,并且不支持截断奇异值分解,这会导致a) 性能非常糟糕,b) 大量内存浪费。

可以看看来自PyPI的sparseSVD包,它可以处理稀疏输入,并且你可以只请求前K个因子。或者试试scipy.sparse.linalg.svd,不过它的效率不如前者,并且只在较新版本的scipy中可用。

或者,为了完全避免复杂的细节,可以使用一个透明地为你执行高效LSA的包,比如gensim

2

看来,感谢@Ferdinand Beyer,我没有注意到我在64位的电脑上使用的是32位的Python。

换成64位的Python并重新安装所有的库后,问题就解决了。

撰写回答