Стемминг для нахождения слов- однофамильцев
Исключительную важность для обработки текста представляет приведение списка однородных слов в разных грамматических формах к одной - базовой. Это процедура называет стеммингом, и здесь я расскажу как ее осуществлять применительно к русскому языку.
Зачем вообще нужен стемминг? При анализе текстов ключевой характеристикой является частота встречаемости слов. С учетом этого для повышения объективности выводов целесообразно такие слова, как, например, "политик", "политику", "политика" считать одним. Если их не привести к базовой форме, они будут трактоваться в качестве разных единиц и, соответственно, результаты работы будут искажены.
Начнем с быстрого и простого, но не самого правильного пути. Так, для наших целей можно использовать класс SnowballStemmer из модуля nltk.stem. Вся процедура в этом случае будет сведена к созданию его экземпляра путем передачи предпочитаемого языка, а затем вызову метода stem, получающему на входе конкретное слово. Продемонстрируем это на практике:
Как можно убедиться, данный инструмент для словоформ слова "политик" подобрал неплохую базовую форму, а для второго слова - ничего не значащую ( "сказа").
Таким образом, при финальной интерпретации результатов придется только догадываться, что означают некоторые базовые формы. Кроме того, зачастую они могут совпадать даже для разных слов:
В этих условиях можно пойти другим, более медленным и надежным путем. Например, скачав словарь базовых и грамматических форм (мне удалось найти такой на просторах Интернета), искать строку, в которой встречается целевое слово и заменять его на базовое (в оригинале базовое слово отделялось вертикальной линией "|", а словоформы друг от друга двоеточием). При этом простой поиск заданного слова по всем строкам происходит достаточно медленно.
Для ускорения процедуры я использовал вышеописанный стеммер. Так, я добавил к каждой строке краткую форму слова, возвращаемую этим стеммером, отделив ее еще одной вертикальной линией. В результате мой словарь приобрел следующий вид:
Имея данный словарь, поиск базовой формы слова я произвожу следующим образом. Сначала я считываю данный файл в объект Pandas DataFrame, и в качестве индекса устанавливаю "простемленные" версии слов (в получившемся DataFrame под названием dict_stem колонка "инфинитив" обозначает базовую форму):
Затем я пропускаю целевое слово через стеммер и ищу в индексе DataFrame совпадения. После их нахождения (если нет, то оставляем слово как есть) производится поиск полной формы искомого слова в результирующем наборе и в случае успеха возвращается базовая форма из той же строки.
Например, найдем таким способом базовую версию слова "здоровья":
Как видим, результат работы такой стратегии более надежный, чем в первом случае (выделенное слово - "здоровье"). Однако за это мы расплачиваемся скоростью работы. Если есть предложения по улучшению алгоритма, в частности ускорению его работы, делитесь в комментариях.