【问题标题】:Extend a 2D-matrix to a 3D-matrix by multiplying with a vector [duplicate]通过与向量相乘将 2D 矩阵扩展到 3D 矩阵 [重复]
【发布时间】:2016-06-03 22:50:04
【问题描述】:

这是我想要实现的目标:

我有一个矩阵 C

C=[1 2 3; 4 5 6; 7 8 9];

还有一个向量a

a=[1 2];

我想做这样一个操作,将a向量的每个元素与C(标量乘法)相乘,得到一个3维数组D

(:,:,1) =

     1     2     3
     4     5     6
     7     8     9


(:,:,2) =

     2     4     6
     8    10    12
    14    16    18

它当然可以使用循环,但是,由于我需要多次执行此操作,所以 oneliner 将是一个很好的保护程序。

【问题讨论】:

    标签: arrays matlab matrix multidimensional-array


    【解决方案1】:

    我有另一种基准比较方法... IMO 这是最简洁的方式,至少对于语法/可读性术语而言:

    out = reshape(kron(a,C),[size(C),numel(a)]);
    
    out(:,:,1) =
    
         1     2     3
         4     5     6
         7     8     9
    
    
    out(:,:,2) =
    
         2     4     6
         8    10    12
        14    16    18
    

    【讨论】:

    • 我喜欢它,但kron 和可读性......只有当你有一些整洁的数学背景我会说!
    • 或者对该有用功能的一些经验... :)
    【解决方案2】:

    编辑(基准测试):由于已经提出了几种解决方案(包括下面我的),这里有一些粗略的基准测试来比较不同的解决方案,使用更大的数组:

    a=1:10;
    N=1000; timers=zeros(N,6);
    for ii=1:N; C=rand(400);
      tic; out = repmat(C,[1,1,numel(a)]).*reshape(repelem(a,size(C,1),size(C,2)),[size(C),numel(a)]); timers(ii,1)=toc;
      tic; out = bsxfun(@times,C,reshape(a,1,1,[])); timers(ii,2)=toc;
      tic; out = reshape(C(:)*a, size(C,1), size(C,2), numel(a)); timers(ii,3)=toc;
      tic; out = bsxfun(@mtimes,C,permute(a,[3,1,2])); timers(ii,4)=toc;
      tic; out = reshape(bsxfun(@mtimes, C(:), a(:).'), [size(C),numel(a)] ); timers(ii,5)=toc; 
      tic; out = reshape(kron(a,C),[size(C),numel(a)]); timers(ii,6)=toc;
    end;
    
    mean(timers)
    
    ans =
    
        0.0080863    0.0032406    0.0041718     0.015166    0.0074462    0.0033051
    

    ... 建议 @hbaderts 解决方案最快,然后是 @Adiel 的,然后是 @Luis Mendo 的,然后是 @thewaywewalk 的 (1),然后是我的,然后是 @thewaywewalk 的 (2)。

    我的解决方案:

    另一个选项,使用repmatreshape(没有bsxfun):

    out = repmat(C,[1,1,numel(a)]).*reshape(repelem(a,size(C,1),size(C,2)),[size(C),numel(a)])
    
    out(:,:,1) =
    
     1     2     3
     4     5     6
     7     8     9
    
    out(:,:,2) =
    
     2     4     6
     8    10    12
    14    16    18
    

    这是两个数组的元素乘法。第一个是您的原始矩阵 C 在第三维重复 numel(a) 次:

    repmat(C,[1,1,numel(a)])
    
    ans(:,:,1) =
    
     1     2     3
     4     5     6
     7     8     9
    
    ans(:,:,2) =
    
     1     2     3
     4     5     6
     7     8     9
    

    第二个和第一个大小一样,每个切片都包含a的对应元素:

    reshape(repelem(a,size(C,1),size(C,2)),[size(C),numel(a)])
    
    ans(:,:,1) =
    
     1     1     1
     1     1     1
     1     1     1
    
    ans(:,:,2) =
    
     2     2     2
     2     2     2
     2     2     2
    

    【讨论】:

      【解决方案3】:

      另一种可能性是使用matrix multiplicationC 作为列向量乘以a 作为行向量(这给出了所有元素的产品),然后reshape 结果:

      out = reshape(C(:)*a, size(C,1), size(C,2), numel(a));
      

      【讨论】:

        【解决方案4】:

        一些reshape'ing 和一些bsxfun 可以:

        out = reshape(bsxfun(@mtimes, C(:), a(:).'), [size(C),numel(a)] )
        

        正如hbaderts answer 所建议的,也可以使用bsxfun 的维度扩展能力,并提供一个置换的因子向量:

        out = bsxfun(@mtimes,C,permute(a,[3,1,2]))
        

        out(:,:,1) =
        
             1     2     3
             4     5     6
             7     8     9
        
        
        out(:,:,2) =
        
             2     4     6
             8    10    12
            14    16    18
        

        【讨论】:

          【解决方案5】:

          这是使用bsxfunreshape 的一个很好的例子。虽然@thewaywewalks 建议首先调用bsxfun 并重塑结果,但我建议相反。这使得bsxfun 的关键概念之一——单例维度扩展——更加清晰:

          out = bsxfun(@times,C,reshape(a,1,1,[]))
          
          ans(:,:,1) =
          
               1     2     3
               4     5     6
               7     8     9
          
          
          ans(:,:,2) =
          
               2     4     6
               8    10    12
              14    16    18
          

          使用reshape(a,1,1,[]),您可以使a 处于第三维。如果现在应用bsxfun,它会将矩阵Ca 的每个元素相乘。

          【讨论】:

          • 在这里permute 会不会比reshape 更合适?
          猜你喜欢
          • 1970-01-01
          • 2016-12-11
          • 2021-05-25
          • 1970-01-01
          • 1970-01-01
          • 2015-01-24
          • 2018-07-09
          • 1970-01-01
          相关资源
          最近更新 更多