Простой NLP на Python с TextBlob: Лемматизация

TextBlob — это пакет, построенный поверх двух других пакетов, один из них называется Natural Language Toolkit, известный в основном в сокращенной форме как NLTK , а другой — Pattern. NLTK — это традиционный пакет, используемый для обработки текста или обработки естественного языка (NLP) , а Pattern создан в основном для веб-майнинга. TextBlob спроектирован так, чтобы его было легче изучать и манипулировать, чем NLTK, при этом поддерживая те же важные задачи NLP, такие как лемматизация, анализ тональности, выделение корней, POS-теги, извлечение именной фразы, классификация, перевод и многое другое.

Кроме того, если у вас нет под рукой текстовой информации, TextBlob предоставляет необходимые наборы языковых данных (обычно текстов), называемые корпусами , из базы данных NLTK.

Установка TextBlob

Начнем с установки TextBlob. Если вы используете терминал, командную строку или командную строку, вы можете ввести:

$ pip install textblob

В противном случае, если вы используете блокнот Jupyter, вы можете выполнить команду прямо из блокнота, добавив восклицательный знак !в начале инструкции:

!pip install textblob

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

После установки TextBlob, чтобы иметь текстовые примеры, вы можете скачать корпуса, выполнив команду python -m textblob.download_corpora. Опять же, вы можете выполнить его прямо в командной строке или в блокноте, поставив перед ним восклицательный знак.

При выполнении команды вы должны увидеть вывод ниже:

$ python -m textblob.download_corpora
[nltk_data] Downloading package brown to /Users/csamp/nltk_data...
[nltk_data]   Package brown is already up-to-date!
[nltk_data] Downloading package punkt to /Users/csamp/nltk_data...
[nltk_data]   Package punkt is already up-to-date!
[nltk_data] Downloading package wordnet to /Users/csamp/nltk_data...
[nltk_data]   Package wordnet is already up-to-date!
[nltk_data] Downloading package averaged_perceptron_tagger to
[nltk_data]     /Users/csamp/nltk_data...
[nltk_data]   Package averaged_perceptron_tagger is already up-to-
[nltk_data]       date!
[nltk_data] Downloading package conll2000 to /Users/csamp/nltk_data...
[nltk_data]   Unzipping corpora/conll2000.zip.
[nltk_data] Downloading package movie_reviews to
[nltk_data]     /Users/csamp/nltk_data...
[nltk_data]   Unzipping corpora/movie_reviews.zip.
Finished.

Мы уже установили пакет TextBlob и его корпуса. Теперь давайте больше разберемся в лемматизации.

Что такое лемматизация?

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

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

Лемма - это слово, которое вы бы искали в словаре. Например, если вы хотите посмотреть определение глагола «бежать», вы должны искать «бежать».

Основа - это часть слова, которая никогда не изменяется.

Что такое лемматизация?

Лемматизация — это процесс получения лемм слов из корпуса.

Иллюстрацией этого может быть следующее предложение:

  • Входные данные (корпус): Алиса думает, что заблудилась, но затем начинает находить себя.
  • Вывод (леммы): | Алиса | думать | она | есть | потерял | но | затем | начать | к | найти | сама |

Обратите внимание, что каждое слово во входном предложении лемматизировано в соответствии с его контекстом в исходном предложении. Например, «Алиса» — это имя собственное, поэтому оно остается прежним, а глаголы «думает» и «начинает» упоминаются в их основных формах «думать» и «начинать».

Лемматизация — один из основных этапов языковой обработки. Он приводит слова к их корневым формам или леммам , которые мы бы нашли, если бы искали их в словаре.

В случае TextBlob лемматизация основана на базе данных WordNet , которая разрабатывается и поддерживается Принстонским университетом. В фоновом режиме TextBlob использует процессор преобразования WordNet для получения леммы для слова.

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

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

Реализация лемматизации в коде

Прежде всего, необходимо установить объект TextBlob и определить образец корпуса, который будет лемматизирован позже. На этом начальном этапе вы можете либо написать, либо определить строку текста для использования, или мы можем использовать пример из загруженного нами корпуса NLTK. Пойдем с последним.

Выбор обзора из корпуса NLTK

