Domanda

Sto cercando di cluster utilizzando DBSCAN (scikit saperne di attuazione) e la posizione dei dati.I miei dati sono in np formato di gamma, ma di utilizzare DBSCAN con Haversine formula ho bisogno di creare una matrice di distanza.Ricevo il seguente errore quando provo a fare questo( un 'modulo' non callable errore). Da quello che ho leggendo questa linea è un errore di importazione, ma sono abbastanza sicuro che non è questo il caso per me.Ho creato il mio haversine distanza formula, ma sono sicuro che l'errore non è con questo.

Questo è il mio dati di input, un np array (ResultArray).

[[ 53.3252628   -6.2644198 ]
[ 53.3287395   -6.2646543 ]
[ 53.33321202  -6.24785807]
[ 53.3261015   -6.2598324 ]
[ 53.325291    -6.2644105 ]
[ 53.3281323   -6.2661467 ]
[ 53.3253074   -6.2644483 ]
[ 53.3388147   -6.2338417 ]
[ 53.3381102   -6.2343826 ]
[ 53.3253074   -6.2644483 ]
[ 53.3228188   -6.2625379 ]
[ 53.3253074   -6.2644483 ]]

E questa è la riga di codice che mandare in errore.

distance_matrix = sp.spatial.distance.squareform(sp.spatial.distance.pdist
(ResultArray,(lambda u,v: haversine(u,v))))

Questo è il messaggio di errore:

File "Location.py", line 48, in <module>
distance_matrix = sp.spatial.distance.squareform(sp.spatial.distance.pdist
(ResArray,(lambda u,v: haversine(u,v))))
File "/usr/lib/python2.7/dist-packages/scipy/spatial/distance.py", line 1118, in pdist
dm[k] = dfun(X[i], X[j])
File "Location.py", line 48, in <lambda>
distance_matrix = sp.spatial.distance.squareform(sp.spatial.distance.pdist
(ResArray,(lambda u,v: haversine(u,v))))
TypeError: 'module' object is not callable

Mi importa scipy sp.( importazione scipy sp )

È stato utile?

Soluzione

Si prega di fare riferimento a @TommasoF risposta.Questa risposta è sbagliata: pdist permette di scegliere una custom funzione di distanza.Voglio eliminare la risposta una volta che non è più scelto come risposta corretta.

Semplicemente scipy's pdist non consentire il passaggio di un custom funzione di distanza.Come si può leggere nel docs, avete alcune opzioni, ma haverside distanza non è nella lista dei supportati metriche.

(Matlab pdist non supporta l'opzione, però, vedere qui)

hai bisogno di fare il calcolo "manuale", cioècon passanti, qualcosa di simile a questo lavoro:

from numpy import array,zeros

def haversine(lon1, lat1, lon2, lat2):
    """  See the link below for a possible implementation """
    pass

#example input (your's, truncated)
ResultArray = array([[ 53.3252628, -6.2644198 ],
                     [ 53.3287395  , -6.2646543 ],
                     [ 53.33321202 , -6.24785807],
                     [ 53.3253074  , -6.2644483 ]])

N = ResultArray.shape[0]
distance_matrix = zeros((N, N))
for i in xrange(N):
    for j in xrange(N):
        lati, loni = ResultArray[i]
        latj, lonj = ResultArray[j]
        distance_matrix[i, j] = haversine(loni, lati, lonj, latj)
        distance_matrix[j, i] = distance_matrix[i, j]

print distance_matrix
[[ 0.          0.38666203  1.41010971  0.00530489]
 [ 0.38666203  0.          1.22043364  0.38163748]
 [ 1.41010971  1.22043364  0.          1.40848782]
 [ 0.00530489  0.38163748  1.40848782  0.        ]]

Solo per riferimento, un'implementazione in Python di Haverside può essere trovato qui.

Altri suggerimenti

Con Scipy è possibile definire una funzione di distanza personalizzata come suggerito dalla documentazione in questo Link e segnalato qui per convenienza:

.
Y = pdist(X, f)
.
Computes the distance between all pairs of vectors in X using the user supplied 2-arity function f. For example, Euclidean distance between the vectors could be computed as follows:

dm = pdist(X, lambda u, v: np.sqrt(((u-v)**2).sum()))
.

Qui riporto la mia versione del codice ispirato al codice da questo Link :

from numpy import sin,cos,arctan2,sqrt,pi # import from numpy
# earth's mean radius = 6,371km
EARTHRADIUS = 6371.0

def getDistanceByHaversine(loc1, loc2):
    '''Haversine formula - give coordinates as a 2D numpy array of
    (lat_denter link description hereecimal,lon_decimal) pairs'''
    #      
    # "unpack" our numpy array, this extracts column wise arrays
    lat1 = loc1[1]
    lon1 = loc1[0]
    lat2 = loc2[1]
    lon2 = loc2[0]
    #
    # convert to radians ##### Completely identical
    lon1 = lon1 * pi / 180.0
    lon2 = lon2 * pi / 180.0
    lat1 = lat1 * pi / 180.0
    lat2 = lat2 * pi / 180.0
    #
    # haversine formula #### Same, but atan2 named arctan2 in numpy
    dlon = lon2 - lon1
    dlat = lat2 - lat1
    a = (sin(dlat/2))**2 + cos(lat1) * cos(lat2) * (sin(dlon/2.0))**2
    c = 2.0 * arctan2(sqrt(a), sqrt(1.0-a))
    km = EARTHRADIUS * c
    return km
.

e chiamando nel modo seguente:

D = spatial.distance.pdist(A, lambda u, v: getDistanceByHaversine(u,v))
.

Nella mia implementazione la matrice A è come prima colonna dei valori di longitudine e come seconda colonna i valori di latitudine espressi in gradi decimali.

Ora puoi cluster il cluster di DBSCAN di DBSCan e DBSCAN di Scikit-Leart senza precomputing di una matrice di distanza con Scipy.

db = DBSCAN(eps=2/6371., min_samples=5, algorithm='ball_tree', metric='haversine').fit(np.radians(coordinates))
.

Questo viene da questo tutorial su Clustering Dati spaziali con Scikit-Learn DbScan .In particolare, si nota che il valore eps è diviso di 2 km per 6371 (raggio della Terra nel km) per convertirlo in Radians.Inoltre, notare che .fit() prende coordinate in unità radiali per la metrica di Haversine.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top