Calcul rapide de la distance Levenshtein


24

Étant donné une énorme base de données de mots autorisés (triés par ordre alphabétique) et un mot, recherchez le mot de la base de données le plus proche du mot donné en termes de distance de Levenshtein.

L'approche naïve consiste, bien entendu, à simplement calculer la distance de levenshtein entre le mot donné et tous les mots du dictionnaire (on peut faire une recherche binaire dans la base de données avant de calculer réellement les distances).

Je me demande s'il existe une solution plus efficace à ce problème. Peut-être une heuristique qui nous permet de réduire le nombre de mots à rechercher, ou des optimisations à l'algorithme de distance levenshtein.

Liens vers des articles sur le sujet bienvenus.

Réponses:


16

Ce que vous demandez, c'est le problème de la recherche de voisins proches sous la distance de modification. Vous n'avez pas mentionné si vous êtes intéressé par les résultats théoriques ou l'heuristique, je vais donc répondre à la première.

La distance de montage est quelque peu désagréable à gérer pour la construction de structures de recherche proches voisins. Le problème principal est qu'en tant que métrique, elle se comporte (en quelque sorte) comme d'autres mauvaises métriques bien connues comme aux fins de réduction et d'approximation de dimensionnalité. Il y a un travail assez vaste à lire sur ce sujet, et votre meilleure source est l'ensemble des articles d' Alex Andoni : en suivant les pointeurs vers l'arrière (par exemple à partir de son article FOCS 2010), vous obtiendrez un bon ensemble de sources.1


1
Tout ce que je sais sur les espaces métriques est de la sémantique, donc une question: y a-t-il des incorporations décentes (pour n'importe quelle valeur de décent) de la métrique Levenshtein dans un ultramétrique? Offhand, cela pourrait donner lieu à un algorithme d'arbre binaire.
Neel Krishnaswami

Je ne suis pas tout à fait sûr. Je soupçonne que la réponse est non en général, mais je n'ai rien à signaler.
Suresh Venkat

Le deuxième article sur boytsov.info/pubs est un bon aperçu des solutions possibles pour la recherche de voisins proches sous la distance d'édition Levenshtein et Damereau-Levenshtein.
a3nm

@NeelKrishnaswami Une intégration dans un ultramétrique aurait une distorsion d'au moins d est la longueur de la chaîne. Cela découle d'une distorsion de la borne inférieure pour l'incorporation dans L 1 due à Krauthgamer et Rabani , car les ultramétriques sont intégrés isométriquement dans l'espace euclidien, qui s'intègre isométriquement dans L 1 . Ω(logd)dL1L1
Sasho Nikolov


5

Si vous avez un petit nombre de modifications erronées que vous allez tolérer, vous pouvez essayer d'utiliser un arbre de suffixes en pointillés . Avertissement: j'ai écrit ce document, mais il résout ce que vous voulez: il a un coût d'espace disque élevé, mais les requêtes sont vraiment rapides.

En général, il vaut mieux le regarder dans l'autre sens: vous avez un index de tous les mots du dictionnaire. Maintenant, pour un mot d'entrée w, s'il se trouve dans le dictionnaire, arrêtez. Sinon, générez toutes les variations à la distance 1 et recherchez-les. S'ils ne sont pas là, cherchez des variations à la distance 2, etc.

Il y a plusieurs améliorations à cette idée de base.


1
Vous devriez avoir inclus un lien vers vos archives de recherche reproductibles pour l'article .
Dan D.


4

J'ai écrit une réponse à une question très similaire sur cs.stackexchange.com ( /cs//a/2096/1490 ), puis j'ai trouvé cette question. La réponse est pour la recherche approximative du voisin proche dans la distance d'édition (c'est-à-dire que l'algorithme génère une chaîne qui est approximativement aussi proche de la chaîne de requête que le plus proche voisin de la chaîne de requête). Je poste ici car je ne trouve aucune des références que j'ai données dans les réponses données ici.



2

Vous pouvez utiliser Vouliez-vous dire?

Et puis trouvez la distance Levenshtein entre la réponse renvoyée par "Vouliez-vous dire" "et la chaîne de saisie à l'aide de la programmation dynamique.


Je ne comprends pas cette réponse. La question demande comment on peut trouver efficacement un mot dans un grand dictionnaire avec une distance Levenshtein proche d'une entrée donnée, pas sur la façon de calculer la distance Levenshtein ou sur la comparaison avec la sortie d'un correcteur orthographique de boîte noire ...
Huck Bennett

@Huck Bennett: Je pensais que @Grigory Javadyan était en train de construire Did you mean?. En plus Did you mean?retourne le mot qui est très proche de l'entrée donnée et le fait assez efficacement. :)
Pratik Deoghare

Je pense que vos idées sont bonnes, mais il semble que Grigory demande quelque chose de plus profond et de plus spécifique.
Huck Bennett

@Huck Bennett: Oui, vous avez raison! :)
Pratik Deoghare