Например, попробуем получить леммы для рецензии на фильм, которая есть в корпусе. Для этого мы импортируем как библиотеку TextBlob, так и movie_reviewsиз nltk.corpusпакета:

# importing necessary libraries
from textblob import TextBlob
from nltk.corpus import movie_reviews

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

movie_reviews.fileids()

Это вернет список из 2000 имен текстовых файлов, содержащих отрицательные и положительные отзывы:

['neg/cv000_29416.txt',
 'neg/cv001_19502.txt',
 'neg/cv002_17424.txt',
 'neg/cv003_12683.txt',
 'neg/cv004_12641.txt',
 'neg/cv005_29357.txt',
 'neg/cv006_17022.txt',
 'neg/cv007_4992.txt',
 'neg/cv008_29326.txt',
 'neg/cv009_29417.txt',
 ...]
Примечание : Если вы запускаете код другим способом, например, в терминале или IDE, вы можете распечатать ответ, выполнив print(movie_reviews.fileids()).

Глядя на минус в названии файла, можно предположить, что список начинается с отрицательных отзывов и заканчивается положительными. Мы можем посмотреть на положительный отзыв, проведя индексацию с конца списка. Здесь мы выбираем 1989-й отзыв:

movie_reviews.fileids()[-10]

Это приводит к:

'pos/cv990_11591.txt'

Чтобы изучить предложения обзора, мы можем передать имя обзора методу .sents(), который выводит список всех предложений обзора:

movie_reviews.sents('pos/cv990_11591.txt')
[['the', 'relaxed', 'dude', 'rides', 'a', 'roller', 'coaster',
'the', 'big', 'lebowski', 'a', 'film', 'review', 'by', 'michael',
'redman', 'copyright', '1998', 'by', 'michael', 'redman', 'the',
'most', 'surreal', 'situations', 'are', 'ordinary', 'everyday',
'life', 'as', 'viewed', 'by', 'an', 'outsider', '.'], ['when',
'those', 'observers', 'are', 'joel', 'and', 'ethan', 'coen', ',',
'the', 'surreal', 'becomes', 'bizarre', '.'], ...]

Давайте сохраним этот список в переменной с именем pos_review:

pos_review = movie_reviews.sents("pos/cv990_11591.txt")
len(pos_review) #returns 63

Здесь мы видим, что есть 63 предложения. Теперь мы можем выбрать одно предложение для лемматизации, например, 15-е предложение:

sentence = pos_review[16]
type(sentence) # returns list

Создание объекта TextBlob

После выбора предложения нам нужно создать объект TextBlob, чтобы получить доступ к .lemmatize()методу. Объекты TextBlob необходимо создавать из строк. Так как у нас есть список, мы можем преобразовать его в строку с помощью string.join()метода соединения на основе пробелов:

sentence_string = ' '.join(sentence)

Теперь, когда у нас есть строка предложения, мы можем передать ее конструктору TextBlob:

blob_object = TextBlob(sentence_string)

Получив объект TextBlob, мы можем выполнять различные операции, например лемматизацию.

Лемматизация предложения

Наконец, чтобы получить лемматизированные слова, мы просто получаем wordsатрибут созданного blob_object. Это дает нам список, содержащий объекты Word, которые ведут себя очень похоже на строковые объекты:

# Word tokenization of the sentence corpus
corpus_words = blob_object.words
# To see all tokens
print('sentence:', corpus_words)
# To count the number of tokens
number_of_tokens = len(corpus_words)
print('\nnumber of tokens:', number_of_tokens)

Выходные команды должны дать вам следующее:

sentence: ['the', 'carpet', 'is', 'important', 'to', 'him', 'because', 'it', 'pulls', 'the', 'room', 'together', 'not', 'surprisingly', 'since', 'it', 's', 'virtually', 'the', 'only', 'object', 'there']

number of tokens: 22

Чтобы лемматизировать слова, мы можем просто использовать .lemmatize()метод:

corpus_words.lemmatize()

Это дает нам лемматизированный объект WordList:

WordList(['the', 'carpet', 'is', 'important', 'to', 'him', 'because', 'it', 'pull', 'the',
'room', 'together', 'not', 'surprisingly', 'since', 'it', 's', 'virtually', 'the', 'only',
'object', 'there'])

