MATLAB:有两种方法可以让两个重塑相互取消,两个相互置换

时间:2016-08-26 00:23:52

标签: matlab matrix

我有一个3乘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)'是矩阵的复共轭转置而没有第二列。

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])是使重塑成行的技巧。

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

第三,重塑和.'使其成为一个列:

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乘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)巧合是对称的。

2 个答案:

答案 0 :(得分:2)

你问哪个部分最耗时,所以我将讨论如何找到它:

我们做的第一件事就是重新安排你的" 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]));

然后,我们运行探查器并获取:

Profiler output

因此:索引c花费的时间最多(尽管由于总体运行时间较低,很难准确地说出百分比,但不是订单的百分比差别很大)。

答案 1 :(得分:1)

直接回答您的问题:

  • 连续两次reshape次操作不一定"取消" out,be可以替换为最外层的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 从不是必需的。你编写它的方式首先重塑为行向量然后采用转置(技术上是另一个 reshape)使其成为列向量,然后重塑为3 x N.只需跳过前两步,直接进入3 x N.

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

    话虽如此,如果您真正密切关注此您的原始数据已经是这种形状,那么您就不需要任何重塑。如果你真的需要复共轭(因为你显然不需要转置部分),你可以使用conj来获得它。

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

    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]));
    

    尽管如此,为什么这需要被困在一条线上?这真的让它变得非常难以辨认,并且可能会让你在看完这段代码后感到困惑。将它分成多行会更好,这样逻辑就更容易理解了。