【问题标题】:Matlab: what is the best way to reshape a large matrix based on sub-matricesMatlab:基于子矩阵重塑大矩阵的最佳方法是什么
【发布时间】:2015-10-20 03:56:21
【问题描述】:

我有一个 250-by-200 的大矩阵。里面是 50-by-50 个更小的 5-by-4 矩阵。

重塑矩阵以使 2500 个 5-by-4 个较小的矩阵相互水平对齐的最佳方法是什么?所以大矩阵的结束维度应该是5-×-10000

【问题讨论】:

  • 当你说 50 时,你真的是指 50x50 = 2500 吗?
  • 是的,大矩阵填充了 50x50 较小的 5x4 矩阵。
  • 嗨,马特,我已经添加了一些说明,您是否了解问题所在?
  • 子矩阵在输出矩阵中的顺序应该是什么?从输入矩阵按列还是按行?
  • 逐行。所以第二行的第一个子矩阵移动到第一行末尾的子矩阵旁边。

标签: matlab matrix reshape


【解决方案1】:

Matlab 的reshape 函数非常方便(而且速度很快),但总是读取和写入完整 列。因此,对于您的问题,需要一些额外的步骤。

你可以这样做:

m = 5 % columns of submatrix
n = 4 % rows of submatrix
k = 50 % num submatrixes in matrix column
l = 50 % num submatrixes in matrix row
A = rand(m*k,n*l); % rand(250,200)

将矩阵重塑为一个四维矩阵(维度 x1,x2,x3,x4),其中每个子矩阵位于 x1-x3 平面内。原始矩阵的子矩阵列在 x2 方向,子矩阵行在 x4 方向。

B = reshape(A,[m,k,n,l]); % [4,50,5,50]

置换('转置') 4D 矩阵,使每个子矩阵位于 x1-x2 平面内。 (reshape首先读取列,然后是行,然后是第 3 维等)

C = permute(B,[1,3,4,2]); % For column-wise reshaping, use [1,3,2,4]

将 4D 矩阵重塑为所需的 2D 输出矩阵。

D = reshape(C,m,[]);

【讨论】:

  • reshapetransposed 之前可以按行使用。
  • 我的意思是它读取完整的列,这意味着你不能告诉它只读取一列的前 5 个条目,然后继续下一列。我会清除它。
【解决方案2】:

您可以使用mat2cell,然后使用reshape,最后使用cell2mat 获取矩阵。出于演示目的,我使用了变量nm。对于您的矩阵,它们都是 50。

正如您在评论中阐明的那样,以下代码按行执行:

n = 3;                          % rows
m = 2;                          % columns

A = reshape(1:20,[5,4]);        % generate some data
M = repmat(A,n,m);              % create the large matrix

X = mat2cell(M,repmat(5,1,n),repmat(4,1,m))
X = reshape(X.',1,[])
X = cell2mat(X)

注意: reshape 按列操作。因此我们需要在使用reshape之前将X.'transpose进行转置,如上面的代码所示。

【讨论】:

    【解决方案3】:

    我想添加另一种使用索引和一个内置函数zeros 的方法。也许这种方式不会有任何不必要的错误检查或重塑操作。事实证明它更有效(见下文)。

    %submatrix size
    m = 5;
    n = 4;
    %repeated submatrix rows and cols
    rep_rows = 50;
    rep_cols = 50;
    % big matrix
    A = rand(m * rep_rows, n * rep_cols);
    % create new matrix 
    C = zeros(m, (n * rep_cols) * rep_rows);
    for k = 1:rep_rows
       ind_cols = (n * rep_cols) * (k - 1) + 1: (n * rep_cols) * k;
       ind_rows = m * (k - 1) + 1: m * k;
       C(:, ind_cols) = A(ind_rows, :);
    end
    

    我决定在这里对三个答案进行计时,发现这种方法明显更快。下面是测试代码:

    % Bastian's approach
    m = 5; % columns of submatrix
    n = 4; % rows of submatrix
    k = 50; % num submatrixes in matrix column
    l = 50; % num submatrixes in matrix row
    A = rand(m*k,n*l); % rand(250,200)
    % start timing
    tic
    B = reshape(A,[m,k,n,l]); % [4,50,5,50]
    C = permute(B,[1,3,4,2]); % For column-wise reshaping, use [1,3,2,4]
    D = reshape(C,m,[]);
    toc
    % stop timing
    disp('                ^^^ Bastian');
    
    % Matt's approach
    n = 50;                          % rows
    m = 50;                          % columns
    % start timing
    tic
    X = mat2cell(A,repmat(5,1,n),repmat(4,1,m));
    X = reshape(X.',1,[]);
    X = cell2mat(X);
    toc
    % stop timing
    disp('                ^^^ Matt');
    
    % ChisholmKyle
    m = 5;
    n = 4;
    rep_rows = 50;
    rep_cols = 50;
    % start timing
    tic
    C = zeros(m, (n * rep_cols) * rep_rows);
    for k = 1:rep_rows
       ind_cols = (n * rep_cols) * (k - 1) + 1: (n * rep_cols) * k;
       ind_rows = m * (k - 1) + 1: m * k;
       C(:,ind_cols) = A(ind_rows, :);
    end
    toc
    % stop timing
    disp('                ^^^ this approach');
    

    这是我机器上的输出:

    Elapsed time is 0.004038 seconds.
                    ^^^ Bastian
    Elapsed time is 0.020217 seconds.
                    ^^^ Matt
    Elapsed time is 0.000604 seconds.
                    ^^^ this approach
    

    【讨论】:

    • 好一个!显然,这些年来循环确实变得更快了 =)
    • 我注意到我的方法在clear allclear functions 之后的第一次执行时要慢得多。否则,两种解决方案的速度大致相同。显然我的版本编译需要很多时间,但是编译后的脚本执行时间还是挺快的。
    • 喜欢 Matlab 的即时编译器!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-08
    • 1970-01-01
    • 2017-12-25
    相关资源
    最近更新 更多