我有2个矩阵: V ,它是平方MxM, K 是MxN。调整行x
的维度和列t
的维度,我需要评估 K 的两个维度的积分(即和)乘以t移位版本 V ,答案是转变的函数(几乎像卷积,见下文)。总和由以下表达式定义,其中_{}
表示求和指数,并假设超出限制元素的零填充:
S(t) = sum_{x,tau}[V(x,t+tau) * K(x,tau)]
我设法在t
维度(向量化x
维度)上使用单个循环执行此操作:
% some toy matrices
V = rand(50,50);
K = rand(50,10);
[M N] = size(K);
S = zeros(1, M);
for t = 1 : N
S(1,1:end-t+1) = S(1,1:end-t+1) + sum(bsxfun(@times, V(:,t:end), K(:,t)),1);
end
我有类似的表达式,我设法在没有for循环的情况下进行评估,使用conv2
和\或镜像(翻转)单个维度的组合。但是在这种情况下我无法看到如何避免for循环(尽管看起来与卷积相似)。
答案 0 :(得分:1)
矢量化步骤
1]对于K中的所有列,使用矩阵乘法对V中的所有列执行sum(bsxfun(@times, V(:,t:end), K(:,t)),1)
-
sum_mults = V.'*K
这将为我们提供一个2D数组,每列代表sum(bsxfun(@times,..
每次迭代的操作。
2] Step1为我们提供了所有可能的求和,并且要求求和的值在迭代中不在同一行中对齐,因此我们需要在沿行求和之前再做一些工作。其余的工作是关于获得升级版本。同样,您可以使用带有上下三角形布尔掩码的布尔索引。最后,我们将每一行汇总为最终输出。所以,这部分代码看起来就是这样 -
valid_mask = tril(true(size(sum_mults)));
sum_mults_shifted = zeros(size(sum_mults));
sum_mults_shifted(flipud(valid_mask)) = sum_mults(valid_mask);
out = sum(sum_mults_shifted,2);
运行时测试 -
%// Inputs
V = rand(1000,1000);
K = rand(1000,200);
disp('--------------------- With original loopy approach')
tic
[M N] = size(K);
S = zeros(1, M);
for t = 1 : N
S(1,1:end-t+1) = S(1,1:end-t+1) + sum(bsxfun(@times, V(:,t:end), K(:,t)),1);
end
toc
disp('--------------------- With proposed vectorized approach')
tic
sum_mults = V.'*K; %//'
valid_mask = tril(true(size(sum_mults)));
sum_mults_shifted = zeros(size(sum_mults));
sum_mults_shifted(flipud(valid_mask)) = sum_mults(valid_mask);
out = sum(sum_mults_shifted,2);
toc
输出 -
--------------------- With original loopy approach
Elapsed time is 2.696773 seconds.
--------------------- With proposed vectorized approach
Elapsed time is 0.044144 seconds.
答案 1 :(得分:0)
这可能是作弊(使用arrayfun
而不是for
循环),但我相信这个表达式可以为您提供所需内容:
S = arrayfun(@(t) sum(sum( V(:,(t+1):(t+N)) .* K )), 1:(M-N), 'UniformOutput', true)