从两个二维矩阵中获取多个三维矩阵(逐列乘法)

Get many 3d matrices from two 2d matrices (column-wise multiplication)

有没有更快的方法可以不用循环执行下面的操作?

n = 2;
m = 1000;
A = rand(n,m);
B = rand(n,m);

C = zeros(n*n,m);
for i = 1 : m
    tmp = A(:,i) * B(:,i)';
    C(:,i) = tmp(:);
end

基本上我需要获得 m nxn 矩阵,在 AB 之间进行逐列矩阵乘法。然后我需要对这些矩阵进行矢量化。

您可以使用 repmat, kron and reshape 完全 向量化 或使用 Divakar 的 bsxfunpermuterepmat 解决方案在速度方面给你另一个显着的改进。

tic
for j = 1:1000
A1 = repmat(A, n, 1);
B1 = kron(B,ones(n,1));
D = reshape(A1(:).*B1(:), n*n, m);
end
toc

Elapsed time is 0.117396 seconds.

tic
for j = 1:1000
C = zeros(n*n,m);
for i = 1 : m
    tmp = A(:,i) * B(:,i)';
    C(:,i) = tmp(:);
end
end
toc

Elapsed time is 5.751179 seconds.

因此,加速大约是 50 倍。然而,正如下面评论中所讨论的,加速比通常取决于矩阵的大小和任务执行的次数。

您基本上是对 A 中的所有列对所有列执行逐元素乘法,但在 B 中进行转置。您可以使用 bsxfun(@times,..) 的一种矢量化方法,基本上 killing/replacing 那些 讨厌的循环 具有 bsxfun 的强大功能内部扩展能力。该实现还将涉及重塑以使其具有与 C 相同的格式,并且看起来像这样 -

out = reshape(bsxfun(@times,permute(A,[1 3 2]),permute(B,[3 1 2])),n^2,[]) 

运行时测试

本节比较了迄今为止列出的所有解决问题的方法。

基准代码-

%// Inputs
n = 2;
m = 1000;
A = rand(n,m);
B = rand(n,m);

num_iter = 5000;

disp('-------------------- For loop NO fuN') %// From OP question
tic
for iter = 1:num_iter
    C = zeros(n*n,m);
    for i = 1 : m
        tmp = A(:,i) * B(:,i)';
        C(:,i) = tmp(:);
    end
end
toc

disp('-------------------- run run KRON') %'// @lhcgeneva's solution
tic
for iter = 1:num_iter
    A1 = repmat(A, n, 1);
    B1 = kron(B,ones(n,1));
    D = reshape(A1(:).*B1(:), n*n, m);
end
toc

disp('-------------------- fun fun BSXFUN') %// Proposed in this post
tic
for iter = 1:num_iter
    out = reshape(bsxfun(@times,permute(A,[1 3 2]),permute(B,[3 1 2])),n^2,[]);
end
toc

输出-

-------------------- For loop NO fuN
Elapsed time is 28.101873 seconds.
-------------------- run run KRON
Elapsed time is 1.156337 seconds.
-------------------- fun fun BSXFUN
Elapsed time is 0.692433 seconds.