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


114

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

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

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

Ответы:


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 .

Хм, расстояния Левенштейна от «терки» до «большего» в данном случае было бы недостаточно, поскольку «терка» тоже словарное слово. ;-)
— Тони Брасунас 07

1
@TonyBrasunas, да ты прав. Но программа фактически вернет список из 10 слов в случае ввода «терка» и предложит «терку» с расстоянием редактирования 0, а также «больше» с расстоянием редактирования, равным 1. Что может быть полезно. ;)
— amarjeetAnand 08

Если один кандидат имеет расстояние 2, но встречается очень часто, а другой кандидат имеет расстояние 1, но встречается крайне редко, как вы оцениваете этих двух? При описанном выше подходе всегда выигрывает редкий предмет, правильный ли это результат?
— скоростной самолет

@speedplane Да. редкий победит. И я считаю, что это правильный результат. Поскольку мы ожидаем, что это самое близкое слово, основанное на написании входного слова. Если вы все еще сомневаетесь, подумайте так - предположим, есть редкое слово, которое пользователь написал правильно. Теперь его расстояние равно 0, но частота очень низкая. Теперь в предложениях мы должны перечислить это редкое слово (с расстоянием 0) вверху (потому что наименьшее расстояние редактирования лучше), а другие слова с расстоянием 1-2-3 ниже.
— amarjeetAnand

3

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


1

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

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.