Jaki algorytm podaje sugestie w module sprawdzania pisowni?

114

Jaki algorytm jest zwykle używany podczas implementowania modułu sprawdzania pisowni, któremu towarzyszą sugestie słów?

Na początku pomyślałem, że sensowne może być sprawdzenie każdego nowego wpisanego słowa (jeśli nie ma go w słowniku) pod kątem jego odległości Levenshteina od każdego innego słowa w słowniku i zwrócenie pierwszych wyników. Wydaje się jednak, że byłoby to wysoce nieefektywne, wymagając wielokrotnej oceny całego słownika.

Jak to się zazwyczaj robi?

Mithrax
źródło

Odpowiedzi:

203

Jest dobry esej autorstwa Petera Norviga, jak wdrożyć korektor pisowni. Jest to w zasadzie metoda brutalnej siły, próbująca sprawdzać ciągi kandydatów z określoną odległością edycji. ( Oto kilka wskazówek, jak poprawić wydajność korektora pisowni za pomocą filtra Blooma i szybszego haszowania kandydatów ).

Wymagania dotyczące modułu sprawdzania pisowni są słabsze. Musisz tylko dowiedzieć się, że słowa nie ma w słowniku. Możesz użyć filtra wykwitów, aby zbudować moduł sprawdzania pisowni, który zużywa mniej pamięci. Starożytna wersja jest opisana w Perły programowania autorstwa Jona Bentleya przy użyciu 64kb dla angielskiego słownika.

BK-Tree jest alternatywne podejście. Ładny artykuł jest tutaj .

Odległość Levenshsteina nie jest dokładnie odpowiednią odległością edycji dla modułu sprawdzania pisowni. Zna tylko wstawianie, usuwanie i podstawianie. Brak transpozycji i daje 2 dla transpozycji 1 znaku (to jest 1 usunięcie i 1 wstawienie). Odległość Damerau – Levenshteina to właściwa odległość edycji.

Thomas Jung
źródło
2
+1 dla stosunkowo nieznanego odniesienia do BK-Tree. W ten sposób robią to firmy takie jak Google, pracujące z ilością danych Real-World [TM].
NoozNooz42
2
Jest to znacznie lepsze wyjaśnienie BK drzew tutaj .
Ian Boyd
17

Podejściem do generowania sugestii, które z powodzeniem stosowałem, ale nigdzie nie widziałem opisanego, polega na wstępnym obliczaniu sugestii (podczas budowania słownika) przy użyciu „złych” funkcji skrótu.

Chodzi o to, aby przyjrzeć się typom błędów pisowni, które ludzie popełniają, i zaprojektować funkcje skrótu, które przypisałyby niepoprawną pisownię do tego samego zasobnika, co poprawna pisownia.

Na przykład, częstym błędem jest użycie niewłaściwego samogłoskę, jak zdecydowanym zamiast definitywna . Więc projektujesz funkcję skrótu, która traktuje wszystkie samogłoski jako tę samą literę. Łatwym sposobem na to jest najpierw „znormalizowanie” słowa wejściowego, a następnie umieszczenie znormalizowanego wyniku za pomocą zwykłej funkcji skrótu. W tym przykładzie funkcja normalizująca może porzucić wszystkie samogłoski, więc stanie definitesię dfnt. Słowo „znormalizowane” jest następnie hashowane za pomocą typowej funkcji skrótu.

Wstaw wszystkie słowa ze słownika do pomocniczego indeksu (tablicy skrótów) za pomocą tej specjalnej funkcji skrótu. Zasobniki w tej tabeli będą miały długie listy kolizji, ponieważ funkcja skrótu jest „zła”, ale te listy kolizji są zasadniczo wstępnie obliczonymi sugestiami.

Teraz, gdy znajdziesz błędnie napisane słowo, przeszukujesz listy kolizji dla zasobnika, do którego odwzorowuje błąd pisowni w indeksach pomocniczych. Ta da: Masz listę sugestii! Wszystko, co musisz zrobić, to uszeregować zawarte w nim słowa.

W praktyce będziesz potrzebować kilku pomocniczych indeksów z innymi funkcjami skrótu do obsługi innych typów błędów, takich jak transponowane litery, pojedyncza / podwójna litera, a nawet uproszczony, podobny do Soundexa, aby wychwycić błędy ortograficzne. W praktyce znalazłem uproszczone wymowy, które przeszły długą drogę i zasadniczo przestarzały niektóre z tych, które miały na celu znalezienie trywialnych literówek.

Więc teraz wyszukujesz błędy ortograficzne w każdym z indeksów pomocniczych i łączysz listy kolizji przed rankingiem.

Pamiętaj, że listy kolizji zawierają tylko słowa, które są w słowniku. Dzięki podejściom, które próbują generować alternatywną pisownię (jak w artykule Petera Norviga), możesz uzyskać (dziesiątki) tysięcy kandydatów, których najpierw musisz przefiltrować w słowniku. Dzięki wstępnie obliczonemu podejściu otrzymujesz może kilkaset kandydatów i wiesz, że wszystkie są poprawnie napisane, więc możesz przejść od razu do rankingu.

Aktualizacja : Od tego czasu znalazłem jeden opis algorytmu, który jest podobny do tego, Wyszukiwanie rozproszone FAROO . Wciąż jest to wyszukiwanie ograniczone do edycji, ale jest bardzo szybkie, ponieważ etap obliczeń wstępnych działa jak mój pomysł na „złe funkcje skrótu”. FAROO używa tylko ograniczonej koncepcji złej funkcji skrótu.

