Algorithm 快速计算点(a(n:end),b(1:end-n))`
假设我们有两个一维值数组Algorithm 快速计算点(a(n:end),b(1:end-n))`,algorithm,matlab,vector,convolution,numerical-methods,Algorithm,Matlab,Vector,Convolution,Numerical Methods,假设我们有两个一维值数组a和b,它们都有长度N。我想创建一个新数组c,这样c(n)=点(a(n:n),b(1:n-n+1))我当然可以使用一个简单的循环: for n=1:N c(n)=dot(a(n:N), b(1:N-n+1)); end 但考虑到这是一个类似于卷积的简单操作,我想知道是否有更有效的方法(使用Matlab)来实现这一点。这是一个有趣的问题 我假设a和b是相同长度的列向量。让我们考虑一个简单的例子: a=[9;10;2;10;7]; b=[1;3;6;10;10];
a
和b
,它们都有长度N
。我想创建一个新数组c
,这样c(n)=点(a(n:n),b(1:n-n+1))
我当然可以使用一个简单的循环:
for n=1:N
c(n)=dot(a(n:N), b(1:N-n+1));
end
但考虑到这是一个类似于卷积的简单操作,我想知道是否有更有效的方法(使用Matlab)来实现这一点。这是一个有趣的问题 我假设
a
和b
是相同长度的列向量。让我们考虑一个简单的例子:
a=[9;10;2;10;7];
b=[1;3;6;10;10];
%收益率:
c=[221;146;74;31;7];
现在让我们看看当我们计算这些向量的卷积时会发生什么:
conv(a,b)
ans=
9
37
86
166
239
201
162
170
70
>>conv2(a,b.)
ans=
9 27 54 90 90
10 30 60 100 100
2 6 12 20 20
10 30 60 100 100
7 21 42 70 70
我们注意到,c
是沿着conv2
结果的下对角线的元素之和。为了更清楚地显示,我们将进行转置,使对角线的顺序与c
中的值相同:
>triu(conv2(a.,b))
ans=
9 10 2 10 7
0 30 6 30 21
0 0 12 60 42
0 0 0 100 70
0 0 0 0 70
所以现在它变成了一个矩阵对角线求和的问题,这是一个已有的解决方案,例如Andrei Bobrov的解决方案:
C=conv2(a',b);
p=总和(spdiags(C,0:size(C,2)-1));%这将给出与循环相同的结果。
使用1D卷积的解决方案conv
:
out = conv(a, flip(b));
c = out(ceil(numel(out)/2):end);
在
conv
中,第一个向量乘以第二个向量的反转版本,因此我们需要计算a
和翻转的b
的卷积,并修剪不必要的部分。性能方面如何?你能添加一个小的计时实验吗?我为N=10^4
,a=1:N
和b=1:N
的解决方案计时。然后我做了:ticc=conv2(a',b);p1=总和(spdiags(C,0:size(C,2)-1));n=1:np2(i)=点(a(n:end),b(1:end-n+1));结束toc,第一种方法(我相信是您的解决方案)耗时2秒,而另一种方法耗时0.2秒。。我喜欢这个解决方案,它看起来很整洁,但可能不是很有效?@Darkwizie注意到tic/toc
测量实际的挂钟时间,对于性能测试可能不准确。如果一个简单的循环对于大的N
更快,那么使用instedi不会感到惊讶,因为它不涉及卷积和创建大矩阵(相对于原始1D向量)。。。循环在MATLAB中并不是天生的慢,而且很清楚在使用timeit()时会发生什么,它会产生类似的计时。