Python >> Tutoriel Python >  >> Python

Puis-je utiliser l'algorithme K-means sur une chaîne ?

Un problème auquel vous seriez confronté si vous utilisiez scipy.cluster.vq.kmeans est que cette fonction utilise la distance euclidienne pour mesurer la proximité. Pour transformer votre problème en un problème résoluble par k-means clustering, vous devez trouver un moyen de convertir vos chaînes en vecteurs numériques et être en mesure de justifier l'utilisation de la distance euclidienne comme mesure raisonnable de proximité.

Cela semble... difficile. Peut-être recherchez-vous plutôt la distance de Levenshtein ?

Notez qu'il existe des variantes de l'algorithme K-means qui peuvent fonctionner avec des métriques de distance non-Euclideance (telles que la distance de Levenshtein). K-medoids (alias PAM), par exemple, peut être appliqué aux données avec une métrique de distance arbitraire.

Par exemple, en utilisant Pycluster l'implémentation de k-medoids , et nltk l'implémentation de la distance de Levenshtein,

import nltk.metrics.distance as distance
import Pycluster as PC

words = ['apple', 'Doppler', 'applaud', 'append', 'barker', 
         'baker', 'bismark', 'park', 'stake', 'steak', 'teak', 'sleek']

dist = [distance.edit_distance(words[i], words[j]) 
        for i in range(1, len(words))
        for j in range(0, i)]

labels, error, nfound = PC.kmedoids(dist, nclusters=3)
cluster = dict()
for word, label in zip(words, labels):
    cluster.setdefault(label, []).append(word)
for label, grp in cluster.items():
    print(grp)

donne un résultat comme

['apple', 'Doppler', 'applaud', 'append']
['stake', 'steak', 'teak', 'sleek']
['barker', 'baker', 'bismark', 'park']

K-means ne fonctionne qu'avec la distance euclidienne. Les distances d'édition telles que Levenshtein ne obéissent même pas à l'inégalité triangulaire peuvent obéir à l'inégalité triangulaire, mais ne sont pas euclidiens. Pour les types de métriques qui vous intéressent, il vaut mieux utiliser un autre type d'algorithme, tel que le clustering hiérarchique :http://en.wikipedia.org/wiki/Hierarchical_clustering

Alternativement, convertissez simplement votre liste d'ARN en un graphique pondéré, avec des poids de Levenshtein sur les bords, puis décomposez-la en un arbre couvrant minimum. Les nœuds les plus connectés de cet arbre seront, en un sens, les "plus représentatifs".


K-means ne se soucie pas vraiment du type de données impliquées. Tout ce dont vous avez besoin pour faire un K-means est un moyen de mesurer une "distance" d'un élément à un autre. Il fera son travail en fonction des distances, quelle que soit la façon dont cela se calcule à partir des données sous-jacentes.

Cela dit, je n'ai pas utilisé scipy.cluster.vq , donc je ne sais pas exactement comment vous lui indiquez la relation entre les éléments, ou comment calculer une distance entre l'élément A et l'élément B.