4

私の問題に非常に簡単な解決策があることを願っています。私はそれを見つけることができません:

2 つのベクトル (1 つは列ベクトル、もう 1 つは行ベクトル) A、B があるとします。

A = [1,2,3]
B = [4;5;6]

次のように乗算すると、行列が得られます。

>> B*A
ans =
 4     8    12
 5    10    15
 6    12    18

今私の問題は次のとおりです。サイズの2つの3Dマトリックスがm × n × pあり、m × n × q

次元mnに沿ってピクセルがあり、各ピクセルに対してベクトル (長さ p または q) があると想像してください。今私が欲しいのは、対応するピクセルごとに2つの画像のベクトルを乗算して、ピクセルごとにマトリックスを取得し、最終的に合計で4Dマトリックスを取得することです。

これを効率的に行うにはどうすればよいですか?

4

3 に答える 3

4

Matlabのループは、もはや恐れたり、回避したりするものではありません。

確かに、それらを使用するときは細心の注意を払う必要がありますが、それでも、JIT はさまざまな種類のループを処理し、組み込み関数を超えてパフォーマンスを向上させることができます。

次のテスト ケースを検討してください。

clc

m = 512;   n = 384;
p = 5;     q = 3;

A = rand(m,n,p); % some sample data
B = rand(m,n,q); % some sample data

%% non-loop approach

tic
A2 = reshape(A,[],p);
B2 = reshape(B,[],q);
C2 = arrayfun(@(ii) A2(ii,:)'*B2(ii,:),1:m*n,'uni',false);
C0 = permute(reshape(cell2mat(C2),p,q,m,n),[3 4 1 2]);
toc

%% looped approach, simplest

tic
C = zeros(m,n,p,q);
for mm = 1:m
    for nn = 1:n        
        C(mm,nn,:,:) = ...
            squeeze(A(mm,nn,:))*squeeze(B(mm,nn,:)).';
    end
end
toc

% check for equality
all(C0(:) == C(:))

%% looped approach, slightly optimized

tic
C = zeros(m,n,p,q);
pp = zeros(p,1);
qq = zeros(1,q);
for mm = 1:m
    for nn = 1:n
        pp(:) = A(mm,nn,:);
        qq(:) = B(mm,nn,:);
        C(mm,nn,:,:) = pp*qq;
    end
end
toc

% check for equality
all(C0(:) == C(:))

%% looped approach, optimized

tic
C  = zeros(p,q,m*n);
A2 = reshape(A,[],p);
B2 = reshape(B,[],q);
for mn = 1:m*n
    C(:,:,mn) = A2(mn,:).'*B2(mn,:);
end
C = permute(reshape(C, p,q,m,n), [3,4,1,2]);
toc

% check for equality
all(C0(:) == C(:))

結果:

Elapsed time is 3.955728 seconds.
Elapsed time is 21.013715 seconds.
ans =
     1
Elapsed time is 1.334897 seconds.
ans =
     1
Elapsed time is 0.573624 seconds.
ans =
     1

パフォーマンスに関係なく、最後のケースは非ループのケースよりもはるかに直感的で読みやすいと思います。

于 2012-07-28T05:46:17.937 に答える
3

いくつかのreshapingarrayfunおよびpermuteを使用:

m=5;
n=4;
p=3;
q=2;
A=randi(10,m,n,p); %some sample data
B=randi(10,m,n,q); %some sample data

A2=reshape(A,[],p);
B2=reshape(B,[],q);
C2=arrayfun(@(ii) A2(ii,:)'*B2(ii,:),1:m*n,'uni',false);

C=permute(reshape(cell2mat(C2),p,q,m,n),[3 4 1 2]);

壊す:

  • 最初の 2 つの reshape は、A 行列と Bmxnx(p or q)行列を(m*n)x(p or q)フォーマットに変更します
  • arrayfun がそれらを簡単にループして、行のベクトル積を計算できるようにします。
  • 次に、cell2mat、reshape、および permute により、結果をmxnxpxqフォーマットに戻します
于 2012-07-27T16:29:22.520 に答える
0

私はrody_oのソリューションを使用し、それを変更して、形状変更と順列を取り除きました。

C  = zeros(m*n, p, q);
A2 = reshape(A,[],p);
B2 = reshape(B,[],q);
for mn = 1:m*n
    C(mn,:,:) = A2(mn,:).' * B2(mn,:);
end
于 2012-07-30T07:37:58.077 に答える