有人可以帮助矢量化这个 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
我正在尝试学习如何矢量化 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