【问题标题】:Replace each element in a matrix with a diagonal matrix用对角矩阵替换矩阵中的每个元素
【发布时间】:2015-03-20 22:15:21
【问题描述】:

假设我有一个维度为 NxV 的矩阵 A。我想创建一个更大的 NTxVT 矩阵,即我想用 diag(T)*A(e) 替换矩阵 A(e) 的每个元素 e,同时保持矩阵的大致方向(例如, A(e) 在 A(e-1) 的左边,所以 diag(T)*A(e) 在 diag(T)*A(e-1) 的左边。

在matlab中有什么技巧可以做到这一点吗? (制作每个对角矩阵并将它们连接起来需要很长时间)。

非常感谢^^

【问题讨论】:

标签: matlab matrix vectorization


【解决方案1】:
A = magic(3);
T = diag([-1 1]);
kron(A,T)

给予

-8     0    -1     0    -6     0
 0     8     0     1     0     6
-3     0    -5     0    -7     0
 0     3     0     5     0     7
-4     0    -9     0    -2     0
 0     4     0     9     0     2

ps。我从this example复制了这个想法

【讨论】:

  • 这是要走的路!简洁快速。
【解决方案2】:

这是使用bsxfun的解决方案

A = magic(3);
T = [-1 1]
T = diag(T);
M=bsxfun(@times,permute(A,[3,1,4,2]),permute(T,[1,3,2,4]));
M=reshape(M,size(T).*size(A));

它创建一个 4D 矩阵,其中各个块为 M(:,i,:,j),然后将其重新整形为 2D 矩阵。

图像处理工具箱提供了另一种很短但很慢的解决方案:

A = magic(3);
T = [-1 1]
T = diag(T);
M=blockproc(A,[1 1],@(x) x.data.*T);

最后是一个生成稀疏矩阵的实现,这可能对大 T 有帮助,因为您的矩阵将包含许多零:

T=[-1 1];
A=magic(3);
%p and q hold the positions where the first element element is stored. Check sparse(p(:),q(:),A(:)) to understand this intermediate step
[p,q]=ndgrid(1:numel(T):numel(T)*size(A,1),1:numel(T):numel(T)*size(A,2));
%now p and q are extended to hold the indices for all elements
tP=bsxfun(@plus,p(:),0:numel(T)-1);
tQ=bsxfun(@plus,q(:),0:numel(T)-1);
%
tA=bsxfun(@times,A(:),T);
M=sparse(tP,tQ,tA);

当 T 的大小为 nx1 时,稀疏解决方案会将您的内存使用量减少大约 n/1.55​​ 倍。

【讨论】:

  • 我认为,permute(A,[3,1,4,2]).*permute(T,[1,3,2,4]) 看起来比其等效的 bsxfun 更清晰。
  • @LeonidBeschastny:八度用户? matlab不支持广播,这里需要bsxfun。
  • You got me ;) 我几年前切换到八度。你是对的,如果没有bsxfun,它将无法在 MatLab 中工作。
【解决方案3】:

我能想到的最简单的方法是结合arrayfuncell2mat函数:

B = cell2mat(arrayfun((@(x) T .* x), A, 'UniformOutput', false));

首先,我将矩阵A 转换为矩阵T .* x 的元胞数组,其中xA 的一个元素(假设T 是一个矩阵)。

然后我使用cell2mat 转换回矩阵。

这是一个完整的例子 (execute online):

A = magic(3);
T = diag([-1 1]);
B = cell2mat(arrayfun((@(x) T .* x), A, 'UniformOutput', false));

导致:

B =

  -8   0  -1   0  -6   0
   0   8   0   1   0   6
  -3   0  -5   0  -7   0
   0   3   0   5   0   7
  -4   0  -9   0  -2   0
   0   4   0   9   0   2

【讨论】:

    【解决方案4】:

    仅使用索引:

    A = magic(3); 
    T = diag([-1 1]); %// example data from Daniel's answer
    [a1, a2] = size(A);
    [t1, t2] = size(T);
    M = A(ceil(1/t1:1/t1:a1), ceil(1/t2:1/t2:a2)).*T(repmat(1:t1,1,a1), repmat(1:t2,1,a2));
    

    【讨论】:

      【解决方案5】:

      使用good old-fashioned matrix multiplication -

      M = reshape(diag(T)*A(:).',[size(A,1)*size(T,1) size(A,2)])
      

      示例运行 -

      A = magic(4)
      T = magic(3)
      M = reshape(diag(T)*A(:).',[size(A,1)*size(T,1) size(A,2)])
      

      将导致 -

      A =
          16     2     3    13
           5    11    10     8
           9     7     6    12
           4    14    15     1
      T =  %// Notice that only diag(T) elements would be used to calculate M 
           8     1     6
           3     5     7
           4     9     2
      M =
         128    16    24   104
          80    10    15    65
          32     4     6    26
          40    88    80    64
          25    55    50    40
          10    22    20    16
          72    56    48    96
          45    35    30    60
          18    14    12    24
          32   112   120     8
          20    70    75     5
           8    28    30     2
      

      【讨论】:

        猜你喜欢
        • 2017-05-09
        • 2016-11-13
        • 1970-01-01
        • 2018-02-15
        • 2017-02-10
        • 1970-01-01
        • 2013-03-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多