如何有效地垂直组合稀疏矩阵

时间:2013-03-14 20:12:22

标签: matlab indexing block sparse-matrix

我的目标是将许多稀疏矩阵组合在一起形成一个大的稀疏矩阵。我能够想到的唯一两个想法是(1)创建一个大的稀疏矩阵并覆盖某些块,(2)单独创建块使用vertcat来形成我的最终稀疏矩阵。但是,我已经读过overwriting稀疏矩阵的效率非常低,而且我还读到了vertcat的计算效率并不完全。 (我没有考虑使用for循环,因为它们效率低下。)

那么我还有其他什么选择?

编辑:通过组合我的意思是“粘合”矩阵(垂直),元素不会相互作用。

2 个答案:

答案 0 :(得分:5)

根据matlab的帮助,你可以用

“反汇编”稀疏矩阵
[i,j,s] = find(S);

这意味着如果您有两个矩阵ST,并且您希望(有效地)vertcat它们,那么您可以

[is, js, ss] = find(S);
[it, jt, st] = find(T);
ST = sparse([is; it + size(S,1)], [js; jt], [ss; st]);

不确定这是否非常有效......但我猜它不是太糟糕。

编辑:使用密度为1%的2000x1000稀疏矩阵,并将其与另一个密度为2%的稀疏矩阵相结合,上述代码在我的机器上运行0.016秒。只做[S;T]的速度提高了10倍。是什么让你觉得垂直连接很慢?

EDIT2:假设您需要使用“许多”稀疏矩阵执行此操作,以下工作(假设您希望它们全部“在同一位置”):

m = 1000; n = 2000; density = 0.01;
N = 100;
Q = cell(1, N);
is = Q;
js = Q;
ss = Q;
numrows = 0; % keep track of dimensions so far

for ii = 1:N
    Q{ii} = sprandn(m+ii, n-jj, density); % so each matrix has different size
    [a b c] = find(Q{ii});
    sz = size(Q{ii}); 
    is{ii} = a' + numrows; js{ii}=b'; ss{ii}=c'; % append "on the corner"
    numrows = numrows + sz(1); % keep track of the size
end

tic
ST = sparse([is{:}], [js{:}], [ss{:}]);
fprintf(1, 'using find takes %.2f sec\n', toc);

输出:

using find takes 0.63 sec

这种方法的一大优点是你不需要在你的各个稀疏数组中拥有相同数量的列......它将全部通过sparse命令进行整理,这将只考虑缺少列全为零。

答案 1 :(得分:0)

考虑到已经给出的答案。

我稍微改变了实验,为了能够垂直连接矩阵(它应该具有相同的宽度),所以我们不需要通过提取 n 来调整 ii(这是jj 输入错误)。

这种方法

tic
ST = sparse([is{:}], [js{:}], [ss{:}]);
fprintf(1, 'using find takes %.2f sec\n', toc);

它的 0.45 sec 比这个慢得多

tic
ST = vertcat(Q{:});
fprintf(1, 'using vertcat takes %.2f sec\n', toc);

平均 0.18 sec

我也用探查器检查过,第一个例子预计速度较慢,因为至少内存分配高出 100 倍。很可能是因为 [ss{:}] 数组构造将数据显式复制到新数组。

然而,即使使用预先计算的向量,0,3 sec 的速度也是 0,18 secvertcat

因此,我建议 vertcat 是解决原始问题的更好选择。至少在 2021 年 :)