Так как это может быть немного сложно читать, мы можем сделать цикл и вывести каждое слово до и после лемматизации:

for word in corpus_words:
    print(f'{word} | {word.lemmatize()}')

Это приводит к:

the | the
carpet | carpet
is | is
important | important
to | to
him | him
because | because
it | it
pulls | pull
the | the
room | room
together | together
not | not
surprisingly | surprisingly
since | since
it | it
s | s
virtually | virtually
the | the
only | only
object | object
there | there

Обратите внимание, как «вытягивание» изменилось на «вытягивание»; другие слова, кроме «это», также были лемматизированы, как и ожидалось. Мы также можем видеть, что «это» было отделено из-за апострофа. Это указывает на то, что мы можем дополнительно предварительно обработать предложение, чтобы «это» считалось словом, а не «это» и «с».

Разница между лемматизацией и стеммингом

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

Давайте быстро изменим наш цикл for, чтобы увидеть эти различия:

print('word | lemma | stem\n')
for word in corpus_words:
    print(f'{word} | {word.lemmatize()} | {word.stem()}')

Это выводит:

the | the | the
carpet | carpet | carpet
is | is | is
important | important | import
to | to | to
him | him | him
because | because | becaus
it | it | it
pulls | pull | pull
the | the | the
room | room | room
together | together | togeth
not | not | not
surprisingly | surprisingly | surprisingli
since | since | sinc
it | it | it
s | s | s
virtually | virtually | virtual
the | the | the
only | only | onli
object | object | object
there | there | there

Глядя на приведенный выше вывод, мы видим, насколько проблематичным может быть поиск корней. Он сводит «важный» к «импортировать», теряя весь смысл слова, которое теперь даже можно считать глаголом; «потому что» на «потому что», слова, которого не существует, то же самое для «вместе», «удивительно», «синк», «онли».

Существуют четкие различия между лемматизацией и стеммингом. Ключевым моментом является понимание того, когда использовать каждую технику. Предположим, вы оптимизируете поиск слов, и основное внимание уделяется возможности предложить максимальное количество похожих слов, какой метод вы бы использовали? Когда контекст слова не имеет значения, и мы можем получить «важный» с помощью «импортировать», очевидный выбор — корень. С другой стороны, если вы работаете над сравнением текста документа, в котором положение слов в предложении имеет значение, а контекст «важность» необходимо сохранить и не путать с глаголом «импортировать», лучшим выбором будет лемматизация.

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

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

Лемматизация обзора

Чтобы лемматизировать весь обзор, нам нужно только изменить файл .join(). Вместо того, чтобы соединять слова в предложение, мы будем соединять предложения в обзоре:

# joining each sentence with a new line between them, and a space between each word
corpus_words = '\n'.join(' '.join(sentence) for sentence in pos_review)

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

blob_object = TextBlob(pos_rev)
corpus_words = blob_object.words
corpus_words.lemmatize()

Это генерирует объект WordList с лемматизированным полным текстом обзора. Здесь мы опускаем некоторые части с многоточием, (...)так как обзор большой, но вы сможете увидеть его в цельном виде. Мы можем найти наше предложение в середине:

WordList(['the', 'relaxed', 'dude', 'rides', 'a', 'roller', 'coaster', 'the', 'big',
'lebowski', 'a', 'film', 'review', 'by', 'michael', 'redman', 'copyright', '1998', 'by',
'michael', 'redman', 'the', 'most', 'surreal', 'situations', 'are', 'ordinary', 'everyday',
'life', 'as', 'viewed', 'by', 'an', 'outsider', 'when', 'those', 'observers', 'are', 'joel',
(...) 

'the', 'carpet', 'is', 'important', 'to', 'him', 'because', 'it', 'pulls', 'the', 'room',
'together', 'not', 'surprisingly', 'since', 'it', 's', 'virtually', 'the', 'only', 'object',
'there'

(...)
'com', 'is', 'the', 'eaddress', 'for', 'estuff'])

Заключение

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

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

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

Есть много способов выполнить лемматизацию, и TextBlob — отличная библиотека для начала работы с НЛП. Он предлагает простой API, который позволяет пользователям быстро начать работу над задачами НЛП. Оставьте комментарий, если вы использовали лемматизацию в проекте или планируете ее использовать.