三维向量的Matlab积

三维向量的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矩阵

我希望我的问题有一个非常简单的解决方案。我就是找不到:

假设有两个向量(一个是列向量,一个是行向量)a,B:

如果我们将它们相乘,得到一个矩阵:

>> B*A
ans =
 4     8    12
 5    10    15
 6    12    18
现在我的问题是:我有两个大小为
m×n×p
m×n×q

想象沿着维度mn我们有像素,每个像素有一个向量(长度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