0

私は行列を持っており、ある点から他のすべての点までの距離aを計算したいと考えています。したがって、実際には、結果マトリックスは (選択したポイントで) ゼロを持ち、その特定のポイントの周りにある種の数字の円として表示されるはずです。

これは私がすでに持っているものですが、正しい結果が得られないようです。

a = [1 2 3 4 5 6 7 8 9 10]

for i = 2:20
    a(i,:) = a(i-1,:) + 1;
end

N = 10

for I = 1:N
    for J = 1:N
        dx = a(I,1)-a(J,1);
        dy = a(I,2)-a(J,2);
        distance(I,J) = sqrt(dx^2 + dy^2)
    end
end
4

3 に答える 3

12

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 )

u2 つのデータ配列と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) squareform2 倍の時間がかかるのは、距離行列が対称であるため、三角行列しか計算しないpdistためと考えられます。pdist正方行列なしで実行できる場合は、 (0.5609/1.3348)squareformを使用して手動で計算するのに必要な時間の約 40% で計算を回避して実行できます。bsxfun

于 2013-10-18T18:17:58.393 に答える
-2

これは私が探していたものですが、すべての提案に感謝します。

A = rand(5, 5);
select_cell = [3 3];
distance = zeros(size(A, 1), size(A, 2));
for i = 1:size(A, 1)
    for j = 1:size(A, 2)
        distance(i, j) = sqrt((i - select_cell(1))^2 + (j - select_cell(2))^2);
    end
end
disp(distance)

また、ベクトル化を使用して改善することもできます。

distances = sqrt((x-xCenter).^2+(y-yCenter).^2
于 2013-10-28T15:14:27.777 に答える
-3

重要: data_matrix は DXN です。D は次元数、N はデータ ポイントの数です。

final_dist_pairs=data_matrix'*data_matrix;

ノルム = diag(final_dist_pairs);

final_dist_pairs = bsxfun(@plus, ノルム, ノルム') - 2 * final_dist_pairs; それが役に立てば幸い!

% もう一つ重要なことは、 MATLAB の pdist 関数を絶対に使わないことです。これは for ループのような順次評価であり、おそらく O(N^2) で多くの時間がかかります

于 2013-10-18T18:14:17.617 に答える