Matlab 三重加权和

Matlab 三重加权和,matlab,vectorization,weighted-average,Matlab,Vectorization,Weighted Average,我试图对某个加权和进行矢量化,但不知道如何实现。我在下面创建了一个简单的最小工作示例。我猜解决方案涉及bsxfun或Reforme和kronecker产品,但我仍然没有设法让它工作 rng(1); N = 200; T1 = 5; T2 = 7; T3 = 10; A = rand(N,T1,T2,T3); w1 = rand(T1,1); w2 = rand(T2,1); w3 = rand(T3,1); B = zeros(N,1); for i = 1:N for j1=1:T1

我试图对某个加权和进行矢量化,但不知道如何实现。我在下面创建了一个简单的最小工作示例。我猜解决方案涉及bsxfun或Reforme和kronecker产品,但我仍然没有设法让它工作

rng(1);
N = 200;
T1 = 5;
T2 = 7;
T3 = 10;


A = rand(N,T1,T2,T3);
w1 = rand(T1,1);
w2 = rand(T2,1);
w3 = rand(T3,1);

B = zeros(N,1);

for i = 1:N
 for j1=1:T1
  for j2=1:T2
   for j3=1:T3
    B(i) = B(i) + w1(j1) * w2(j2) * w3(j3) * A(i,j1,j2,j3);
   end
  end
 end
end

A = B;

对于二维情况,有一个聪明的答案。

您可以使用额外的乘法修改上一个答案的
w1*w2'
网格,然后再乘以
w3
。然后,您可以再次使用矩阵乘法与
a
的“展平”版本进行乘法

W = reshape(w1 * w2.', [], 1) * w3.';
B = reshape(A, size(A, 1), []) * W(:);
您可以将权重的创建封装到它自己的函数中,并将其概括为
N
weights。由于这使用递归,
N
被限制为当前的递归限制(默认为500)

并将其用于:

W = createWeights(w1, w2, w3);
B = reshape(A, size(A, 1), []) * W(:);
更新

使用@CKT的一部分非常好的建议来使用
kron
,我们可以稍微修改
createWeights

function W = createWeights(W, varargin)
    if numel(varargin) > 0
        W = createWeights(kron(varargin{1}, W), varargin{2:end});
    end
end

这就是背后的逻辑:

ww1 = repmat (permute (w1, [4, 1, 2, 3]), [N, 1,  T2, T3]);
ww2 = repmat (permute (w2, [3, 4, 1, 2]), [N, T1, 1,  T3]);
ww3 = repmat (permute (w3, [2, 3, 4, 1]), [N, T1, T2, 1 ]);

B = ww1 .* ww2 .* ww3 .* A;
B = sum (B(:,:), 2)
通过首先在适当的维度中创建
w1
w2
w3
,可以避免
permute
。您也可以使用
bsxfun
而不是
repmat
,以获得更高的性能,我只是在这里展示逻辑,而且
repmat
更容易理解

编辑:任意输入维度的通用版本:

Dims   = {N, T1, T2, T3};  % add T4, T5, T6, etc as appropriate
Params = cell (1, length (Dims));

Params{1} = rand (Dims{:});
for n = 2 : length (Dims)
  DimSubscripts = ones (1, length (Dims));  DimSubscripts(n) = Dims{n};
  RepSubscripts = [Dims{:}];  RepSubscripts(n) = 1;
  Params{n} = repmat (rand (DimSubscripts), RepSubscripts);
end

B = times (Params{:});
B = sum (B(:,:), 2)

同样,除非你做了一些函数来构造Kronecker积向量,否则你不能把它推广到N-D,但是呢

  A = reshape(A, N, []) * kron(w3, kron(w2, w1));

如果我们要走有功能的路线,并且倾向于表现在优雅/简洁上,那么考虑一下:

function B = weightReduce(A, varargin)

    B = A;
    for i = length(varargin):-1:1
        N = length(varargin{i});
        B = reshape(B, [], N) * varargin{i};
    end

end
这是我看到的性能比较:

tic;
for i = 1:10000
    W = createWeights(w1,w2,w3);
    B = reshape(A, size(A,1), [])*W(:);
end
toc
Elapsed time is 0.920821 seconds.
tic; 
for i = 1:10000
    B2 = weightReduce(A, w1, w2, w3); 
end
toc
Elapsed time is 0.484470 seconds.

你需要概括一下吗?因为如果是这样的话,我会把你的N,T1,T2,T3换成一个数组,实际上我只是想要三维的情况。但是概括可能对其他人有用:)下面的概括:)我想你可能对基准感兴趣。对于以倍频程执行的1000次迭代,循环版本需要20分钟,我的版本使用repmat需要1.66s,不使用repmat需要0.92s,Suever的版本需要0.77s.)@太棒了!非常有用!
tic;
for i = 1:10000
    W = createWeights(w1,w2,w3);
    B = reshape(A, size(A,1), [])*W(:);
end
toc
Elapsed time is 0.920821 seconds.
tic; 
for i = 1:10000
    B2 = weightReduce(A, w1, w2, w3); 
end
toc
Elapsed time is 0.484470 seconds.