【问题标题】:How to get indexes of logical matrix without using find in matlab?如何在matlab中不使用find获取逻辑矩阵的索引?
【发布时间】:2020-01-01 15:03:38
【问题描述】:

假设我的矩阵 A 是比较函数的输出,即只有值 0 和 1 的逻辑矩阵。对于一个大小为 3*4 的小矩阵,我们可能有这样的东西:

A =

     1     1     0     0
     0     0     1     0
     0     0     1     1

现在,我正在生成另一个与 A 大小相同的矩阵 B,但它的行填充了 A 的索引,并且每行中的任何剩余值都设置为零。

B =

     1     2     0     0
     3     0     0     0
     3     4     0     0

目前我在A的每一行使用find函数来得到矩阵B。完整的代码可以写成:

A=[1,1,0,0;0,0,1,0;0,0,1,1];
[rows,columns]=size(A);
B=zeros(rows,columns);

for i=1:rows
    currRow=find(A(i,:));
    B(i,1:length(currRow))=currRow;
end

对于大型矩阵,根据 Matlab Profiler,“查找”功能在计算中需要时间。有什么方法可以更快地生成矩阵 B 吗?

注意: 矩阵 A 每行有超过 1000 列,但非零元素永远不会超过 50。在这里,我将矩阵 B 与 A 的大小相同,但矩阵 B 的列大小可以小得多。

【问题讨论】:

  • 您可以将find 替换为索引操作,但如果这样更快,我会感到惊讶。 I = 1:columns; currRow = I(A(i,:));
  • 我一直在考虑可以完全删除“for”循环以加快操作。这可能吗?
  • 您是否考虑将矩阵存储为sparse 矩阵?我还将存储矩阵的转置,以便沿列进行搜索,就像它们在 MATLAB 中存储的方式一样。
  • for Matlab 中的循环不一定很慢。从历史上看,它们是,但现在情况并非如此。根据 Cris 和 beaker 的建议,我不希望矢量化版本更快。

标签: matlab


【解决方案1】:

我建议使用parfor,但是这里的开销太大,而且问题较多,所以不是一个好的解决方案。

rows = 5e5;
cols = 1000;
A = rand(rows, cols) < 0.050;
I = uint16(1:cols);
B = zeros(size(A), 'uint16');
% [r,c] = find(A);
tic
for i=1:rows
%     currRow = find(A(i,:));
    currRow = I(A(i,:));
    B(i,1:length(currRow)) = currRow;
end
toc

@Cris 建议用索引操作替换find。它将性能提高了约 10%。

显然,除非B 必须采用您所说的特定形式,否则没有更好的优化。如果矩阵形式不需要索引,我建议使用[r,c] = find(A);

【讨论】:

  • 我一直在考虑可以完全删除“for”循环以加快操作。这可能吗?
  • 不,您需要区别对待每一行。像I = repmat(uint16(1:cols), rows, 1); B = I(A); 这样的东西给出了一个输出,但它不知道每个结果属于哪一行。
猜你喜欢
  • 2012-07-10
  • 2023-03-04
  • 2013-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-02
  • 1970-01-01
  • 2013-05-13
相关资源
最近更新 更多