web-dev-qa-db-ja.com

Nポイントとnumpy / scipyの参照間の効率的な距離計算

Scipy/numpyを使い始めました。 100000 * 3の配列があり、各行は座標で、1 * 3の中心点です。配列内の各行の中心までの距離を計算し、それらを別の配列に格納したいと思います。それを行う最も効率的な方法は何ですか?

20
D. Huang

scipy.spatial.distance.cdistを見てみましょう。

http://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.cdist.html

import numpy as np
import scipy

a = np.random.normal(size=(10,3))
b = np.random.normal(size=(1,3))

dist = scipy.spatial.distance.cdist(a,b) # pick the appropriate distance metric 

デフォルトの距離メトリックのdistは、以下と同等です。

np.sqrt(np.sum((a-b)**2,axis=1))  

cdistは大規模な配列の方がはるかに効率的ですが(私のマシンではサイズの問題のため、cdistは約35倍高速です)。

28
JoshAdel

私はユークリッド距離のsklearn実装を使用します。利点は、行列の乗算を使用することにより、より効率的な式を使用できることです。

dist(x, y) = sqrt(dot(x, x) - 2 * dot(x, y) + dot(y, y)

単純なスクリプトは次のようになります。

import numpy as np

x = np.random.Rand(1000, 3)
y = np.random.Rand(1000, 3)

dist = np.sqrt(np.dot(x, x)) - (dot(x, y) + dot(x, y)) + dot(y, y)

このアプローチの利点は、sklearnのドキュメント http://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.euclidean_distances.html#sklearn.metricsでうまく説明されています。 pairwise.euclidean_distances

このアプローチを使用して、np.einsum関数を使用するなどのいくつかの小さな変更を加えて、大きなデータマトリックス(10000、10000)をクランチします。

6
lemitech

規範の発達を使用することもできます(注目に値するアイデンティティと同様)。これはおそらく、点の行列の距離を計算する最も効率的な方法です。

以下は、Octaveでk-Nearest-Neighborsの実装に最初に使用したコードスニペットですが、行列の乗算のみを使用するので、numpyに簡単に適合させることができます(同等のものはnumpy.dot()です)。

% Computing the euclidian distance between each known point (Xapp) and unknown points (Xtest)
% Note: we use the development of the norm just like a remarkable identity:
% ||x1 - x2||^2 = ||x1||^2 + ||x2||^2 - 2*<x1,x2>
[napp, d] = size(Xapp);
[ntest, d] = size(Xtest);

A = sum(Xapp.^2, 2);
A = repmat(A, 1, ntest);

B = sum(Xtest.^2, 2);
B = repmat(B', napp, 1);

C = Xapp*Xtest';

dist = A+B-2.*C;
1
gaborous

これはあなたの質問に直接答えないかもしれませんが、あなたが粒子ペアのすべての順列の後である場合、私は以下の解決策がいくつかのケースでpdist関数より速いことがわかりました。

import numpy as np

L   = 100       # simulation box dimension
N   = 100       # Number of particles
dim = 2         # Dimensions

# Generate random positions of particles
r = (np.random.random(size=(N,dim))-0.5)*L

# uti is a list of two (1-D) numpy arrays  
# containing the indices of the upper triangular matrix
uti = np.triu_indices(100,k=1)        # k=1 eliminates diagonal indices

# uti[0] is i, and uti[1] is j from the previous example 
dr = r[uti[0]] - r[uti[1]]            # computes differences between particle positions
D = np.sqrt(np.sum(dr*dr, axis=1))    # computes distances; D is a 4950 x 1 np array

この問題の詳細については、私のブログ投稿で this を参照してください。

1
shrokmel

興味のある距離関数をより詳細に指定する必要があるかもしれませんが、これは Squared Euclidean Distance の非常に単純な(そして効率的な)実装です。に基づく inner product(これは明らかに他の種類の距離測度に一般化された簡単な方法です):

In []: P, c= randn(5, 3), randn(1, 3)
In []: dot(((P- c)** 2), ones(3))
Out[]: array([  8.80512,   4.61693,   2.6002,   3.3293,  12.41800])

ここで、Pはポイントであり、cは中心です。

0
eat
#is it true, to find the biggest distance between the points in surface?

from math import sqrt

n = int(input( "enter the range : "))
x = list(map(float,input("type x coordinates: ").split()))
y = list(map(float,input("type y coordinates: ").split()))
maxdis = 0  
for i in range(n):
    for j in range(n):
        print(i, j, x[i], x[j], y[i], y[j])
        dist = sqrt((x[j]-x[i])**2+(y[j]-y[i])**2)
        if maxdis < dist:

            maxdis = dist
print(" maximum distance is : {:5g}".format(maxdis))
0
Mohammad Feroz