1

我有一个很大的术语文档矩阵,想使用 matlab 提供的非负矩阵分解函数。问题是在第 1 次迭代之后,内存使用率迅速上升并达到顶峰(我的系统有 6GB),另一方面,CPU 使用率水平变得非常低(大约 1%-5%)。整个系统的行为就像它已经崩溃一样,只有等待很长时间才能完成第二次迭代。(请注意,要获得好的结果需要更多的迭代)。

问题:

如果有人对此有任何经验,或者使用比我更大的矩阵运行 nnmf(),我真的很想知道他/她实际上是如何克服上述问题的。

另外:我用较小的矩阵(大约 7000x1800)完成了这个,没有问题。我使用稀疏矩阵是因为术语文档矩阵有很多零元素,这有助于减少需要存储的空间。例如,在我的情况下,术语文档矩阵具有14608 * 18828 = 275039424元素和sum(sum(spa~=0)) = 1312582非零元素:

>> whos
Name          Size                    Bytes  Class     Attributes

full      14608x18828            2200315392  double              
spa       14608x18828              21151944  double    sparse    
4

2 回答 2

1

我想我们都看过太多《星际迷航》的剧集了。我们的计算机不是无限快的,也不是无限量的内存。我们期望我们几乎可以进行任何我们想要的计算,并且几乎立即获得结果,这让我们感到厌烦。仅仅因为您想要处理大型矩阵的分解并不意味着您将能够这样做。获得更多内存来处理这种大小的问题。或者解决较小的问题。

您描述的矩阵甚至不是非常稀疏,它们的分解将基本上是完全完整的。稀疏矩阵很少有价值,除非非零值的数量占总数的一小部分。只有 50% 零值的稀疏矩阵是对工具的浪费。例如,

>> A = randi([0 1],100, 100);
>> B = sparse(A);
>> whos
  Name        Size             Bytes  Class     Attributes

  A         100x100            80000  double              
  B         100x100            81480  double    sparse    

看到这里 A 是 50% 的零,但稀疏形式实际上比完整版本需要更多的内存来存储!请记住,您不仅需要存储非零元素,还需要存储它们的位置。

好的,所以稀疏存储效率不高。但是,您肯定可以在运营效率方面获得收益吗?甚至不是这样。使用 Steve Eddins timeit 函数进行比较,我得到以下结果:

>> timeit(@() A*A)
ans =
   7.3604e-05

>> timeit(@() B*B)
ans =
    0.0014884

所以稀疏乘法比全乘法慢得多。

本质上,只有 50% 为零的稀疏矩阵正在浪费稀疏形式的功能。如果矩阵更加稀疏,结果会有所不同。

于 2012-08-21T14:16:41.257 回答
1

终于奏效的东西:

我检查了nnmf.m文件(Matlab提供的算法实现)并试图理解代码。有一个名为“d”的变量执行以下操作:d = a - w*h; 并且是一个与“a”具有相同维度的完整矩阵(即大型术语文档矩阵):

Name             Size                    Bytes  Class      Attributes
a            14608x18828              21151944  double     sparse    
d            14608x18828            2200315392  double               
...
h                4x18828                602496  double               
h0               4x18828                602496  double               
...
w            14608x4                    467456  double               
w0           14608x4                    467456  double   

为了节省一些内存空间,我曾经clear在不需要时删除此矩阵。 nnmf.m文件的一部分:

d = a - w*h;
dnorm = sqrt(sum(sum(d.^2))/nm);
dw = max(max(abs(w-w0) / (sqrteps+max(max(abs(w0))))));
dh = max(max(abs(h-h0) / (sqrteps+max(max(abs(h0))))));
delta = max(dw,dh);

被这个的取代:

d = a - w*h;
dnorm = sqrt(sum(sum(d.^2))/nm);
clear d;
dw = max(max(abs(w-w0) / (sqrteps+max(max(abs(w0))))));
dh = max(max(abs(h-h0) / (sqrteps+max(max(abs(h0))))));
delta = max(dw,dh);

clear d was added there because d was never used after that. For the term-document matrix that was being used, this worked without causing memory problems.

于 2012-08-22T08:07:33.817 回答