Предобработка текста в NLP

В предыдущий раз мы говорили о векторизации текстовых данных в NLP. Однако прежде чем преобразовать слова в числа, их следует обработать. Читайте в нашей статье о методах предобработки текста: токенизации, удалении стоп-слов, стемминге и лемматизации с Python-библиотеками pymorphy2 и NLTK.

Разбиваем текст на токены

Токенизация – процесс разбиения текста на текстовые единицы, например, слова или предложения. В случае разбиений на предложения задача кажется тривиальной, нужно просто найти точку, вопросительный или восклицательный знак. Но в русском языке существует сокращения, в которых есть точка, например, к.т.н. — кандидат технических наук или т.е. — то есть. Поэтому такой путь может привести к ошибкам. К счастью, Python-библиотека NLTK позволяет избежать этой проблемы. Рассмотрим пример:

>>> from nltk.tokenize import sent_tokenize
>>> text = "Я - к.т.н, т.е. проучился долгое время. Имею образование."
>>> sent_tokenize(text, language="russian")
['Я - к.т.н, т.е. проучился долгое время.', 'Имею образование.']

Как видим, функция sent_tokenize разбила исходное предложения на два, несмотря на присутствие слов к.т.н. и т.е.

Помимо разбиения на предложения в NLTK можно в качестве токенов использовать слова:

>>> from nltk.tokenize import sent_tokenize, word_tokenize
>>> text = "Я - к.т.н. Сижу на диван-кровати."
>>> word_tokenize(text, language="russian")
['Я', '-', 'к.т.н.', 'Сижу', 'на', 'диван-кровати', '.']

Здесь к.т.н. и диван-кровать были определены как отдельные слова.

Исключаем стоп-слова из исходного текста

Иногда одних слов в тексте больше, чем других, к тому же они встречаются почти в каждом предложении и не несут большой информативной нагрузки. Такие слова являются шумом для последующего глубокого обучения (Deep Learning) и называются стоп-словами. Библиотека NLTK также имеет список стоп-слов, который предварительно необходимо скачать. Это можно сделать следующим образом:

>>> import nltk
>>> nltk.download('stopwords')

После этого доступен список стоп-слов для русского языка:

>>> from nltk.corpus import stopwords
>>> stopwords.words("russian")

Всего их насчитывается в этом списке 151. Вот некоторые из них:

и, в, во, не, что, он, на, я, с, со, как, а, то, все, чтоб, без, будто, впрочем, хорошо, свою, этой, перед, иногда, лучше, чуть, том, нельзя, такой, им, более, всегда, конечно, всю, между

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

for token in tokens:
    if token not in stop_words:
        filtered_tokens.append(token)

Стемминг: удаляем окончания

Русский язык обладает богатой морфологической структурой. Слово хороший и хорошая имеют тот же смысл, но разную форму, например, хорошая мебель и хороший стул. Поэтому для машинного обучения (Machine Learning) лучше привести их к одной форме для уменьшения размерности. Одним из таких методов является стемминг (stemming). В частности, он опускает окончания слова. В Python-библиотеке NLTK для этого есть Snowball Stemmer, который поддерживает русский язык:

>>> from nltk.stem import SnowballStemmer
...
>>> snowball = SnowballStemmer(language="russian")
>>> snowball.stem("Хороший")
хорош
>>> snowball.stem("Хорошая")
хорош

Проблемы могут возникнуть со словами, которые значительно изменяются в других формах:

>>> snowball.stem("Хочу")
хоч
>>> snowball.stem("Хотеть")
хотет

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

Приведение к начальной форме с лемматизацией

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

Рассмотрим пример для слова “хочу”:

>>> import pymorphy2
>>> morph = pymorphy2.MorphAnalyzer()
>>> morph.parse("хочу")
[Parse(word='хочу', tag=OpencorporaTag('VERB,impf,tran sing,1per,pres,indc'), normal_form='хотеть', score=1.0, methods_stack=((<DictionaryAnalyzer>, 'хочу', 2999, 1),))]

Метод parse возвращает список объектов Parse, которые обозначают виды грамматических форм анализируемого слова. Такой объект обладает следующими атрибутами:

  • tag обозначает набор граммем. В данном случае слово хочу — это глагол (VERB) несовершенного вида (impf), переходный (tran), единственного числа (sing), 1 лица (1per), настоящего времени (pres), изъявительного наклонения (indc);
  • normal_form— нормального форма слова;
  • score — оценка вероятности того, что данный разбор правильный;
  • methods_stack — тип словаря распарсенного слова с его индексом.

Нас больше всего интересует нормальная форма слова. По умолчанию объекты Parse сортированы в порядке убывания значения score. Поэтому из списка лучше всего брать 1-й элемент:

>>> morph.parse("хотеть")[0].normal_form
хотеть
>>> morph.parse("хочу")[0].normal_form
хотеть
>>> morph.parse("хотят")[0].normal_form
хотеть

Таким образом, мы получили одно слово из разных его форм.

 

Как обрабатывать текстовые данные и применять их в реальных проектах Data Science для моделей Machine Learning с помощью Python, вы узнаете на наших курсах в лицензированном учебном центре обучения и повышения квалификации ИТ-специалистов в Москве.

Добавить комментарий

Поиск по сайту