Какой алгоритм дает предложения при проверке орфографии?

114

Какой алгоритм обычно используется при реализации средства проверки правописания, которое сопровождается предложениями слов?

Сначала я подумал, что имеет смысл проверять каждое новое введенное слово (если оно не найдено в словаре) на расстояние Левенштейна от каждого другого слова в словаре и возвращать лучшие результаты. Однако это кажется крайне неэффективным, если придется многократно оценивать весь словарь.

Как это обычно делается?

Mithrax
источник

Ответы:

203

Есть хорошее эссе Питера Норвига, как реализовать корректор орфографии. По сути, это метод грубой силы, пробующий строки-кандидаты с заданным расстоянием редактирования. ( Вот несколько советов, как повысить производительность корректора орфографии с помощью фильтра Блума и более быстрого хеширования кандидатов .)

Требования для проверки орфографии слабее. Вам нужно только узнать, что слова нет в словаре. Вы можете использовать фильтр Блума для создания средства проверки орфографии, которое потребляет меньше памяти. Древняя версия описана в Programming Pearls Джона Бентли с использованием 64 КБ для английского словаря.

BK-дерево представляет собой альтернативный подход. Хорошая статья здесь .

Расстояние Левенштейна - не совсем правильное расстояние редактирования для средства проверки орфографии. Он знает только вставку, удаление и замену. Транспонирование отсутствует и дает 2 для транспонирования 1 символа (это 1 удаление и 1 вставка). Расстояние Дамерау – Левенштейна - это правильное расстояние редактирования.

Томас Юнг
источник
2
+1 за относительно неизвестную ссылку на BK-Tree. Так поступают такие компании, как Google, работающие с объемом данных в реальном мире [TM].
NoozNooz42
2
Существует гораздо лучшее объяснение БК-деревьев здесь .
Ian Boyd
17

Подход к генерации предложений, который я успешно использовал, но нигде не встречал описанного, - это предварительное вычисление предложений (при построении словаря) с использованием «плохих» хэш-функций.

Идея состоит в том, чтобы посмотреть на типы орфографических ошибок, которые делают люди, и разработать хэш-функции, которые будут назначать неправильное написание тому же сегменту, что и его правильное написание.

Например, распространенной ошибкой является использование неправильной гласной, например, определения вместо определенного . Итак, вы создаете хеш-функцию, которая обрабатывает все гласные как одну и ту же букву. Самый простой способ сделать это - сначала «нормализовать» входное слово, а затем передать нормализованный результат через обычную хеш-функцию. В этом примере функция нормализации может отбросить все гласные, поэтому definiteстановится dfnt. Затем "нормализованное" слово хешируется с помощью типичной хеш-функции.

Вставьте все свои словарные слова во вспомогательный индекс (хеш-таблицу) с помощью этой специальной хеш-функции. У сегментов в этой таблице будут длинные списки конфликтов, потому что хеш-функция «плохая», но эти списки конфликтов по сути являются предварительно вычисленными предложениями.

Теперь, когда вы обнаруживаете слово с ошибкой, вы просматриваете списки конфликтов для сегмента, которому оно соответствует во вспомогательных индексах. Ta da: У вас есть список предложений! Все, что вам нужно сделать, это ранжировать слова на нем.

На практике вам понадобится несколько вспомогательных индексов с другими хэш-функциями для обработки других типов ошибок, таких как транспонированные буквы, одинарные / двойные буквы и даже упрощенный Soundex-подобный индекс для обнаружения фонетических орфографических ошибок. На практике я обнаружил, что упрощенные варианты произношения имеют большое значение и существенно устарели некоторые из них, предназначенные для поиска тривиальных опечаток.

Итак, теперь вы ищите орфографические ошибки в каждом из вспомогательных индексов и объединяете списки конфликтов перед ранжированием.

Помните, что списки конфликтов содержат только слова, которые есть в словаре. С помощью подходов, которые пытаются генерировать альтернативные варианты написания (как в статье Питера Норвига), вы можете получить (десятки) тысяч кандидатов, которых вам сначала нужно отфильтровать по словарю. При использовании заранее рассчитанного подхода у вас может быть пара сотен кандидатов, и вы знаете, что все они написаны правильно, поэтому вы можете сразу перейти к ранжированию.

Обновление : с тех пор я нашел одно описание алгоритма, похожее на это, распределенный поиск FAROO . Это все еще поиск с ограниченным расстоянием редактирования, но он очень быстрый, потому что этап предварительного вычисления работает как моя идея о «плохих хэш-функциях». FAROO просто использует ограниченную концепцию плохой хеш-функции.

