三维向量的Matlab积
我希望我的问题有一个非常简单的解决方案。我就是找不到: 假设有两个向量(一个是列向量,一个是行向量)a,B: 如果我们将它们相乘,得到一个矩阵:三维向量的Matlab积,matlab,matrix,matrix-multiplication,Matlab,Matrix,Matrix Multiplication,我希望我的问题有一个非常简单的解决方案。我就是找不到: 假设有两个向量(一个是列向量,一个是行向量)a,B: 如果我们将它们相乘,得到一个矩阵: >> B*A ans = 4 8 12 5 10 15 6 12 18 现在我的问题是:我有两个大小为m×n×p和m×n×q 想象沿着维度m和n我们有像素,每个像素有一个向量(长度p或q)。 现在我想要的是,对每个对应的像素乘以两幅图像的向量,这样对于每个像素我得到一个矩阵,最终得到一个4D矩阵
>> B*A
ans =
4 8 12
5 10 15
6 12 18
现在我的问题是:我有两个大小为m×n×p
和m×n×q
想象沿着维度m和n我们有像素,每个像素有一个向量(长度p或q)。
现在我想要的是,对每个对应的像素乘以两幅图像的向量,这样对于每个像素我得到一个矩阵,最终得到一个4D矩阵
如何有效地做到这一点?使用一些,以及:
细分:
- 前两次重塑将A和B
矩阵更改为mxnx(p或q)
格式(m*n)x(p或q)
- 这样arrayfun就可以很容易地循环通过它们来计算行的向量积
- 然后cell2mat、重塑和置换将结果更改回
格式mxnxpxq
- Matlab中的循环不再是一件可怕的事情,也不再是一件可以避免的事情
当然,在使用它们时应该非常小心,但是,JIT可以处理多种循环,甚至可以在内置函数之外提高性能
考虑以下测试用例:
clc
m = 512; n = 384;
p = 5; q = 3;
A = rand(m,n,p); % some sample data
B = rand(m,n,q); % some sample data
%% non-loop approach
tic
A2 = reshape(A,[],p);
B2 = reshape(B,[],q);
C2 = arrayfun(@(ii) A2(ii,:)'*B2(ii,:),1:m*n,'uni',false);
C0 = permute(reshape(cell2mat(C2),p,q,m,n),[3 4 1 2]);
toc
%% looped approach, simplest
tic
C = zeros(m,n,p,q);
for mm = 1:m
for nn = 1:n
C(mm,nn,:,:) = ...
squeeze(A(mm,nn,:))*squeeze(B(mm,nn,:)).';
end
end
toc
% check for equality
all(C0(:) == C(:))
%% looped approach, slightly optimized
tic
C = zeros(m,n,p,q);
pp = zeros(p,1);
qq = zeros(1,q);
for mm = 1:m
for nn = 1:n
pp(:) = A(mm,nn,:);
qq(:) = B(mm,nn,:);
C(mm,nn,:,:) = pp*qq;
end
end
toc
% check for equality
all(C0(:) == C(:))
%% looped approach, optimized
tic
C = zeros(p,q,m*n);
A2 = reshape(A,[],p);
B2 = reshape(B,[],q);
for mn = 1:m*n
C(:,:,mn) = A2(mn,:).'*B2(mn,:);
end
C = permute(reshape(C, p,q,m,n), [3,4,1,2]);
toc
% check for equality
all(C0(:) == C(:))
结果:
Elapsed time is 3.955728 seconds.
Elapsed time is 21.013715 seconds.
ans =
1
Elapsed time is 1.334897 seconds.
ans =
1
Elapsed time is 0.573624 seconds.
ans =
1
不管性能如何,我还发现最后一种情况比非循环情况更直观和可读 我使用了rody_o的解决方案,并对其进行了修改,以消除重塑和置换:
C = zeros(m*n, p, q);
A2 = reshape(A,[],p);
B2 = reshape(B,[],q);
for mn = 1:m*n
C(mn,:,:) = A2(mn,:).' * B2(mn,:);
end
哇,这是一件很酷的事情。我不知道MATLAB能做这种事情。我会尝试一下,如果它真的能以这种方式工作并且速度更快,我会使用它;)@rody_o:+1为了进行全面的比较,加上我对JIT加速的看法非常一致,我仍然需要进行重塑,但我没有意识到,因为“all(C0(:)==C(:)”并没有检查这一点
Elapsed time is 3.955728 seconds.
Elapsed time is 21.013715 seconds.
ans =
1
Elapsed time is 1.334897 seconds.
ans =
1
Elapsed time is 0.573624 seconds.
ans =
1
C = zeros(m*n, p, q);
A2 = reshape(A,[],p);
B2 = reshape(B,[],q);
for mn = 1:m*n
C(mn,:,:) = A2(mn,:).' * B2(mn,:);
end