可能重复:
MATLAB: How to vector-multiply two arrays of matrices?
有没有办法在Matlab中签订高维张量?
例如,假设我有两个具有以下尺寸的三维数组:
size(A) == [M,N,P]
size(B) == [N,Q,P]
我想分别在第二个和第一个索引上签订A
和B
。换句话说,我想将A
视为大小为[M,N]
和B
的矩阵数组,为[N,Q]
矩阵的等长数组;我想逐个元素(逐个矩阵)乘以这些数组,得到大小为[M,Q,P]
的东西。
我可以通过for循环执行此操作:
assert(size(A,2) == size(B,1));
assert(size(A,3) == size(B,3));
M = size(A,1);
P = size(A,3);
Q = size(B,2);
C = zeros(M, Q, P);
for ii = 1:size(A,3)
C(:,:,ii) = A(:,:,ii) * B(:,:,ii);
end
有没有办法避免for循环? (也许可以使用任意数量维的数组?)
答案 0 :(得分:4)
这是一个解决方案(类似于所做的here),它在单个矩阵乘法运算中计算结果,尽管它涉及对矩阵的大量操作以使它们成为所需的形状。然后我将它与简单的for循环计算进行比较(我承认它更具可读性)
%# 3D matrices
A = rand(4,2,3);
B = rand(2,5,3);
[m n p] = size(A);
[n q p] = size(B);
%# single matrix-multiplication operation (computes more products than needed)
AA = reshape(permute(A,[2 1 3]), [n m*p])'; %'# cat(1,A(:,:,1),...,A(:,:,p))
BB = reshape(B, [n q*p]); %# cat(2,B(:,:,1),...,B(:,:,p))
CC = AA * BB;
[mp qp] = size(CC);
%# only keep "blocks" on the diagonal
yy = repmat(1:qp, [m 1]);
xx = bsxfun(@plus, repmat(1:m,[1 q])', 0:m:mp-1); %'
idx = sub2ind(size(CC), xx(:), yy(:));
CC = reshape(CC(idx), [m q p]);
%# compare against FOR-LOOP solution
C = zeros(m,q,p);
for i=1:p
C(:,:,i) = A(:,:,i) * B(:,:,i);
end
isequal(C,CC)
请注意,上述内容的执行次数比需要的多,但有时候"Anyone who adds, detracts (from execution time)"。遗憾的是情况并非如此,因为FOR循环在这里要快得多:)
我的观点是要表明矢量化并不容易,而基于循环的解决方案并不总是坏事......