Quel algorithme donne des suggestions dans un correcteur orthographique?

114

Quel algorithme est généralement utilisé lors de la mise en œuvre d'un correcteur orthographique accompagné de suggestions de mots?

Au début, j'ai pensé qu'il pourrait être judicieux de vérifier chaque nouveau mot tapé (s'il ne se trouve pas dans le dictionnaire) par rapport à la distance de Levenshtein de tous les autres mots du dictionnaire et de renvoyer les meilleurs résultats. Cependant, cela semble être très inefficace, étant obligé d'évaluer le dictionnaire entier à plusieurs reprises.

Comment cela se fait-il généralement?

Mithrax
la source

Réponses:

203

Il y a un bon essai de Peter Norvig sur la façon d'implémenter un correcteur orthographique. Il s'agit essentiellement d'une approche de force brute essayant des chaînes candidates avec une distance d'édition donnée. ( Voici quelques conseils pour améliorer les performances du correcteur orthographique à l'aide d'un filtre Bloom et d' un hachage plus rapide des candidats .)

Les exigences pour un correcteur orthographique sont plus faibles. Vous n'avez qu'à découvrir qu'un mot n'est pas dans le dictionnaire. Vous pouvez utiliser un filtre Bloom pour créer un correcteur orthographique qui consomme moins de mémoire. Une version ancienne est décrite dans Programming Pearls par Jon Bentley en utilisant 64kb pour un dictionnaire anglais.

Un BK-Tree est une approche alternative. Un bel article est ici .

La distance de Levenshstein n'est pas exactement la bonne distance d'édition pour un correcteur orthographique. Il ne connaît que l'insertion, la suppression et la substitution. La transposition est manquante et produit 2 pour une transposition de 1 caractère (c'est 1 suppression et 1 insertion). La distance Damerau – Levenshtein est la bonne distance d'édition.

Thomas Jung
la source
2
+1 pour la référence BK-Tree relativement inconnue. C'est ainsi que des entreprises comme Google, qui travaillent avec la quantité de données Real-World ™, le font.
NoozNooz42
2
Il y a une bien meilleure explication des BK-Trees ici .
Ian Boyd
17

Une approche pour générer des suggestions que j'ai utilisées avec succès mais que je n'ai jamais vues décrites nulle part consiste à pré-calculer les suggestions (lors de la construction du dictionnaire) en utilisant des fonctions de hachage "mauvaises".

L'idée est d'examiner les types d'erreurs d'orthographe que les gens font et de concevoir des fonctions de hachage qui attribueraient une orthographe incorrecte au même compartiment que son orthographe correcte.

Par exemple, une erreur courante consiste à utiliser la mauvaise voyelle, comme definate au lieu de définitif . Vous concevez donc une fonction de hachage qui traite toutes les voyelles comme la même lettre. Une manière simple de le faire est de «normaliser» d'abord le mot d'entrée, puis de placer le résultat normalisé via une fonction de hachage régulière. Dans cet exemple, la fonction de normalisation peut supprimer toutes les voyelles, ainsi le definitedevient dfnt. Le mot "normalisé" est ensuite haché avec une fonction de hachage typique.

Insérez tous les mots de votre dictionnaire dans un index auxiliaire (table de hachage) à l'aide de cette fonction de hachage spéciale. Les compartiments de ce tableau auront des listes de collisions plus longues car la fonction de hachage est «mauvaise», mais ces listes de collisions sont essentiellement des suggestions précalculées.

Désormais, lorsque vous trouvez un mot mal orthographié, vous recherchez dans les listes de collisions le compartiment auquel la faute d'orthographe correspond dans les index auxiliaires. Ta da: Vous avez une liste de suggestions! Tout ce que vous avez à faire est de classer les mots dessus.

En pratique, vous aurez besoin de quelques index auxiliaires avec d'autres fonctions de hachage pour gérer d'autres types d'erreurs, comme des lettres transposées, une lettre simple / double et même une simple de type Soundex pour détecter les fautes d'orthographe phonétiques. Dans la pratique, j'ai trouvé que les prononciation simplistes allaient très loin et certaines d'entre elles étaient essentiellement obsolètes pour trouver des fautes de frappe triviales.

Vous recherchez maintenant les fautes d'orthographe dans chacun des index auxiliaires et concaténez les listes de collisions avant le classement.

Souvenez-vous que les listes de collisions ne contiennent que les mots du dictionnaire. Avec des approches qui tentent de générer des orthographes alternatives (comme dans l'article de Peter Norvig), vous pouvez obtenir (dizaines de) milliers de candidats que vous devez d'abord filtrer par rapport au dictionnaire. Avec l'approche pré-calculée, vous obtenez peut-être quelques centaines de candidats, et vous savez qu'ils sont tous correctement orthographiés, vous pouvez donc passer directement au classement.

Mise à jour : j'ai depuis trouvé une description d'algorithme similaire à celle-ci, la recherche distribuée FAROO . Il s'agit toujours d'une recherche limitée à la distance d'édition, mais elle est très rapide car l'étape de pré-calcul fonctionne comme mon idée de «mauvaises fonctions de hachage». FAROO utilise simplement un concept limité de mauvaise fonction de hachage.

Adrian McCarthy
la source
Merci d'avoir fait référence à l'algorithme SymSpell de Faroos. Alors que les deux algorithmes précalculent les fautes de frappe possibles et utilisent une table de hachage pour une recherche rapide, la principale différence est que SymSpell garantit de détecter toutes les erreurs d'orthographe possibles jusqu'à une certaine distance d'édition (à cet égard, SymSpell est équivalent à l'algorithme de Peter Norvig, juste 3..6 ordres de grandeur plus rapides), alors que votre algorithme utilise une approche heuristique qui ne détectera qu'un sous-ensemble limité de toutes les fautes d'orthographe théoriquement possibles (donc votre coût de pré-calcul pourrait être inférieur).
Wolf Garbe
L'algorithme SymSpell pré-calcule et stocke explicitement les fautes de frappe possibles, ce n'est pas le cas de mon schéma de "mauvais hachage". Pour l'anglais, il est trivial d'ajouter juste un hachage phonétique simpliste qui couvre beaucoup de terrain (par exemple, "terradacktle" -> "pterodactyl", qui a une distance d'édition de 6). Certes, si vous avez besoin de recherches multilingues, cela peut être beaucoup plus difficile.
Adrian McCarthy le
Absolument, en exploitant les connaissances empiriques sur les fautes de frappe probables (et en vous limitant à celles-ci), vous économisez du temps et de l'espace avant le calcul. Mais pour couvrir toutes les erreurs d'orthographe possibles, SymSpell n'a besoin de pré-calculer qu'une infime partie d'entre elles. Un mot de 5 lettres a environ 3 millions d'erreurs d'orthographe possibles dans une distance d'édition maximale de 3, mais avec SymSpell, vous devez pré-calculer et stocker seulement 25 suppressions. Ceci est important pour la recherche floue / similitude au-delà de la correction orthographique là où aucune connaissance empirique n'existe.
Wolf Garbe
7

Algorithme

  1. Prenez un mot mal orthographié comme entrée.
  2. Stockez la liste des mots anglais avec leurs fréquences dans un fichier texte.
  3. Insérez tous les mots anglais disponibles (stockés dans le fichier texte) avec leur fréquence (mesure de la fréquence à laquelle un mot est utilisé en anglais) dans un arbre de recherche ternaire.
  4. Traversez maintenant l'arbre de recherche ternaire -
    • Pour chaque mot rencontré dans l'arbre de recherche ternaire, calculez sa distance de Levensthein à partir du mot mal orthographié.
    • Si Levensthein Distance <= 3, enregistrez le mot dans une file d'attente prioritaire.
    • Si deux mots ont la même distance d'édition, celui avec la fréquence la plus élevée est râpe. Imprimez les 10 premiers éléments de la file d'attente prioritaire.

Optimisation

  1. Vous pouvez éliminer les mots du sous-arbre du nœud actuel si la distance d'édition de la sous-chaîne du mot d'entrée par rapport au mot actuel est supérieure à 3.
    Vous pouvez trouver l'explication plus détaillée et le code source sur le projet github .
amarjeet
la source
Hmm, la distance de Levenshtein entre «râpe» et «plus grand» dans ce cas ne serait pas suffisante, car «râpe» est également un mot du dictionnaire. ;-)
Tony Brasunas
1
@TonyBrasunas, oui vous avez raison. Mais le programme renverra en fait une liste de 10 mots dans le cas de «râpe» comme entrée et il suggérera «râpe» avec une distance d'édition de 0 et aussi «plus grand» avec une distance d'édition de 1. Ce qui pourrait être d'une certaine aide. ;)
amarjeetAnand
Si un candidat a une distance de 2, mais est extrêmement fréquente, et un autre candidat a une distance de 1 mais est extrêmement rare, comment classez-vous les deux? Dans l'approche ci-dessus, l'objet rare gagnerait toujours, est-ce le bon résultat?
speedplane
@speedplane Oui. le rare gagnera. Et je pense que c'est le bon résultat. Parce que ce que nous attendons est le mot le plus proche, basé sur l'orthographe du mot d'entrée. Si vous avez encore des doutes, pensez de cette façon - supposons qu'il existe un mot rare que l'utilisateur a correctement orthographié. Maintenant, sa distance est de 0 mais sa fréquence est très basse. Maintenant, dans les suggestions, nous devrions lister ce mot rare (avec une distance 0) en haut (car la distance minimale d'édition l'emporte) et d'autres mots avec une distance 1-2-3, ci-dessous.
amarjeetAnand
3

Vous n'avez pas besoin de connaître la distance d'édition exacte pour chaque mot du dictionnaire. Vous pouvez arrêter l'algorithme après avoir atteint une valeur limite et exclure le mot. Cela vous fera gagner beaucoup de temps de calcul.

Petr Peller
la source
1

Le correcteur orthographique est très facile à implémenter comme dans le programme orthographique Unix. Le code source est disponible en public. La correction peut être impliquée, une technique consiste à faire des modifications et à vérifier à nouveau si ce nouveau mot est dans le dictionnaire. Ces nouvelles modifications peuvent être regroupées et présentées à l'utilisateur.

Le système Unix utilise un programme écrit par Mc IllRoy. Une autre manière est d'utiliser un Trie qui peut être utile dans le cas de fichiers volumineux.

L'approche unix nécessite très moins d'espace pour un énorme dictionnaire car elle utilise un algorithme de hachage de dispersion.

Harisankar Krishna Swamy
la source