web-dev-qa-db-fra.com

Comment spécifier une fonction de distance pour le clustering?

J'aimerais regrouper les points attribués à une distance personnalisée et, étrangement, il semble que ni les méthodes de regroupement scipy ni sklearn ne permettent de spécifier une fonction de distance.

Par exemple, dans sklearn.cluster.AgglomerativeClustering, la seule chose que je puisse faire est d'entrer une matrice d'affinité (qui sera très gourmande en mémoire). Afin de construire cette matrice, il est recommandé d'utiliser sklearn.neighbors.kneighbors_graph, mais je ne comprends pas comment spécifier une fonction de distance entre deux points. Quelqu'un pourrait-il m'éclairer?

19
Mark Morrisson

Toutes les routines de clustering hiérarchiques scipy accepteront une fonction de distance personnalisée qui accepte deux vecteurs 1D spécifiant une paire de points et renvoie un scalaire. Par exemple, en utilisant fclusterdata :

import numpy as np
from scipy.cluster.hierarchy import fclusterdata

# a custom function that just computes Euclidean distance
def mydist(p1, p2):
    diff = p1 - p2
    return np.vdot(diff, diff) ** 0.5

X = np.random.randn(100, 2)

fclust1 = fclusterdata(X, 1.0, metric=mydist)
fclust2 = fclusterdata(X, 1.0, metric='euclidean')

print(np.allclose(fclust1, fclust2))
# True

Entrées valides pour le metric= kwarg sont les mêmes que pour scipy.spatial.distance.pdist .

16
ali_m

sklearn a DBSCAN qui permet des matrices de distance précalculées (en utilisant une matrice triangulaire où M_ij est la distance entre i et j). Mais ce n'est peut-être pas le type de clustering que vous recherchez.

De plus, comme quelqu'un l'a mentionné, scipy.cluster.hierarchy.fclusterdata permet également des mesures de distance précalculées. Il y a un extrait de code donné dans cette réponse qui donne un peu de code pour transformer une matrice NxN de distances en un format que fclusterdata peut facilement lire:

import scipy.spatial.distance as ssd
# convert the redundant n*n square matrix form into a condensed nC2 array
    distArray = ssd.squareform(distMatrix) # distArray[{n choose 2}-{n-i choose 2} + (j-i-1)] is the distance between points i and j
3
samus

Pour le clustering hiérarchique, scipy.cluster.hierarchy.fclusterdata vous permet d'utiliser n'importe quelle métrique de distance incluse dans la liste ici via le metric= argument mot-clé, à condition qu'il fonctionne avec la méthode de liaison souhaitée.

1
Adam Acosta