【问题标题】:Number of values greater than a threshold大于阈值的值的数量
【发布时间】:2012-09-26 02:45:45
【问题描述】:

我有一个矩阵A。现在我想找到大于 5 的元素数量及其对应的索引。不使用for循环如何在matlab中解决这个问题?

例如如果A = [1 4 6 8 9 5 6 8 9]':

  • 元素数量 > 5:6
  • 指数:[3 4 5 7 8 9]

【问题讨论】:

    标签: matlab indexing


    【解决方案1】:

    你使用find:

    index = find(A>5);
    numberOfElements = length(index);
    

    【讨论】:

      【解决方案2】:

      您使用sum,它允许您通过一个命令获取元素的数量:

      numberOfElements = sum(A>5);
      

      您真的需要显式索引吗?因为逻辑矩阵A>5 也可以用作索引(通常比使用find 索引更高效):

      index = (A>5);
      numberOfElements = sum(index);
      

      为了完整性:逻辑索引与常规索引相同:

      >> A(A>5)
      ans = 
           6  8  9  6  8  9
      

      【讨论】:

      • Rody,你对sum/find 的看法可能是对的。但是,无论如何您都必须存储索引。否则,您最终会计算 A>5 两次。此外,sum 可能比 find 快,但 A(integer_index) 比 A(logical_index) 快,因为 logical_index 是一个 0-1 向量,与您的数据大小一样,而 integer_index 仅包含必要的值。
      • @angainor:当然,只需使用index=A>5; numEls = sum(index);。加:逻辑索引比find索引更快;自己试试。至于内存开销,这真的取决于——find 返回双精度数(每个条目 64 位),而逻辑索引是布尔值(每个条目可能是 8 位,甚至可能 1 位)——在此不能对两者做出全面的陈述尊重。
      • 您可以将双精度转换为 uint(16/32/64) - 实际上您应该这样做,因为使用双精度进行索引在性能方面是一个相当糟糕的主意。逻辑当前是 (2011b+) 1 字节。在早期版本中,它们是 4 个字节 :) 但是是的,这一切都取决于.. 有没有办法在 SO 上发布带有基准的代码?我想我可以用我写的基准代码来回答这个问题。或者有其他选择吗?
      • @angainor:聊天室 :) 但实际上,我认为答案是最佳实践。我还怀疑 Matlab 隐式地将双索引转换为 uints,我怀疑这部分是性能差异的来源。
      【解决方案3】:

      受上述与 Rody 讨论的启发,这里有一个简单的基准测试,用于测试 MATLAB 中整数与逻辑数组索引的速度。我要说的是一件很重要的事情,因为“矢量化” MATLAB 主要是关于索引的。所以

      % random data
      a = rand(10^7, 1);
      
      % threashold - how much data meets the a>threashold criterion
      % This determines the total indexing time - the more data we extract from a,
      % the longer it takes.
      % In this example - small threashold meaning most data in a 
      % will meet the criterion.
      threashold = 0.08;
      
      % prepare logical and integer indices (note the uint32 cast)
      index_logical = a>threashold;
      index_integer = uint32(find(index_logical));
      
      % logical indexing of a
      tic
      for i=1:10
          b = a(index_logical);
      end
      toc
      
      % integer indexing of a
      tic
      for i=1:10
          b = a(index_integer);
      end
      toc
      

      在我的电脑上结果是

      Elapsed time is 0.755399 seconds.
      Elapsed time is 0.728462 seconds.
      

      意味着这两种方法的执行几乎相同——这就是我选择示例threashold 的方式。这很有趣,因为index_integer 数组几乎大了 4 倍!

      index_integer       9198678x1              36794712  uint32               
      index_logical      10000000x1              10000000  logical              
      

      对于较大的threashold 整数索引值更快。 threashold=0.5 的结果:

      Elapsed time is 0.687044 seconds. (logical)
      Elapsed time is 0.296044 seconds. (integer)
      

      除非我在这里做错了什么,否则整数索引在大多数情况下似乎是最快的。

      在测试中包含索引的创建会产生非常不同的结果:

      a = rand(1e7, 1);    
      threshold = 0.5;
      
      % logical 
      tic
      for i=1:10
          inds = a>threshold;
          b = a(inds);
      end
      toc
      
      % double
      tic
      for i=1:10
          inds = find(a>threshold);
          b = a(inds);
      end
      toc
      
      % integer 
      tic
      for i=1:10
          inds = uint32(find(a>threshold));
          b = a(inds);
      end
      toc
      

      结果(罗迪):

      Elapsed time is 1.945478 seconds. (logical)
      Elapsed time is 3.233831 seconds. (double)
      Elapsed time is 3.508009 seconds. (integer)
      

      结果(变化):

      Elapsed time is 1.440018 seconds. (logical)
      Elapsed time is 1.851225 seconds. (double)
      Elapsed time is 1.726806 seconds. (integer)
      

      因此,使用整数索引时,实际索引似乎更快,但从前到后的逻辑索引性能要好得多。

      虽然最后两种方法之间的运行时差异是出乎意料的——看起来 Matlab 的内部要么不会将双精度数转换为整数,而是在执行实际索引之前对每个元素执行错误检查。否则,我们会发现 double 和 integer 方法之间几乎没有区别。

      编辑在我看来有两个选项:

      • matlab 在索引调用之前将双索引显式转换为 uint32 索引(就像我们在整数测试中所做的那样)
      • matlab 传递双精度并在索引调用期间即时执行 double->int 强制转换

      第二个选项应该更快,因为我们只需要读取一次双索引。在我们的显式转换测试中,我们必须读取双索引,写入整数索引,然后在实际索引期间再次读取整数索引。所以matlab应该更快...为什么不是呢?

      【讨论】:

      • +1:很好的测试,虽然我很想看看索引的创建如何影响时间。介意我编辑吗?
      • @RodyOldenhuis 哦,继续。我希望我们在这里得出有趣的结论。
      • @RodyOldenhuis 第一个测试有一个b = a() 声明,我猜这是错误的。这会影响你的结果吗?是的,根据我的经验,matlab 将双精度数显式转换为整数(通过检查 - 还能如何?)。这就是为什么有时使用显式整数更好。
      • 哎呀!!复制粘贴错误传播的经典案例。现在修复:)
      • 哇,你的结果比我的好多了……为什么呢?你有什么处理器?我的笔记本电脑上有一个 Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz。相当糟糕,双核。
      猜你喜欢
      • 2019-04-26
      • 1970-01-01
      • 1970-01-01
      • 2016-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多