有人可以帮助矢量化这个 matlab 循环吗?

Can someone help vectorise this matlab loop?

我正在尝试学习如何矢量化 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 作为一种语言在这种类型的操作上做得很差 - 你总是需要一个外部 O(N) loop/operation 涉及至少 O(K) 个副本,这在性能上不值得进一步矢量化因为 matlab 是一种重量级语言。相反,请考虑使用 filter 函数,其中这些东西通常在 C 中实现,这使得该类型的操作几乎是免费的。

你好像在表演 convolution operation there. So, just use conv -

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

请注意,我已将变量名称 input 替换为 input1,因为 input 已用作 MATLAB 中的内置函数名称,因此它是避免此类 冲突的良好做法 .


一般情况:对于一般情况,您可以查看bsxfun创建这样的组,然后选择您打算在最后执行的操作阶段。下面是这样的代码对于 sliding/moving 平均操作的样子 -

%// 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

对于滑动平均,可以使用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