我有一个大的术语文档矩阵,想要使用matlab提供的非负矩阵分解函数。问题是在第一次迭代后,内存使用率迅速上升并达到顶部(我的系统有6GB),另一方面CPU使用率水平变得非常低(约1%-5%)。整个系统的行为就像崩溃一样,只有你等了很久才能完成第二次迭代。 (注意,为了获得良好的结果,需要更多的迭代)。
问题:
如果有人对此有任何经验,或者使用比我更大的矩阵运行nnmf(),我真的想知道他/她是如何实际克服上述问题的。
另外:我用较小的矩阵(大约7000x1800)做了这个并没有问题。我使用稀疏矩阵,因为term-document矩阵有很多零元素,这有助于减少需要存储的空间。例如,在我的情况下,Term-Document矩阵包含14608 * 18828 = 275039424
个元素和sum(sum(spa~=0)) = 1312582
非零元素:
>> whos
Name Size Bytes Class Attributes
full 14608x18828 2200315392 double
spa 14608x18828 21151944 double sparse
答案 0 :(得分: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%零的稀疏矩阵正在浪费稀疏形式的能力。如果矩阵更稀疏,结果会有所不同。
答案 1 :(得分: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
,因为之后从未使用d
。对于正在使用的术语 - 文档矩阵,这可以在不引起内存问题的情况下工作。