-1

Une façon consiste à former un modèle d'apprentissage automatique pour mapper les mots aux vecteurs et mapper la distance levenshtein à la distance euclidienne. Ensuite, vous pouvez créer un KDTree à partir des vecteurs du dictionnaire que vous souhaitez utiliser. J'ai créé un cahier jupyter qui le fait ici: https://gist.github.com/MichaelSnowden/9b8b1e662c98c514d571f4d5c20c3a03

Selon les commentaires de DW:

  1. procédure de formation = descente de gradient stochastique avec gradients adaptatifs
  2. fonction de perte = erreur quadratique moyenne entre la vraie distance d'édition et la distance euclidienne
  3. données d'apprentissage = chaînes aléatoires de 1 à 32 caractères (pourraient être améliorées avec des données correspondant à une distribution réelle de fautes de frappe courantes)
  4. résultats quantitatifs: après une formation d'environ 150 époques avec une taille de lot de 2048 (durée du mur = environ une minute), en utilisant des incorporations de mots de 512 dimensions, avec une couche cachée, l'erreur absolue moyenne entre la vraie distance d'édition et la distance d'édition prévue se situe à environ 0,75, ce qui signifie que la distance d'édition prévue est d'environ un caractère

Résumé de la structure du modèle:

  1. Créez une incorporation apprise pour chaque caractère, y compris le caractère nul (utilisé plus tard pour compléter le texte à droite sous la limite de caractères)
  2. Remplissez le côté droit du texte avec le caractère nul jusqu'à ce qu'il soit à la limite de caractères (32)
  3. Concaténer ces plongements
  4. Exécutez les plongements à travers un réseau de neurones à action directe pour produire une intégration de mots de dimension inférieure (512 dimensions)
  5. Faites cela pour les deux mots
  6. Trouver la distance euclidienne entre les vecteurs
  7. Définir la perte comme étant l'erreur quadratique moyenne entre la vraie distance de Levenshtein et la distance euclidienne

Mes données d'entraînement ne sont que des chaînes aléatoires, mais je pense que les résultats pourraient vraiment s'améliorer si les données d'entraînement étaient des paires (faute de frappe / mot correct). J'ai fini par utiliser simplement /usr/share/dict/wordsparce qu'il est couramment disponible.


2
Comment entraînez-vous un modèle ML afin que les mots qui se trouvent à proximité dans la carte de distance de Levenshtein à des vecteurs similaires? Quelle procédure de formation et quelle fonction de perte utilisez-vous pour cela? Pouvez-vous résumer la méthode dans votre réponse, afin que la réponse soit toujours utile même si le lien cesse de fonctionner, et pour que nous n'ayons pas à fouiller dans votre carnet pour comprendre la méthode que vous utilisez? Pouvez-vous également évaluer son efficacité quantitative? Est-ce mieux que les alternatives?
DW

À l'heure actuelle, c'est (je pense) un mauvais ajustement pour CSTheory. Autrement dit, aucune idée de ce qui est spécifiquement suggéré, et aucune justification théorique pour cela.
Clement C.

@DW Désolé à ce sujet - j'ai fait une modification assez substantielle qui devrait être complète au cas où le lien tomberait (ou au cas où vous ne voudriez pas fouiller dans le cahier). Bien que ce ne soit pas vraiment de la théorie CS car ce n'est pas de la recherche, je pense que c'est une approche pratique car elle est rapide et facile à la fois pour la formation et l'inférence.
michaelsnowden

1
Vous vous entraînez sur des chaînes aléatoires. La distance Levenshtein attendue entre deux de ces chaînes sera approximativement la longueur de la chaîne la plus longue. Ainsi, il est très facile d'estimer cette distance sur des chaînes aléatoires, mais ce n'est pas utile pour traiter des données réelles. Je soupçonne que vos intégrations peuvent simplement coder la longueur de la chaîne, et donc vous avez peut-être construit une façon élégante de faire quelque chose de trivial et inutile. C'est un problème avec l'utilisation de ML; il est très sensible à la fonction de perte que vous utilisez.
DW

@DW Si vous regardez les résultats dans le bloc-notes, la récupération a fini par donner des résultats décents - pas seulement des chaînes de même longueur. Je vous encourage vraiment à le parcourir. Je ne dirais pas que c'est trivial et inutile.
michaelsnowden
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.