a
マトリックスは 1D ベクトルであり、ネストされたループと互換性がありません。これは、各ポイントから他の各ポイントまでの 2D 空間での距離を計算します。N-by-D
したがって、次の答えは、ループが の場合に行うように、行列内のすべてのペアごとの距離を見つける問題に適用されますD=2
。
オプション 1 - pdist
距離オプションpdist
で探していると思います。'euclidean'
a = randn(10, 2); %// 2D, 10 samples
D = pdist(a,'euclidean'); %// euclidean distance
それに従って、squareform
必要に応じて対角線がゼロの正方行列を取得します。
distances = squareform(D);
オプション 2 - bsxfun
Statistics Toolbox にある がない場合はpdist
、次の方法で簡単に実行できますbsxfun
。
da = bsxfun(@minus,a,permute(a,[3 2 1]));
distances = squeeze(sqrt(sum(da.^2,2)));
オプション 3 - 再定式化された方程式
ユークリッド (2 ノルム) 距離の別の形式を使用することもできます。
||A-B|| = sqrt ( ||A||^2 + ||B||^2 - 2*A.B )
u
2 つのデータ配列とv
サイズ のMATLAB でこれを書くとNxD
、
dot(u-v,u-v,2) == dot(u,u,2) + dot(v,v,2) - 2*dot(u,v,2) % useful identity
%// there are actually small differences from floating point precision, but...
abs(dot(u-v,u-v,2) - (dot(u,u,2) + dot(v,v,2) - 2*dot(u,v,2))) < 1e-15
再定式化された方程式を使用すると、解は次のようになります。
aa = a*a';
a2 = sum(a.*a,2); % diag(aa)
a2 = bsxfun(@plus,a2,a2');
distances = sqrt(a2 - 2*aa);
オプション 2 が大量のメモリを消費する場合は、この方法を使用できます。
タイミング
サイズが 1e3 行 3 列 (N 行 D 列) のランダム データ行列の場合、100 回実行した場合のタイミングは次のとおりです (コア 2 クワッド、4GB DDR2、R2013a)。
- オプション 1 (
pdist
): 1.561150 秒 ( で 0.560947 秒pdist
)
- オプション 2 (
bsxfun
): 2.695059 秒
- オプション 3 (
bsxfun
代替): 1.334880 秒
調査結果: (i) で計算を行いbsxfun
、別の公式を使用します。(ii) pdist
+squareform
オプションのパフォーマンスは同等です。(iii) squareform
2 倍の時間がかかるのは、距離行列が対称であるため、三角行列しか計算しないpdist
ためと考えられます。pdist
正方行列なしで実行できる場合は、 (0.5609/1.3348)squareform
を使用して手動で計算するのに必要な時間の約 40% で計算を回避して実行できます。bsxfun