假设我有:
A = rand(1,10,3);
B = rand(10,16);
我想得到:
C(:,1) = A(:,:,1)*B;
C(:,2) = A(:,:,2)*B;
C(:,3) = A(:,:,3)*B;
我能以某种方式将它乘以一行以便它更快吗?
如果我像这样创建新的张量b
,该怎么办?for i = 1:3
b(:,:,i) = B;
end
我可以将A和B相乘得到相同的C但速度更快吗?通过上面的循环创建b所花费的时间并不重要,因为我将需要C用于许多不同的A-s而B保持不变。
答案 0 :(得分:7)
置换A
和B
的尺寸,然后应用矩阵乘法:
C = B.'*permute(A, [2 3 1]);
答案 1 :(得分:5)
如果A
是 true 3D数组,如A = rand(4,10,3)
并假设B
保持为2D数组,那么每个A(:,:,1)*B
会产生一个2D数组。
因此,假设您希望将这些2D数组作为切片存储在输出数组的第三维中,C
就像这样 -
C(:,:,1) = A(:,:,1)*B;
C(:,:,2) = A(:,:,2)*B;
C(:,:,3) = A(:,:,3)*B; and so on.
为了以矢量化的方式解决这个问题,其中一种方法是将整形A
用于合并第一维和第三维的二维数组,然后执行矩阵多重复制。最后,为了使输出大小与前面列出的C
相同,我们需要重新整形的最后一步。
实现看起来像这样 -
%// Get size and then the final output C
[m,n,r] = size(A);
out = permute(reshape(reshape(permute(A,[1 3 2]),[],n)*B,m,r,[]),[1 3 2]);
示例运行 -
>> A = rand(4,10,3);
B = rand(10,16);
C(:,:,1) = A(:,:,1)*B;
C(:,:,2) = A(:,:,2)*B;
C(:,:,3) = A(:,:,3)*B;
>> [m,n,r] = size(A);
out = permute(reshape(reshape(permute(A,[1 3 2]),[],n)*B,m,r,[]),[1 3 2]);
>> all(C(:)==out(:)) %// Verify results
ans =
1
根据comments
,如果A
是一个在开始时始终为单个维度的3D数组,则可以使用squeeze
然后使用矩阵乘法 -
C = B.'*squeeze(A)
答案 2 :(得分:1)
编辑: @LuisMendo指出这确实可能适用于此特定用例。但是,如果A的第一个维度不是1,则(通常)不可能。
我已经解决了一段时间了,我从来没有能够提出解决方案。 bsxfun
使得逐个元素的计算变得很好,但是张量乘法是一个非常不受支持的东西。对不起,祝你好运!
你可以查看this mathworks file exchange file,这将使你更容易并支持你正在寻找的行为,但我相信它也依赖于循环。 编辑:它依赖于MEX / C ++,因此如果您正在寻找它,那么它不是纯粹的MATLAB解决方案。
答案 3 :(得分:0)
我必须同意@GJSein,for循环非常快
time
0.7050 0.3145
这里是计时器功能
function time
n = 1E7;
A = rand(1,n,3);
B = rand(n,16);
t = [];
C = {};
tic
C{length(C)+1} = squeeze(cell2mat(cellfun(@(x) x*B,num2cell(A,[1 2]),'UniformOutput',false)));
t(length(t)+1) = toc;
tic
for i = 1:size(A,3)
C{length(C)+1}(:,i) = A(:,:,i)*B;
end
t(length(t)+1) = toc;
disp(t)
end