Адриан Маккарти
источник
Спасибо за ссылку на алгоритм Фаруса SymSpell. Хотя оба алгоритма предварительно вычисляют возможные опечатки и используют хеш-таблицу для быстрого поиска, главное отличие состоит в том, что SymSpell гарантирует обнаружение всех возможных орфографических ошибок до определенного расстояния редактирования (в этом отношении SymSpell эквивалентен алгоритму Питера Норвига, просто На 3..6 порядков быстрее), в то время как ваш алгоритм использует эвристический подход, который обнаруживает только ограниченное подмножество всех теоретически возможных орфографических ошибок (поэтому ваши предварительные расчеты могут быть ниже).
Wolf Garbe
Алгоритм SymSpell явно предварительно вычисляет и сохраняет возможные опечатки, в отличие от моей схемы "плохого хеширования". Для английского языка тривиально добавить только один упрощенный фонетический хеш, охватывающий множество вопросов (например, «terradacktle» -> «pterodactyl», у которого расстояние редактирования равно 6). Конечно, если вам нужен многоязычный поиск, это может быть намного сложнее.
Адриан Маккарти,
Безусловно, используя эмпирические знания о вероятных опечатках (и ограничивая их), вы экономите время и место перед расчетами. Но чтобы охватить все возможные орфографические ошибки, SymSpell необходимо предварительно вычислить лишь крошечную их часть. Слово из 5 букв имеет около 3 миллионов возможных орфографических ошибок в пределах максимального расстояния редактирования 3, но с SymSpell вам нужно предварительно рассчитать и сохранить только 25 удалений. Это важно для нечеткого поиска / поиска сходства, помимо исправления орфографии, когда нет эмпирических знаний.
Wolf Garbe
7

Алгоритм

  1. Возьмите неправильно написанное слово в качестве ввода.
  2. Сохраните список английских слов с указанием их частот в текстовом файле.
  3. Вставьте все доступные английские слова (хранящиеся в текстовом файле) вместе с их частотами (мера того, как часто слово используется в английском языке) в троичное дерево поиска.
  4. Теперь пройдитесь по троичному дереву поиска -
    • Для каждого слова, встречающегося в троичном дереве поиска, вычислите его расстояние Левенштейна от неправильно написанного слова.
    • Если Levensthein Distance <= 3, сохранить слово в очереди приоритета.
    • Если два слова имеют одинаковое расстояние редактирования, то слово с более высокой частотой считается более важным. Распечатайте 10 первых элементов из очереди приоритета.

оптимизация

  1. Вы можете удалить слова в поддереве текущего узла, если расстояние редактирования подстроки входного слова от текущего слова больше, чем 3.
    Вы можете найти более подробное объяснение и исходный код в проекте github .
amarjeetAnand
источник
Хм, расстояния Левенштейна от «терки» до «большего» в данном случае было бы недостаточно, поскольку «терка» тоже словарное слово. ;-)
Тони Брасунас 07
1
@TonyBrasunas, да ты прав. Но программа фактически вернет список из 10 слов в случае ввода «терка» и предложит «терку» с расстоянием редактирования 0, а также «больше» с расстоянием редактирования, равным 1. Что может быть полезно. ;)
amarjeetAnand 08
Если один кандидат имеет расстояние 2, но встречается очень часто, а другой кандидат имеет расстояние 1, но встречается крайне редко, как вы оцениваете этих двух? При описанном выше подходе всегда выигрывает редкий предмет, правильный ли это результат?
скоростной самолет
@speedplane Да. редкий победит. И я считаю, что это правильный результат. Поскольку мы ожидаем, что это самое близкое слово, основанное на написании входного слова. Если вы все еще сомневаетесь, подумайте так - предположим, есть редкое слово, которое пользователь написал правильно. Теперь его расстояние равно 0, но частота очень низкая. Теперь в предложениях мы должны перечислить это редкое слово (с расстоянием 0) вверху (потому что наименьшее расстояние редактирования лучше), а другие слова с расстоянием 1-2-3 ниже.
amarjeetAnand
3

Вам не нужно знать точное расстояние редактирования для каждого слова в словаре. Вы можете остановить алгоритм после достижения предельного значения и исключить слово. Это сэкономит вам много вычислительного времени.

Петр Пеллер
источник
1

Проверка орфографии очень проста в реализации, как и в программе проверки орфографии Unix. Исходный код общедоступен. Может быть задействовано исправление, один из способов - внести правки и снова проверить, есть ли это новое слово в словаре. Такие новые правки можно сгруппировать и показать пользователю.

В системе Unix используется программа, написанная Мак Иллроем. Альтернативный способ - использовать Trie, который может быть полезен в случае больших файлов.

Подход unix требует очень мало места для огромного словаря, поскольку он использует алгоритм хеширования разброса.

Харисанкар Кришна Свами
источник