【问题标题】:Matlab product of vectors in third dimension三维向量的Matlab乘积
【发布时间】:2012-07-27 15:35:35
【问题描述】:

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

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

A = [1,2,3]
B = [4;5;6]

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

>> B*A
ans =
 4     8    12
 5    10    15
 6    12    18

现在我的问题是:我有两个大小为 m × n × pm × n × q 的 3D 矩阵

想象沿维度 mn 我们有像素,对于每个像素我们都有一个向量(长度 p 或 q)。 现在我想要的是,将 每个对应的像素 乘以两个图像的向量,这样对于每个像素,我得到一个 ma​​trix,因此总共有一个 4D 矩阵结束。

如何有效地做到这一点?

【问题讨论】:

    标签: matlab matrix matrix-multiplication


    【解决方案1】:

    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
    

    无论性能如何,我还发现最后一个案例比非循环案例更直观和可读。

    【讨论】:

    • 哇,这太酷了。我不知道 MATLAB 可以做这种事情。我会尝试一下,如果它确实以这种方式工作并且速度更快,我会使用它;)
    • @rody_o:+1 进行全面比较,另外我不能更同意 JIT 加速
    【解决方案2】:

    有一些reshapingarrayfunpermute

    m=5;
    n=4;
    p=3;
    q=2;
    A=randi(10,m,n,p); %some sample data
    B=randi(10,m,n,q); %some sample data
    
    A2=reshape(A,[],p);
    B2=reshape(B,[],q);
    C2=arrayfun(@(ii) A2(ii,:)'*B2(ii,:),1:m*n,'uni',false);
    
    C=permute(reshape(cell2mat(C2),p,q,m,n),[3 4 1 2]);
    

    细分:

    • 前两个 reshape 将 A 和 B mxnx(p or q) 矩阵更改为 (m*n)x(p or q) 格式
    • 这样 arrayfun 可以轻松地循环遍历它们以计算行的向量积
    • 然后cell2mat,reshape和permute将结果改回mxnxpxq格式

    【讨论】:

      【解决方案3】:

      我使用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
      

      【讨论】:

      • 哦,我仍然需要重塑,但我没有意识到,因为“all(C0(:) == C(:))”没有检查这个
      猜你喜欢
      • 2016-01-09
      • 2013-07-19
      • 1970-01-01
      • 2017-03-11
      • 2016-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-19
      相关资源
      最近更新 更多