【问题标题】:MATLAB: Is there any way for two reshape to cancel each other and two permute to each otherMATLAB:有没有办法让两个重塑相互抵消,两个相互置换
【发布时间】:2016-08-26 00:23:51
【问题描述】:

我有一个 3 x 3 复数矩阵 c,因此我必须执行以下操作。 c 一般是复杂的,c 也可以更大,但它是一个方阵。

   c= rand(3,3)   
    A = bsxfun(@mtimes,permute(reshape(reshape(permute(c(:,1:end~=2)',[2 1]),1,3*2).', 3, []),[3,1,2]),c(:,1))
    conj(permute(A,[2 1 3]))

但是,时间太长了。哪个部分最耗时?

首先,c(:,1:end~=2)' 是没有第 2 列的矩阵的复共轭转置。

c = rand(3,3)
c =
    0.9791    0.2003    0.9764
    0.5933    0.2570    0.4920
    0.5811    0.6384    0.9031

c(:,1:end~=2)'
ans =
    0.9791    0.5933    0.5811
    0.9764    0.4920    0.9031

其次,permute(c(:,1:end~=2)',[2 1]) 是一个让 reshape 按行工作的技巧。

permute(c(:,1:end~=2)',[2 1])
ans =
    0.9791    0.9764
    0.5933    0.4920
    0.5811    0.9031

第三,做 reshape 和 .' 使其成为一个列:

reshape(permute(c(:,1:end~=2)',[2 1]),1,3*2).'
ans =
    0.9791
    0.5933
    0.5811
    0.9764
    0.4920
    0.9031

第四,将列重塑为 2 x 3 矩阵:

reshape(reshape(permute(c(:,1:end~=2)',[2 1]),1,3*2).', 3, [])
ans =
    0.9791    0.9764
    0.5933    0.4920
    0.5811    0.9031

第五,创建一个多维数组,每一层都是列的行向量(只是重新排序,不采取复杂的共轭)。

permute(reshape(reshape(permute(c(:,1:end~=2)',[2 1]),1,3*2).', 3, []),[3,1,2])
ans(:,:,1) =
    0.9791    0.5933    0.5811
ans(:,:,2) =
    0.9764    0.4920    0.9031

六、用bsxfun得到c第一列与每一层的外积

bsxfun(@mtimes,permute(reshape(reshape(permute(c(:,1:end~=2)',[2 1]),1,3*2).', 3, []),[3,1,2]),c(:,1))
ans(:,:,1) =
    0.9587    0.5809    0.5689
    0.5809    0.3520    0.3448
    0.5689    0.3448    0.3376
ans(:,:,2) =
    0.9560    0.4817    0.8843
    0.5793    0.2919    0.5359
    0.5673    0.2859    0.5248

最后一个我认为不能简化。其目的是在每一层取矩阵的复共轭:

A = bsxfun(@mtimes,permute(reshape(reshape(permute(c(:,1:end~=2)',[2 1]),1,3*2).', 3, []),[3,1,2]),c(:,1))
A(:,:,1) =
    0.9587    0.5809    0.5689
    0.5809    0.3520    0.3448
    0.5689    0.3448    0.3376
A(:,:,2) =
    0.9560    0.4817    0.8843
    0.5793    0.2919    0.5359
    0.5673    0.2859    0.5248

conj(permute(A,[2 1 3]))
ans(:,:,1) =
    0.9587    0.5809    0.5689
    0.5809    0.3520    0.3448
    0.5689    0.3448    0.3376
ans(:,:,2) =
    0.9560    0.5793    0.5673
    0.4817    0.2919    0.2859
    0.8843    0.5359    0.5248

A(:,:,1) 是巧合对称的。

【问题讨论】:

  • 代码中花费最多时间的是打印到命令窗口,因为您的语句没有以; 终止。 (我不是在开玩笑)

标签: matlab matrix


【解决方案1】:

您问哪个部分最耗时,所以我将讨论如何找出答案:

我们要做的第一件事是将您的“1-liner”代码重新排列为单个操作,如下所示(请注意,我分别明确输入 transposectranspose 而不是 .''):

function q39156646
c = rand(3)+1i*rand(3); % Changed this slightly to represent the problem better.
A = bsxfun(@mtimes,...
      permute(...
        reshape(...
          transpose(...
            reshape(...
              permute(...
                ctranspose(...
                  c(:,1:end~=2)...
                  ),...
                [2 1]),...
              1,3*2)...
            ),...
          3, []),...
        [3,1,2]),...
      c(:,1));
conj(permute(A,[2 1 3]));

然后,我们运行分析器并得到:

因此:索引c 花费的时间最多(尽管由于总体运行时间较低,很难准确地说出多少百分比,而不是顺序,变化很大)。

【讨论】:

    【解决方案2】:

    直接回答您的问题:

    • 两个连续的reshape 操作不一定“取消”,可以只替换为最外层的reshape(请参阅下面的更多信息)。

    • permute 操作而言,您只需要确定您是否真的需要它们(更多信息见下文)。


    详细回复:

    您有大量多余和不必要的步骤。在这里,我概述了一些并提出了一个替代解决方案,无疑会更快。附带说明一下,单步调试代码并确保在将一堆不同的东西粘贴在一起而不真正了解它们各自的作用之前了解所有部分是非常有益的。

    1. 您不需要使用逻辑比较1:end~=2,只需指定除2之外的所有索引

      without_column_2 = c(:,[1 3:end])
      
    2. permute(a', [2 1]) 完全没有必要,因为您正在对某些东西进行复共轭转置(使用'),然后立即再次进行转置(这次使用permute),这会产生原始矩阵。只需将其替换为 a 即可。在你的情况下,这只是conj(c(:,[1 3:end]))

    3. 连续两个reshapes从不必要的。您编写它的方式首先重塑为行向量,然后采用转置(技术上是 another reshape)使其成为列向量,然后重塑为 3 x N。只需跳过前两步,直奔3 x N。

      reshape(c(:,[1 3:end]), 3, []);
      

      话虽如此,如果您真的仔细观察这个您的原始数据已经是这个形状,那么您就不需要任何重塑。如果您确实需要复共轭(因为您显然不需要转置部分),您可以使用conj 来获得它。

    对于那些保持得分的人,这意味着我们现在已经简化了:

    reshape(reshape(permute(c(:,1:end~=2)',[2 1]),1,3*2).', 3, [])
    

    conj(c(:,[1 3:end]))
    

    现在得到这个,以便c 的每一列都沿着您使用permute 的第二个维度;但这只是一个简单的reshape 操作

    reshape(conj(c(:,[1 3:end])), 1, size(c, 1), [])
    

    现在您必须使用c(:,1) 获取该外部产品并将结果共轭转置。

    这将简化为:

    out = conj(permute(bsxfun(@mtimes, reshape(conj(c(:,[1 3:end])), 1, size(c, 1), []), c(:,1)), [2 1 3]));
    

    尽管如此,为什么需要将其固定在一行上?它确实使它非常难以辨认,并且可能会使任何在您之后查看此代码的人感到困惑。你最好把它分成多行,这样逻辑更容易理解。

    【讨论】:

      猜你喜欢
      • 2019-09-30
      • 2019-02-01
      • 2015-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-24
      • 2023-03-08
      相关资源
      最近更新 更多