web-dev-qa-db-fra.com

Regroupement de texte avec les distances de Levenshtein

J'ai un ensemble (2k - 4k) de petites chaînes (3-6 caractères) et je veux les regrouper. Puisque j'utilise des chaînes, les réponses précédentes sur Comment fonctionne le clustering (en particulier le clustering de chaînes)? , m'ont informé que Levenshtein distance est bon à utiliser comme fonction de distance pour les chaînes. De plus, comme je ne connais pas à l'avance le nombre de clusters, clustering hiérarchique est la voie à suivre et non k-means.

Bien que j'obtienne le problème sous sa forme abstraite, je ne sais pas quelle est la manière la plus simple de le faire. Par exemple, MATLAB ou R est-il un meilleur choix pour l'implémentation réelle d'un clustering hiérarchique avec la fonction personnalisée (distance Levenshtein). Pour les deux logiciels, on peut facilement trouver une implémentation à distance Levenshtein. La partie de regroupement semble plus difficile. Par exemple Clustering text in MATLAB calcule le tableau de distance pour toutes les chaînes, mais je ne comprends pas comment utiliser le tableau de distance pour obtenir réellement le clustering. Pouvez-vous l'un de vous, gourous, me montrer comment implémenter le clustering hiérarchique dans MATLAB ou R avec une fonction personnalisée?

30
Alexandros

Cela peut être un peu simpliste, mais voici un exemple de code qui utilise un clustering hiérarchique basé sur la distance de Levenshtein dans R.

set.seed(1)
rstr <- function(n,k){   # vector of n random char(k) strings
  sapply(1:n,function(i){do.call(paste0,as.list(sample(letters,k,replace=T)))})
}

str<- c(paste0("aa",rstr(10,3)),paste0("bb",rstr(10,3)),paste0("cc",rstr(10,3)))
# Levenshtein Distance
d  <- adist(str)
rownames(d) <- str
hc <- hclust(as.dist(d))
plot(hc)
rect.hclust(hc,k=3)
df <- data.frame(str,cutree(hc,k=3))

Dans cet exemple, nous créons artificiellement un ensemble de 30 chaînes de caractères aléatoires (5) en 3 groupes (en commençant par "aa", "bb" et "cc"). Nous calculons la matrice de distance de Levenshtein en utilisant adist(...), et nous exécutons le clustering héréditaire en utilisant hclust(...). Ensuite, nous coupons le dendrogramme en trois clusters avec cutree(...) et ajoutons les identifiants de cluster aux chaînes d'origine.

38
jlhoward

ELKI inclut la distance de Levenshtein et offre un large choix d'algorithmes de clustering avancés, par exemple OPTIQUE clustering.

Felix Stahlberg, dans le cadre de son travail sur:

Stahlberg, F., Schlippe, T., Vogel, S., et Schultz, T.
Segmentation des mots par alignement multilingue du mot au phonème.
Atelier sur les technologies de la langue parlée (SLT), 2012 IEEE. IEEE, 2012.

Nous apprécierions bien entendu des contributions supplémentaires.

4
Erich Schubert

Alors que la réponse dépend dans une certaine mesure de la signification des chaînes, votre problème est généralement résolu par la famille de techniques d'analyse de séquence. Plus précisément, l'analyse de correspondance optimale (OMA).

Le plus souvent, l'OMA s'effectue en trois étapes. Tout d'abord, vous définissez vos séquences. D'après votre description, je peux supposer que chaque lettre est un "état" distinct, le bloc de construction dans une séquence. Deuxièmement, vous utiliserez l'un des nombreux algorithmes pour calculer les distances entre toutes les séquences de votre jeu de données, obtenant ainsi la matrice de distance. Enfin, vous alimenterez cette matrice de distance dans un algorithme de clustering, tel que le clustering hiérarchique ou le partitionnement autour de Medoids (PAM), qui semble gagner en popularité en raison des informations supplémentaires sur la qualité des clusters. Ce dernier vous guide dans le choix du nombre de clusters, l'une des différentes étapes subjectives de l'analyse de séquence.

Dans R le package le plus pratique avec un grand nombre de fonctions est TraMineR, le site Web peut être trouvé ici . Son guide d'utilisation est très accessible, et les développeurs sont plus ou moins actifs sur SO également.

Vous trouverez probablement que le clustering n'est pas la partie la plus difficile, à l'exception de la décision sur le nombre de clusters. Le guide pour TraMineR montre que la syntaxe est très simple et les résultats sont faciles à interpréter sur la base de graphiques de séquence visuels. Voici un exemple du guide de l'utilisateur:

clusterward1 <- agnes(dist.om1, diss = TRUE, method = "ward")

dist.om1 est la matrice de distance obtenue par OMA, l'appartenance au cluster est contenue dans l'objet clusterward1, que vous pouvez faire tout ce que vous voulez: traçage, recodage en tant que variables, etc. Le diss=TRUE option indique que l'objet de données est la matrice de dissimilarité (ou distance). Facile, hein? Le choix le plus difficile (non pas syntaxiquement, mais méthodologiquement) est de choisir l'algorithme de distance approprié, adapté à votre application particulière. Une fois que vous avez cela, pouvoir justifier le choix, le reste est assez facile. Bonne chance!

3
Maxim.K

Si vous souhaitez une explication claire de la façon d'utiliser le clustering partiel (qui sera sûrement plus rapide) pour résoudre votre problème, consultez ce document: Méthodes efficaces de vérification orthographique à l'aide d'algorithmes de clustering. https://www.researchgate.net/publication/255965260_Effective_Spell_Checking_Methods_Using_Clustering_Algorithms?ev=prf_pub

Les auteurs expliquent comment regrouper un dictionnaire à l'aide d'une version modifiée (de type PAM) d'iK-Means.

Bonne chance!

2
TheVoiceInMyHead