【问题标题】:For large sparse matrices in MATLAB, compute the cumulative sum across the columns for non-zero entries?对于 MATLAB 中的大型稀疏矩阵,计算非零条目的列的累积和?
【发布时间】:2013-09-17 19:47:48
【问题描述】:

MATLAB 中有一个带有转移概率的大矩阵transition_probs,和一个邻接矩阵adj_mat。我想计算沿列的转换矩阵的累积和,然后将其与邻接矩阵相乘,邻接矩阵以这种方式充当掩码:

cumsumTransitionMat = cumsum(transition_probs,2) .* adj_mat;

我收到一个 MEMORY 错误,因为使用 cumsum 时,矩阵的所有条目都非零。

我想通过只在有非零条目的地方设置累积和条目来避免这个问题。如果不使用for 循环,如何做到这一点?

【问题讨论】:

    标签: matlab memory matrix sparse-matrix adjacency-matrix


    【解决方案1】:

    当对行应用 CUMSUM 时,对于每一行,它将填充从它找到的第一个非零列开始直到最后一列的值,这就是它的定义。

    就存储而言,最坏的情况是稀疏矩阵在第一列包含值,最好的情况是所有非零值都出现在最后一列。示例:

    % worst case
    >> M = sparse([ones(5,1) zeros(5,4)]);
    >> MM = cumsum(M,2);       % completely dense matrix
    >> nnz(MM)
    ans =
        25
    
    % best case
    >> MM = cumsum(fliplr(M),2);
    

    如果生成的矩阵不适合内存,我看不出你还能做什么,除了可能在行上使用 for 循环,并以较小的批次处理矩阵...

    请注意,您不能在计算累积和之前应用屏蔽操作,因为这会改变结果。所以你不能说cumsum(transition_probs .* adj_mat, 2)

    【讨论】:

    • 所以不可能?你知道我想做什么吗?我想制作一个马尔可夫转换矩阵。因此,在一行(状态)中,只有一组特定的非零条目,即可能的状态转换,由 1/0 的邻接矩阵表示。对于这些状态转换,我有一组概率。我为候选下一个状态抛出一个随机数,并希望查看它在累积总和中的哪个列号值之间。我还能怎么做?
    • 好吧,好像每次有过渡时我都会逐行计算它
    • 是的,我想我理解了代码应该做什么(基本上你想根据与当前状态的转换概率相对应的权重向量选择下一个状态,但仅限于相邻状态只要)。您正在实施randsample。问题是,当一次计算整个矩阵的结果时,它太密集而无法放入内存中。这就是为什么我建议逐行循环而不是矢量化调用的原因。抱歉,我无法提供更多帮助:)
    • 再想一想,我认为可能还有改进代码的空间。但首先你能更详细地解释你在做什么吗?我不明白您为什么首先要计算整个矩阵的累积和。如果您知道自己处于状态i,您只需要查看其对应的行transition_probs(i,:),我的理解是否正确?跨度>
    • 是的,这是正确的,我现在有代码 cumsumTransitionRow = cumsum(transitionMat(row_temp,:)) . graph_com(row_temp,:); nodesLess = find(rand <= cumsumTransitionRow(:));,所以我计算该状态 i 的感兴趣行,转换矩阵的适当行号,将其屏蔽并使用可交换矩阵采样下一个状态的转移概率之和
    【解决方案2】:

    您只能将cumsum 应用于非零元素。这是一些代码:

    A = sparse(round(rand(100,1)));        %some sparse data
    A_cum = A;                             %instantiate A_cum by copy A
    
    idx_A = find(A);                       %find non-zeros
    A_cum(idx_A) = cumsum(A(idx_A)); %cumsum on non-zeros elements only 
    

    你可以检查输出

     B = cumsum(A);
    
    
       A_cum   B
         1     1
         0     1
         0     1
         2     2
         3     3
         4     4
         5     5
         0     5
         0     5
         6     6
    

    isequal(A_cum(find(A_cum)), B(find(A_cum))) 给出1

    【讨论】:

    • 我不确定这是否有效。使用 A_cum 的结果不同
    • 请查看编辑 - 结果与我相同:非零 A 元素及其对应的 B 相同。除非我没有正确理解您的评论或问题。你能详细说明一下吗?
    猜你喜欢
    • 2014-04-18
    • 2021-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-04
    • 2019-06-28
    相关资源
    最近更新 更多