5

Stavo cercando di utilizzare l'algoritmo DBSCAN dalla libreria scikit-learn con la metrica coseno, ma sono rimasto bloccato con l'errore. La riga di codice èErrore DBSCAN con metrica coseno in python

db = DBSCAN(eps=1, min_samples=2, metric='cosine').fit(X)  

dove X è un csr_matrix. L'errore è la seguente:

Metric 'cosine' non è valida per l'algoritmo 'auto',

se la documentazione dice che è possibile utilizzare questa metrica. Ho provato a utilizzare l'opzione algorithm='kd_tree' e 'ball_tree' ma ho ottenuto lo stesso. Tuttavia, non vi è alcun errore se utilizzo la misura euclidean o, ad esempio, l1.

La matrice X è grande, quindi non è possibile utilizzare una matrice pre-elaborata di distanze a coppie.

Io uso python 2.7.6 e scikit-learn 0.16.1. Il mio set di dati non ha una riga completa di zeri, quindi la metrica coseno è ben definita.

+0

Questo è probabilmente un bug in sklearn, francamente. La somiglianza del coseno non è una metrica. Non obbedisce alla disuguaglianza triangolare, ed è per questo che non funzionerà con un KDTree e non hai altra scelta se non quella di forzarlo. Tutto ciò solleva la questione del perché quando si imposta l'algoritmo su "auto", si tenta di utilizzare un metodo che dovrebbe sapere che non può utilizzare. –

+0

@AdamAcosta: Se ho capito bene, stai sostenendo che la parola chiave '' auto'' 'algorithm' dovrebbe usare' 'brute'' piuttosto che provare e fallire usando '' ball_tree''? (Sono d'accordo.) –

risposta

9

Gli indici in sklearn (probabilmente - questo potrebbe cambiare con le nuove versioni) non possono accelerare il coseno.

Prova algorithm='brute'.

Per un elenco di metriche che la versione di sklearn può accelerare, vedere le metriche supportate dell'albero palla:

from sklearn.neighbors.ball_tree import BallTree 
print(BallTree.valid_metrics) 
+0

Grazie! Ora funziona. In primo luogo, mi ha dato un errore perché ho usato 'np.float32' invece di' np.double' per il mio set di dati. Suppongo che DBSCAN richieda tale precisione per la metrica coseno poiché quest'ultimo ha un intervallo ristretto (tra 0 e 1). – cheyp

+0

Ciò non dovrebbe essere necessario in generale, ma l'implementazione sklearn potrebbe avere tali limiti. –

4

Se si desidera una distanza normalizzata come la distanza del coseno, è anche possibile normalizzare i vettori prima e poi usare la metrica euclidea. Si noti che per i due vettori normalizzati uev la distanza euclidea è pari a sqrt (2-2 cos * (u, v)) (see this discussion)

È quindi possibile fare qualcosa di simile:

Xnorm = np.linalg.norm(X,axis = 1) 
Xnormed = np.divide(X,Xnorm.reshape(Xnorm.shape[0],1)) 
db = DBSCAN(eps=0.5, min_samples=2, metric='euclidean').fit(Xnormed) 

Il le distanze si troveranno in [0,2] quindi assicurati di regolare i parametri di conseguenza.

+0

Potresti ampliare un po 'di più il motivo per cui l'algoritmo DBSCAN con i vettori euclidian-distance-on-normalized darebbe lo stesso risultato della distanza straight-cosine, se questo è il caso? In particolare, che cos'è la squadratura/radice quadrata, e importa che il coseno misura davvero * la somiglianza * e non la distanza (la distanza è '1-cos (.;.)) –

+0

Ad esempio, se si sa che 'eps' deve essere impostato su' x' con distanza coseno, allora dovrebbe essere impostato su 'sqrt (x)' quando si usa DBSCAN con 'euclid'. E, se tali dati sono, l'indicizzazione di sklearn sta completando il suo scopo di fissaggio? –

+0

@NikanaReklawyks Come ho detto sopra, ciò che ho menzionato qui può essere fatto per ottenere una distanza normalizzata come la distanza del coseno. Non sarà esattamente lo stesso a causa dell'operazione di squadratura. Inoltre, come hai notato, la distanza coseno è ciò che le persone chiamano il complemento della somiglianza del coseno nello spazio positivo, non è una metrica di distanza adeguata. Ma non vado in quei dettagli poiché la domanda posta sulla distanza del coseno. – benbo

Problemi correlati