Adrian McCarthy
źródło
Dziękujemy za odwołanie się do algorytmu SymSpell firmy Faroos. Podczas gdy oba algorytmy wstępnie obliczają możliwe literówki i używają tablicy skrótów do szybkiego wyszukiwania, główną różnicą jest to, że SymSpell gwarantuje wykrycie wszystkich możliwych błędów ortograficznych do określonej odległości edycji (pod tym względem SymSpell jest odpowiednikiem algorytmu Petera Norviga, po prostu 3..6 rzędów wielkości szybciej), podczas gdy twój algorytm używa podejścia heurystycznego, które wykryje tylko ograniczony podzbiór wszystkich teoretycznie możliwych błędów ortograficznych (w związku z tym koszt wstępnych obliczeń może być niższy).
Wolf Garbe
Algorytm SymSpell wyraźnie wstępnie oblicza i przechowuje możliwe błędy, mój schemat „złego skrótu” tego nie robi. W przypadku języka angielskiego dodanie tylko jednego uproszczonego skrótu fonetycznego obejmującego wiele obszarów (np. „Terradacktle” -> „pterodactyl”, którego odległość edycji wynosi 6). Oczywiście, jeśli potrzebujesz wyszukiwania w wielu językach, może to być znacznie trudniejsze.
Adrian McCarthy
Oczywiście, wykorzystując wiedzę empiryczną na temat prawdopodobnych literówek (i ograniczając się do nich), oszczędzasz czas i przestrzeń przed obliczeniami. Jednak aby pokryć wszystkie możliwe błędy ortograficzne, SymSpell musi wstępnie obliczyć tylko niewielki ułamek z nich. 5-literowe słowo ma około 3 milionów możliwych błędów ortograficznych w maksymalnej odległości edycji 3, ale z SymSpell musisz wstępnie obliczyć i zapisać tylko 25 usunięć. Jest to ważne dla wyszukiwania rozmytego / podobieństwa poza korektą pisowni, gdzie nie istnieje żadna wiedza empiryczna.
Wolf Garbe
7

Algorytm

  1. Jako dane wejściowe weź błędnie napisane słowo.
  2. Przechowuj listę angielskich słów wraz z ich częstotliwościami w pliku tekstowym.
  3. Wstaw wszystkie dostępne angielskie słowa (zapisane w pliku tekstowym) wraz z ich częstotliwościami (miarą częstotliwości użycia danego słowa w języku angielskim) w trójskładnikowym drzewie wyszukiwania.
  4. Teraz przejdź wzdłuż potrójnego drzewa poszukiwań -
    • Dla każdego słowa napotkanego w trójskładnikowym drzewie wyszukiwania oblicz odległość Levensthein od źle napisanego słowa.
    • Jeśli odległość Levensthein <= 3, zapisz słowo w kolejce priorytetowej.
    • Jeśli dwa słowa mają tę samą odległość edycji, to o większej częstotliwości jest większe. Wydrukuj 10 najważniejszych pozycji z kolejki priorytetowej.

Optymalizacja

  1. Możesz usunąć słowa w poddrzewie bieżącego węzła, jeśli odległość edycji podciągu słowa wejściowego od bieżącego słowa jest większa niż 3.
    Bardziej szczegółowe wyjaśnienia i kod źródłowy można znaleźć w projekcie github .
amarjeetAnand
źródło
Hmm, odległość Levenshteina od „tarki” do „większego” w tym przypadku nie wystarczyłaby, ponieważ „tarka” jest również słowem słownikowym. ;-)
Tony Brasunas
1
@TonyBrasunas, Tak, masz rację. Ale program w rzeczywistości zwróci listę 10 słów w przypadku „tarki” jako dane wejściowe i zasugeruje „tarka” z odległością edycji równą 0, a także „większą” z odległością edycji równą 1. Co może być pomocne. ;)
amarjeetAnand
Jeśli jeden kandydat ma dystans 2, ale jest bardzo częsty, a inny kandydat ma dystans 1, ale jest niezwykle rzadki, jak oceniasz oba? W powyższym podejściu rzadki przedmiot zawsze wygrywa, czy to jest właściwy wynik?
szybowiec
@speedplane Tak. ten rzadki wygra. Myślę, że to dobry wynik. Ponieważ to, czego oczekujemy, jest najbliższym słowem, na podstawie pisowni słowa wejściowego. Jeśli nadal masz wątpliwości, pomyśl w ten sposób - przypuśćmy, że istnieje rzadkie słowo, które użytkownik napisał poprawnie. Teraz jego odległość wynosi 0, ale częstotliwość jest bardzo niska. Teraz w sugestiach powinniśmy wymienić to rzadkie słowo (z odległością 0) na górze (ponieważ najmniejsza edycja odległości wygrywa), a inne słowa z odległością 1-2-3 poniżej.
amarjeetAnand
3

Nie musisz znać dokładnej odległości edycji dla każdego słowa w słowniku. Możesz zatrzymać algorytm po osiągnięciu wartości granicznej i wykluczyć słowo. Pozwoli to zaoszczędzić dużo czasu na obliczeniach.

Petr Peller
źródło
1

Sprawdzanie pisowni jest bardzo łatwe do zaimplementowania, podobnie jak w programie do sprawdzania pisowni w systemie Unix. Kod źródłowy jest dostępny publicznie. Można wprowadzić korektę, jedną techniką jest dokonanie edycji i ponowne sprawdzenie, czy to nowe słowo jest w słowniku. Takie nowe zmiany można grupować i wyświetlać użytkownikowi.

System Unix wykorzystuje program napisany przez Mc IllRoy'a. Alternatywnym sposobem jest użycie Trie, co może być przydatne w przypadku dużych plików.

Podejście uniksowe wymaga bardzo mniej miejsca na ogromny słownik, ponieważ używa algorytmu mieszania rozproszonego.

Harisankar Krishna Swamy
źródło