【问题标题】:Efficient ways to find minimum of subset of elements找到最小元素子集的有效方法
【发布时间】:2019-08-08 05:39:15
【问题描述】:

我试图找出矩阵中每一行的最小值,不包括这些行中的特定元素。

特别是在给定的行中,我已经预先计算了我想要包含在valid(i,:) 中的那些元素。

这样做的正确方法是什么,这是我想到的选项:

for i = 1:n
  res(i) = min(x(i, 1, valid(i,:)), [], 3);
  ...
end

根据我对 matlab 的了解,这会更有效:

res = min(x(:, 1, valid), [], 3);

但是,这只会将单个过滤器应用于第 3 维...

【问题讨论】:

  • 这是一个有趣的问题,您能否为此提供一个示例输入以及您的预期输出是什么?
  • 你如何定义这些元素?您的代码选择一行,并从该行中选择一个特定元素,然后计算沿第三维的最大值,这只是一个元素......除非valid(i) 以某种方式不同于单个值。您是在寻找最小行,还是每行中的最小值?一些示例输入 + 输出肯定会澄清一些事情。
  • @CrisLuengo 对不起valid(i) 是为了返回一个矩阵(我来自更函数化的编程背景......)
  • 啊,是的,您无法区分 MATLAB 中的函数调用和矩阵索引操作。尽管如此,我关于您的目标的问题仍然存在:“最少行数”是指每行的最小值,还是所有行的最小值。英语有时也很模棱两可。
  • 如果验证条件从一行更改为下一行(这就是我从 valid(i,:) 中理解的内容,以及您对另一个解决方案只有“单一”过滤器这一事实的评论) ,那么我认为您通过 for 循环做事的方式实际上是有效的方式。您当然可以将其转换为矢量化单线(例如使用 arrayfun),但您可能不会在此过程中获得任何效率(任何效率提升都取决于您将在生产中使用的矩阵的大小,让我们知道这是否相关)。

标签: matlab


【解决方案1】:

您可以使用accumarray 执行此操作,如下所示。不确定它是否会比您的答案更快:

[~, jj] =  find(valid); % column indices, to be used as grouping variable
res = accumarray(jj, x(valid), [size(x,2) 1], @min, NaN); % NaN used as fill value

【讨论】:

    【解决方案2】:

    玩了一会儿,发现利用 matlab 处理 NaN 值的方式非常有效。

    特别是在这种情况下:

    xp = x;
    xp(~valid) = NaN;
    
    res = min(xp,[],3);
    

    这给出了大约 100 倍的保守加速,因为之前的版本(显式循环)每次迭代需要大约 10 秒,而现在 100 次迭代需要大约 5 秒。

    注意:有一种极端情况,如果没有任何有效元素,那么您最终会得到 NaN 作为该行的结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-29
      • 2021-11-11
      • 2014-09-21
      • 1970-01-01
      • 2018-11-18
      • 1970-01-01
      • 2019-07-02
      相关资源
      最近更新 更多