машинное обучение
February 9, 2021

Стемминг для нахождения слов- однофамильцев

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

Зачем  вообще нужен стемминг? При анализе текстов ключевой характеристикой  является частота встречаемости слов. С учетом этого для повышения  объективности выводов целесообразно такие слова, как, например,  "политик", "политику", "политика" считать одним.  Если их не привести к  базовой форме, они будут трактоваться в качестве разных единиц и,  соответственно, результаты работы будут искажены.

Начнем с быстрого и простого, но не самого правильного пути. Так, для наших целей можно использовать класс SnowballStemmer из модуля nltk.stem.  Вся процедура в этом случае будет сведена к созданию его экземпляра  путем передачи предпочитаемого языка, а затем вызову метода stem, получающему на входе конкретное слово. Продемонстрируем это на практике:

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

Таким  образом, при финальной интерпретации результатов придется только  догадываться, что означают некоторые базовые формы. Кроме того, зачастую  они могут совпадать даже для разных слов:

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

Для  ускорения процедуры я использовал вышеописанный стеммер. Так, я добавил  к каждой строке краткую форму слова, возвращаемую этим стеммером,  отделив ее еще одной вертикальной линией. В результате мой словарь  приобрел следующий вид:

Имея данный словарь,  поиск базовой формы слова я произвожу следующим образом. Сначала я считываю данный файл в объект Pandas DataFrame, и в качестве индекса устанавливаю "простемленные" версии слов (в получившемся DataFrame  под названием dict_stem колонка "инфинитив" обозначает базовую форму):

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

Например, найдем таким способом базовую версию слова "здоровья":

Как  видим, результат работы такой стратегии более надежный, чем в первом  случае (выделенное слово - "здоровье"). Однако за это мы расплачиваемся  скоростью работы. Если есть предложения по улучшению алгоритма, в  частности ускорению его работы,  делитесь в комментариях.