Matlab含重复冗余索引的矩阵累加操作向量化实现方法
含重复索引的矩阵向量化累加方案
你遇到的重复索引赋值失效问题,源于MATLAB的索引赋值机制:当索引列表存在重复值时,赋值流程只会保留索引最后一次出现位置的写入结果,不会自动对同位置的多个输入值做累加。另外需要额外注意:
哪怕is、js无重复值,直接写A(is,js) = A(is,js) + ws也是错误写法——该语法会取is和js的笛卡尔积生成子矩阵,完全不满足逐点匹配(is(k),js(k))位置的需求。
以下是两种完全无循环、适配大规模含重复索引场景的向量化实现:
方案1:accumarray聚合实现(通用场景最优)
accumarray是MATLAB原生提供的按索引聚合数据的函数,专门应对同索引下的值合并需求,对稠密、稀疏矩阵都有很好的性能表现,实现代码如下:
% 直接传入行列坐标聚合 A = A + accumarray([is(:), js(:)], ws(:), size(A), @sum, 0); % 如果已经提前生成了线性索引,也可以用线性索引聚合 % lin_idx = sub2ind(size(A), is, js); % A = A + accumarray(lin_idx(:), ws(:), size(A), @sum, 0);
参数说明:
[is(:), js(:)]将行列索引整理为n行2列的坐标矩阵,和ws里的值一一对应size(A)指定输出增量矩阵的尺寸和原矩阵完全一致@sum指定同索引位置的聚合规则为求和,匹配累加需求- 末尾的
0为默认填充值,无索引指向的位置统一补0,不会修改原矩阵对应位置的值
用你给出的测试样例验证:
A = zeros(3,3); % 线性索引[1,2,3,1]对应行列坐标为行[1,2,3,1]、列[1,1,1,1] is = [1;2;3;1]; js = [1;1;1;1]; ws = [5;5;5;5]; A = A + accumarray([is, js], ws, size(A), @sum, 0);
运行后A(1,1)结果为10,其余第一列位置值为5,和预期完全一致。
方案2:稀疏矩阵构造实现(高维稀疏场景最优)
MATLAB构造稀疏矩阵时,会自动对同坐标位置的输入值做求和处理,不会出现重复索引覆盖的问题,写法更简洁,适合矩阵维度高、非零值占比低的场景:
A = A + full(sparse(is, js, ws, size(A,1), size(A,2)));
如果你的后续计算本身就支持稀疏矩阵,还可以去掉full()直接保留稀疏格式,进一步降低内存占用、提升计算速度。
注意:以上两种方案都不需要提前对索引做去重处理,全程调用MATLAB内置的向量化运算逻辑,对于百万级以上长度的索引列表,运行效率比原生for循环高数十到上百倍。
内容的提问来源于stack exchange,提问作者Grey Haven
相关产品推荐
相关产品推荐

