我有一个稀疏矩阵M(290k,230k)
,大小约为640MB(通过whos
检查)。
以下说明:
find(M > 0 & M<=10);
产生“Out of memory”错误,我不明白为什么,仍然有足够的内存可用,并且值在0到10之间的索引列表不能大于矩阵本身的大小。我错过了什么吗?我想是的。
编辑:
我假设M > 0
在M<=10
之前执行(正如在其他编程语言中发生的那样),但我认为我错了,实际上:
temp = find(M > 0)
find(M(temp) < 10)
不会产生任何错误,但我无法获得M的原始值。
因为我的最终目标是将所有值设为0&lt; 10,我改写了我的问题。
拥有一个很大且非常稀疏的矩阵M(290k,230k)
如何将所有值设置为0&lt; 10不使用慢速循环?
编辑2,回复@ AnderBiguri的代码:
我已经尝试过你的代码,没有修改Mnew =稀疏(零(大小(M)))我得到“内存不足”,但这是可以理解的。奇怪的是,即使你的代码有意义,我也会得到“订阅分配维度不匹配”。在这一行:
Mnew(ii(notdelete),jj(notdelete))=nz(notdelete);
我不明白为什么,这是在作业之前whos
的结果:
ii 39701898x1 317615184双
jj 39701898x1 317615184双
M 290621x232537 1860320双稀叉 Mnew 290621x232537 637090672双稀叉 notdelete 39701898x1 39701898逻辑
nz 39701898x1 317615184双
一切对我都有意义,因为M
的非零元素的数量是39701898.如果我在一个小的测试矩阵上尝试你的代码,一切都按预期工作,原始矩阵我得到了那个错误。有没有办法调试这种错误?
编辑3:重现错误的一些代码
R = sprand(29062,23253,5.8748e-04);
[ii,jj,nz]=find(R);
notdelete=nz>0.5;
R2=sparse( size(R,1), size(R,2) );
R2(ii(notdelete),jj(notdelete))=nz(notdelete);
答案 0 :(得分:4)
问题在于M<=10
尝试:
M=sparse(eye(3))
M<=10
ans =
(1,1) 1
(2,1) 1
(3,1) 1
(1,2) 1
(2,2) 1
(3,2) 1
(1,3) 1
(2,3) 1
(3,3) 1
恭喜!现在你有一个完全填充的稀疏矩阵!你现在正在使用完整矩阵的内存+非零条目索引的内存!这就是崩溃的原因。我建议您使用不同的方法来搜索您的解决方案。
因此,如果要删除小于0的值,可以执行以下操作:
% Example matrix
M=sparse(diag([1 11 4]))
sizeM=size(M);
% findnonzero elements and indexes
[ii,jj,nz]=find(M);
% Delete it if you are worried about memory
clear M
% Get the ones you want to keep
notdelete=nz>10;
% Create a new matrix with those
Mnew=sparse(sizeM);
indx=sub2ind(sizeM,ii(notdelete),jj(notdelete));
Mnew(indx)=nz(notdelete);
此代码的工作原理:
我所做的是描述备用矩阵M
,因为内部描述了稀疏矩阵:非零值(ii
,jj
)的索引和值本身, nz
。
然后我找到遵循规则的非零值并且你想要保持(你可以做相反的事情而不是逻辑但是我决定这样做)。您要保留的是nz>10
。如果您在Matlab中执行该操作,它将为您提供一个逻辑数组,其中1
位于您要保留的位置,0
位于您不存在的位置。
然后,创建一个空的备用矩阵(实际上我在那里有一个错误,你在下面的评论中正确地发现并纠正了它)。空白的Matrix充满了您要保留的nz
,因此nz(notdelete)
。同样,为了访问矩阵,只需要使用这些有用元素的索引,因此ii(notdelete),jj(notdelete)
。我希望现在更清楚了
但是,请确保您了解自己在做什么。你陈述了
我认为M>在M <= 10之前执行0(在其他情况下发生) 编程语言)但我认为我错了
实际上M> 0在M <= 10之前执行。从左到右执行适用于其他编程语言。但是,您所做的是(M>0) & (M<=10)
,因此&
的左右部分都需要在&
之前进行评估。实际上,左边的一个将首先被评估,保存在一个辅助的内部变量中,但是然后右边的部分将被执行并保存到另一个辅助内部变量中,所以最后逻辑and
可以应用于这两个辅助变量。