conv
函数非常适合你:
>> x = 1:8;
>> y = conv(x, ones(1,5), 'valid')
y =
15 20 25 30
基准测试
三个答案,三种不同的方法... 这里是一个快速的基准测试(不同的输入大小,固定窗口宽度为5),使用timeit
; 如果您认为需要改进,请随意在评论中提出。
conv
成为最快的方法; 它比coin的方法(使用filter
) 快两倍左右,比Luis Mendo的方法(使用cumsum
) 快四倍左右。
![enter image description here](https://istack.dev59.com/fQNUH.webp)
这里是另一个基准测试(固定输入大小为1e4
,不同的窗口宽度)。 在这里,Luis Mendo的cumsum
方法成为明显的赢家,因为它的复杂性主要取决于输入长度,并且对窗口的宽度不敏感。
![enter image description here](https://istack.dev59.com/61zbb.webp)
结论
总之,您应该
- 如果您的窗口相对较小,请使用
conv
方法,
- 如果您的窗口相对较大,请使用
cumsum
方法。
代码(用于基准测试)
function benchmark
clear all
w = 5;
u = ones(1, w);
n = logspace(2,6,60);
t1 = zeros(size(n));
t2 = t1;
th = t1;
for k = 1 : numel(n)
x = rand(1, round(n(k)));
f = @() luisMendo(w, x);
tf(k) = timeit(f);
g = @() coin(w, u, x);
tg(k) = timeit(g);
h = @() jubobs(u, x);
th(k) = timeit(h);
end
figure
hold on
plot(n, tf, 'bo')
plot(n, tg, 'ro')
plot(n, th, 'mo')
hold off
xlabel('input size')
ylabel('time (s)')
legend('cumsum', 'filter', 'conv')
end
function y = luisMendo(w,x)
cs = cumsum(x);
y(1,numel(x)-w+1) = 0;
y(1) = cs(w);
y(2:end) = cs(w+1:end) - cs(1:end-w);
end
function y = coin(w,u,x)
y = filter(u, 1, x);
y = y(w:end);
end
function jubobs(u,x)
y = conv(x, u, 'valid');
end
function benchmark2
clear all
w = round(logspace(1,3,31));
n = 1e4;
t1 = zeros(size(n));
t2 = t1;
th = t1;
for k = 1 : numel(w)
u = ones(1, w(k));
x = rand(1, n);
f = @() luisMendo(w(k), x);
tf(k) = timeit(f);
g = @() coin(w(k), u, x);
tg(k) = timeit(g);
h = @() jubobs(u, x);
th(k) = timeit(h);
end
figure
hold on
plot(w, tf, 'bo')
plot(w, tg, 'ro')
plot(w, th, 'mo')
hold off
xlabel('window size')
ylabel('time (s)')
legend('cumsum', 'filter', 'conv')
end
function y = luisMendo(w,x)
cs = cumsum(x);
y(1,numel(x)-w+1) = 0;
y(1) = cs(w);
y(2:end) = cs(w+1:end) - cs(1:end-w);
end
function y = coin(w,u,x)
y = filter(u, 1, x);
y = y(w:end);
end
function jubobs(u,x)
y = conv(x, u, 'valid');
end
conv
函数。 - jub0bs