2016-04-30 15 views
2

現在、bunchofpagesというMATLABのペアワイズ距離を効率的に計算する方法がいくつかあります。私は少し違うことをやろうとしています。効率的なMATLABの要素間の差

ではなく二つの行列の行の対の間の全体の距離を計算し、XYを言う:

X = [1 1 1; 2 2 2]; 
Y = [1 2 3; 4 5 6]; 

Iは3次元マトリックスを計算する、の各対の間生列方向差を記憶します行。上記の例では、このマトリックスは、(Y 2回の観測のために)3次元で(X 2つの観測用)二列、3列、2つのスライスを有するであろう:

diffs(:,:,1) = 

    0 -1 -2 
    1  0 -1 


diffs(:,:,2) = 

    -3 -4 -5 
    -2 -3 -4 

私は今まで一般的なケースとしてこれを達成する2つの方法を考案しますが、私はエレガントで透明で効率的なものを探したいと思います。

Repmat + PERMUTEアプローチ

% Set up data 
X = rand(100,10); 
Y = rand(200,10); 

timer = tic; 
X_tiled = repmat(X,[1 1 size(Y,1)]); 
Y_tiled = repmat(permute(Y,[3,2,1]),[size(X,1),1,1]); 
diffs = X_tiled - Y_tiled; 
toc(timer) 
% Elapsed time is 0.001883 seconds. 

forループのアプローチ

timer = tic; 
diffs = zeros(size(X,1),size(X,2),size(Y,1)); 
for i = 1:size(X,1) 
    for j =1:size(Y,1) 
     diffs(i,:,j) = X(i,:) - Y(j,:); 
    end 
end 
toc(timer) 
% Elapsed time is 0.028620 seconds. 

誰が私が持っているものよりも良いものを持っていますか?

答えて

3

あなたはXの第2次元と一致するその場所に二次元を維持する第三の位置に最初の次元を送信するためにYpermuteを使用した後under-the-hood broadcastingのためにその厄介なrepmatを置き換えるためにbsxfunを使用することができます。これはpermute(Y,[3 2 1]で実現できます。したがって、解決策は次のようになります -

diffs = bsxfun(@minus,X,permute(Y,[3 2 1])) 

ベンチマーク

ベンチマークコード -

% Set up data 
X = rand(100,10); 
Y = rand(200,10); 

% Setup number of iterations 
num_iter = 500; 

%// Warm up tic/toc. 
for iter = 1:50000 
    tic(); elapsed = toc(); 
end 

disp('---------------- With messy REPMAT') 
timer = tic; 
for itr = 1:num_iter 
    X_tiled = repmat(X,[1 1 size(Y,1)]); 
    Y_tiled = repmat(permute(Y,[3,2,1]),[size(X,1),1,1]); 
    diffs = X_tiled - Y_tiled; 
end 
toc(timer) 

disp('---------------- With sassy BSXFUN') 
timer = tic; 
for itr = 1:num_iter 
    diffs1 = bsxfun(@minus,X,permute(Y,[3 2 1])); 
end 
toc(timer) 

出力 -

---------------- With messy REPMAT 
Elapsed time is 3.347060 seconds. 
---------------- With sassy BSXFUN 
Elapsed time is 0.966760 seconds. 
+0

私はそれが好き!ありがとう –

関連する問題