【问题标题】:Can someone help vectorise this matlab loop?有人可以帮助矢量化这个 matlab 循环吗?
【发布时间】:2015-04-29 06:39:58
【问题描述】:

我正在尝试学习如何向量化 matlab 循环,所以我只是做了一些小例子。

这是我试图矢量化的标准循环:

function output = moving_avg(input, N)
    output = [];
    for n = N:length(input) % iterate over y vector
        summation = 0;
            for ii = n-(N-1):n % iterate over x vector N times
                summation += input(ii);
            endfor
        output(n) = summation/N;
    endfor 
endfunction

我已经能够矢量化一个循环,但无法弄清楚如何处理第二个循环。到目前为止,这是我要去的地方:

function output = moving_avg(input, N)
    output = [];
    for n = N:length(input) % iterate over y vector
        output(n) = mean(input(n-(N-1):n));
    endfor 
endfunction

有人可以帮我进一步简化吗?

编辑:
输入只是一个一维向量,可能最多 100 个数据点。 N 是单个整数,小于输入的大小(通常可能在 5 左右)

我实际上并不打算将它用于任何特定的应用程序,它只是一个简单的嵌套循环,我认为它可以很好地用于学习矢量化..

【问题讨论】:

  • 输入的维度是多少?您正在使用哪些数据大小?
  • 我已经更新了帖子..

标签: matlab vectorization


【解决方案1】:

好像你在那里表演convolution operation。所以,只需使用conv -

output = zeros(size(input1))
output(N:end) = conv(input1,ones(1,N),'valid')./N

请注意,我已将变量名input 替换为input1,因为input 已被用作MATLAB 中的内置函数的名称,因此最好避免使用此类冲突


一般案例:对于一般案例场景,您可以查看bsxfun 以创建此类组,然后选择您打算在最后阶段执行的操作。下面是这样的代码在滑动/移动平均操作中的样子 -

%// Create groups of indices for each sliding interval of length N
idx = bsxfun(@plus,[1:N]',[0:numel(input1)-N])  %//'

%// Index into input1 with those indices to get grouped elements from it along columns
input1_indexed = input1(idx)

%// Finally, choose the operation you intend to perform and apply along the
%// columns. In this case, you are doing average, so use mean(...,1).
output = mean(input1_indexed,1)
%// Also pre-append with zeros if intended to match up with the expected output

【讨论】:

    【解决方案2】:

    Matlab 作为一种语言,这种类型的操作做得很差——你总是需要一个外部 O(N) 循环/操作,涉及至少 O(K) 个副本,这在性能上不值得进一步矢量化,因为 matlab 是一个重量级的语言。相反,请考虑使用 filter 函数,这些东西通常在 C 中实现,这使得这种类型的操作几乎免费。

    【讨论】:

    • 感谢您的回复,就像我说的,我不一定对这个特定的函数本身感兴趣,只是想了解一下 matlab 中的矢量化循环
    • 啊,在你提到这个之前,那个帖子已经准备好了。这不是用于矢量化的好例子。而是专注于使用 bsxfun 的示例,这肯定会向您展示更多有趣的示例。如果你真的想在矢量化上疯狂,看看爱因斯坦求和:en.wikipedia.org/wiki/Einstein_notationMatlab 可能没有一流的支持,但 numpy 有:docs.scipy.org/doc/numpy/reference/generated/numpy.einsum.html 除了 bsxfun,它是最有趣和性能最好的之一改进我见过的功能。
    【解决方案3】:

    对于滑动平均,您可以使用cumsum 来最小化操作次数:

    x = randi(10,1,10);                      %// example input
    N = 3;                                   %// window length
    y = cumsum(x);                           %// compute cumulative sum of x
    z = zeros(size(x));                      %// initiallize result to zeros
    z(N:end) = (y(N:end)-[0 y(1:end-N)])/N;  %// compute order N difference of cumulative sum
    

    【讨论】:

    • 聪明但更像动态编程而不是矢量化。那么结束和开始的结果呢?大多数时候人们也想要那些:-)!
    • @JasonNewton 我删除了最后的结果,因为原始帖子中的代码这样做了。但是包含它们会很容易
    猜你喜欢
    • 2013-12-12
    • 1970-01-01
    • 2021-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多