【问题标题】:How to Efficiently Combine Sparse Matrices Vertically如何有效地垂直组合稀疏矩阵
【发布时间】:2013-03-03 09:23:49
【问题描述】:

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

那我还有什么其他选择?

编辑:结合我的意思是(垂直)将矩阵“粘合”在一起,元素不会相互作用。

【问题讨论】:

  • 如果你把它们加在一起会发生什么?更具体地说 - 你的矩阵的维度是多少,你的书中的“组合”矩阵是什么样的?你能举个玩具的例子吗?
  • @Floris 尺寸范围可以从 2x2 到 2^18 x 2^18 或任何 Matlab 可以为我的脚本处理的最大值。我认为一个错误会在 2^18 左右产生。一个玩具例子可以是任意的。我的矩阵中唯一固定的是第一个和最后一个块,它们是speye,但两者之间的一切都不同(尽管它们的大小是固定的)
  • @Floris 我也无法添加它们 b/c 我无法找出适用于所有矩阵的全局索引。不过我刚看到你的帖子,所以我认为这不会是问题。
  • 我想我的问题是“你打算如何结合”。当您将 10x10 和 10x10 组合时,结果是 10x10 还是 20x10?
  • @Floris 啊,我明白了。抱歉,10x10 加上 5x10 就是 15x10。元素不交互。

标签: matlab indexing block sparse-matrix


【解决方案1】:

根据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 命令排序,该命令将简单地考虑丢失的列全部为零。

【讨论】:

  • 那你还建议用vertcat还是find?
  • find 方法(以及我正在使用 [is{:}] 做的隐式 horzcat )似乎非常有效。您可能会问自己是如何生成原始(源)稀疏矩阵的;如果您一开始就使用(i,j,s) 格式,则可能永远不需要中间的find 步骤...
  • 在for循环的第一行,你的意思是n-ii吗? jj 没有定义?
  • 是的,当然 - 错字。只是想制作不同大小的矩阵,以证明我可以......我无法从运行 matlab 的计算机上复制/粘贴(长篇故事),所以必须将其输入。我的错。
【解决方案2】:

考虑到已经给出的答案。

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

这种方法

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 sec0,18 secvertcat

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-07
    • 2019-05-26
    • 1970-01-01
    • 1970-01-01
    • 2012-06-30
    • 2021-04-14
    • 2018-08-07
    • 2012-05-18
    相关资源
    最近更新 更多