26

AxBxCマトリックスXBxDマトリックスがあるとしYます。

C AxB行列のそれぞれを で乗算できるループ以外の方法はありYますか?

4

10 に答える 10

17

個人的な好みとして、コードはできるだけ簡潔で読みやすいものにしたいと思っています。

「ループなし」の要件を満たしていませんが、これは私がやったことです:

for m = 1:C

    Z(:,:,m) = X(:,:,m)*Y;

end

これにより、A x D x C行列Zが得られます。

もちろん、Z を事前に割り当てて、 を使用して高速化することもできますZ = zeros(A,D,C);

于 2009-11-17T05:28:46.653 に答える
15

関数NUM2CELLを使用して行列Xをセル配列に分割し、 CELLFUNを使用してセル全体で操作することにより、これを 1 行で実行できます。

Z = cellfun(@(x) x*Y,num2cell(X,[1 2]),'UniformOutput',false);

結果Zは、各セルにA 行 D 列の行列が含まれる1 行 C 列のcell 配列になります。A x D x C行列にしたい場合は、CAT関数使用できます。Z

Z = cat(3,Z{:});



注:私の古いソリューションでは、簡潔ではなかった NUM2CELL の代わりに MAT2CELL を使用ていました。

[A,B,C] = size(X);
Z = cellfun(@(x) x*Y,mat2cell(X,A,B,ones(1,C)),'UniformOutput',false);
于 2009-11-17T03:34:59.457 に答える
8

これは1行のソリューションです(3次元に分割する場合は2行):

A = 2;
B = 3;
C = 4;
D = 5;

X = rand(A,B,C);
Y = rand(B,D);

%# calculate result in one big matrix
Z = reshape(reshape(permute(X, [2 1 3]), [A B*C]), [B A*C])' * Y;

%'# split into third dimension
Z = permute(reshape(Z',[D A C]),[2 1 3]);

したがって今:Z(:,:,i)の結果を含むX(:,:,i) * Y


説明:

上記はわかりにくいかもしれませんが、考え方は単純です。まず、 の 3 番目の次元を取り、最初の次元にX沿って垂直方向に連結することから始めます。

XX = cat(1, X(:,:,1), X(:,:,2), ..., X(:,:,C))

...難点は変数であるため、 catまたはvertcatCを使用してその式を一般化することはできません。次に、これに を掛けます。Y

ZZ = XX * Y;

最後に、それを 3 番目の次元に分割します。

Z(:,:,1) = ZZ(1:2, :);
Z(:,:,2) = ZZ(3:4, :);
Z(:,:,3) = ZZ(5:6, :);
Z(:,:,4) = ZZ(7:8, :);

したがって、行列の乗算が 1 回だけ必要であることがわかりますが、前後に行列を再形成する必要があります。

于 2009-11-16T23:35:10.897 に答える
1

いいえ。いくつかの方法がありますが、それは常に直接または間接のループで発生します。

私の好奇心を喜ばせるために、なぜとにかくそれが欲しいのですか?

于 2009-11-16T22:49:36.597 に答える
1

質問に答えて読みやすくするには、次を参照してください。

  • ndmult、ajuanpi (Juan Pablo Carbajal) 著、2013 年、GNU GPL

入力

  • 2 配列
  • 薄暗い

 nT = 100;
 t = 2*pi*linspace (0,1,nT)’;

 # 2 experiments measuring 3 signals at nT timestamps
 signals = zeros(nT,3,2);
 signals(:,:,1) = [sin(2*t) cos(2*t) sin(4*t).^2];
 signals(:,:,2) = [sin(2*t+pi/4) cos(2*t+pi/4) sin(4*t+pi/6).^2];

 sT(:,:,1) = signals(:,:,1)’;
 sT(:,:,2) = signals(:,:,2)’;
   G = ndmult (signals,sT,[1 2]);

ソース

元のソース。インラインコメントを追加しました。

function M = ndmult (A,B,dim)
  dA = dim(1);
  dB = dim(2);

  # reshape A into 2d
  sA = size (A);
  nA = length (sA);
  perA = [1:(dA-1) (dA+1):(nA-1) nA dA](1:nA);
  Ap = permute (A, perA);
  Ap = reshape (Ap, prod (sA(perA(1:end-1))), sA(perA(end)));

  # reshape B into 2d
  sB = size (B);
  nB = length (sB);
  perB = [dB 1:(dB-1) (dB+1):(nB-1) nB](1:nB);
  Bp = permute (B, perB);
  Bp = reshape (Bp, sB(perB(1)), prod (sB(perB(2:end))));

  # multiply
  M = Ap * Bp;

  # reshape back to original format
  s = [sA(perA(1:end-1)) sB(perB(2:end))];
  M = squeeze (reshape (M, s));
endfunction
于 2014-01-08T23:45:30.513 に答える
0

ループを「展開」できます。つまり、ループで発生するすべての乗算を順番に書き出すことができます。

于 2009-11-16T22:42:24.137 に答える
0

私は再帰だと思いますが、それはあなたができる他の唯一のループ以外の方法です

于 2009-11-16T22:39:13.420 に答える