Рубрики
Без рубрики

Python для НЛП: Токенизация, Стемминг и лемматизация с помощью библиотеки SpaCy

Автор оригинала: Usman Malik.

В предыдущей статье мы начали обсуждение того , как обрабатывать естественный язык с помощью Python. Мы видели, как читать и писать текстовые и PDF-файлы. В этой статье мы начнем работать с библиотекой space для выполнения еще нескольких базовых задач НЛП, таких как токенизация , стемминг и лемматизация .

Введение в космос

Космическая библиотека является одной из самых популярных библиотек НЛП наряду с НЛТК. Основное различие между этими двумя библиотеками заключается в том, что NLTK содержит большое разнообразие алгоритмов для решения одной задачи, в то время как spaCy содержит только один, но лучший алгоритм для решения задачи.

NLTK был выпущен еще в 2001 году, в то время как space является относительно новым и был разработан в 2015 году. В этой серии статей по НЛП мы будем в основном иметь дело с пространством, в силу его современной природы. Однако мы также коснемся NLTK, когда легче выполнить задачу с помощью NLTK, а не пространства.

Установка пространства

Если вы используете установщик pip для установки библиотек Python, перейдите в командную строку и выполните следующую инструкцию:

$ pip install -U spacy

В противном случае, если вы используете Anaconda, вам необходимо выполнить следующую команду в командной строке Anaconda:

$ conda install -c conda-forge spacy

После загрузки и установки space следующим шагом будет загрузка языковой модели. Мы будем использовать модель английского языка. Языковая модель используется для выполнения различных задач НЛП, которые мы увидим в следующем разделе.

Следующая команда загружает языковую модель:

$ python -m spacy download en

Основные Функциональные возможности

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

В качестве первого шага вам нужно импортировать библиотеку space следующим образом:

import spacy

Далее нам нужно загрузить модель языка пространства.

sp = spacy.load('en_core_web_sm')

В приведенном выше сценарии мы используем функцию load из библиотеки space для загрузки основной модели английского языка. Модель хранится в переменной sp .

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

sentence = sp(u'Manchester United is looking to sign a forward for $90 million')

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

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

for word in sentence:
    print(word.text)

Вывод приведенного выше скрипта выглядит следующим образом:

Manchester
United
is
looking
to
sign
a
forward
for
$
90
million

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

for word in sentence:
    print(word.text,  word.pos_)

Выход:

Manchester PROPN
United PROPN
is VERB
looking VERB
to PART
sign VERB
a DET
forward NOUN
for ADP
$ SYM
90 NUM
million NUM

Вы можете видеть, что каждому слову или знаку в нашем предложении была присвоена часть речи. Например,” Манчестер “был помечен как имя собственное,” Смотреть ” – как глагол и так далее.

Наконец, в дополнение к частям речи мы также можем видеть зависимости.

Давайте создадим еще один документ:

sentence2 = sp(u"Manchester United isn't looking to sign any forward.")

Для анализа зависимостей используется атрибут dep_ , как показано ниже:

for word in sentence2:
    print(word.text,  word.pos_, word.dep_)

Вывод выглядит следующим образом:

Manchester PROPN compound
United PROPN nsubj
is VERB aux
n't ADV neg
looking VERB ROOT
to PART aux
sign VERB xcomp
any DET advmod
forward ADV advmod
. PUNCT punct

Из выходных данных вы можете видеть, что пространство достаточно разумно, чтобы найти зависимость между токенами, например, в предложении у нас было слово is'nt . Синтаксический анализатор зависимостей разбил его на два слова и указывает, что n't на самом деле является отрицанием предыдущего слова.

Для получения подробного понимания синтаксического анализа зависимостей обратитесь к этой статье .

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

document = sp(u'Hello from Stackabuse. The site with the best Python Tutorials. What are you looking for?')

Теперь мы можем повторить каждое предложение, используя следующий сценарий:

for sentence in document.sents:
    print(sentence)

Вывод скрипта выглядит следующим образом:

Hello from Stackabuse.
The site with the best Python Tutorials.
What are you looking for?

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

document[4]

В приведенном выше сценарии мы ищем 5-е слово в документе. Имейте в виду, что индекс начинается с нуля, а период считается токеном. В выводе вы должны увидеть:

The

Теперь посмотрим, начинается ли какое-либо предложение в документе с , мы можем использовать атрибут is_sent_start , как показано ниже:

document[4].is_sent_start

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

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

Токенизация

Как объяснялось ранее, токенизация-это процесс разбиения документа на слова, знаки препинания, цифры и т. Д.

Давайте подробно рассмотрим маркировку пространства. Создайте новый документ с помощью следующего сценария:

sentence3 = sp(u'"They\'re leaving U.K. for U.S.A."')
print(sentence3)

Вы можете видеть, что предложение содержит кавычки в начале и в конце. Он также содержит знаки препинания в аббревиатурах “U. K” и “U. S. A.”

Давайте посмотрим, как Спейси маркирует это предложение.

for word in sentence3:
    print(word.text)

Выход:

"
They
're
leaving
U.K.
for
U.S.A.
"

В выходных данных вы можете видеть, что пробел маркировал начальные и конечные двойные кавычки. Однако он достаточно умен, чтобы не маркировать точку препинания, используемую между аббревиатурами, такими как Великобритания и США.

Давайте рассмотрим еще один пример токенизации:

sentence4 = sp(u"Hello, I am non-vegetarian, email me the menu at [email protected]")
print(sentence4)

Здесь, в приведенном выше предложении, у нас есть тире в слове “невегетарианский” и в адресе электронной почты. Давайте посмотрим, как пространство будет маркировать это:

for word in sentence4:
    print(word.text)

Выход:

Hello
,
I
am
non
-
vegetarian
,
email
me
the
menu
at
[email protected]

Из выходных данных видно, что Спейси действительно смог обнаружить электронное письмо, и он не маркировал его, несмотря на наличие “-“. С другой стороны, слово “невегетарианский” было маркировано.

Давайте теперь посмотрим, как мы можем считать слова в документе:

len(sentence4)

В выходных данных вы увидите 14, что является количеством токенов в предложении 4 .

Обнаружение Сущностей

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

Давайте рассмотрим простой пример распознавания именованных сущностей:

sentence5 = sp(u'Manchester United is looking to sign Harry Kane for $90 million')  

Давайте сначала попробуем просто токенизировать его:

for word in sentence5:
    print(word.text)

Выход:

Manchester
United
is
looking
to
sign
Harry
Kane
for
$
90
million

Мы знаем, что “Манчестер Юнайтед” – это одно слово, поэтому его не следует делить на два слова. Точно так же “Гарри Кейн” – это имя человека, а “90 миллионов долларов” – это стоимость валюты. Они также не должны быть токенизированы.

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

for entity in sentence.ents:
    print(entity.text + ' - ' + entity.label_ + ' - ' + str(spacy.explain(entity.label_)))

В приведенном выше сценарии мы печатаем текст сущности, метку сущности и детали сущности. Вывод выглядит следующим образом:

Выход:

Manchester United - ORG - Companies, agencies, institutions, etc.
Harry Kane - PERSON - People, including fictional
$90 million - MONEY - Monetary values, including unit

Вы можете видеть, что распознаватель именованных сущностей Спейси успешно распознал “Манчестер Юнайтед” как организацию, “Гарри Кейна” как личность и “90 миллионов долларов” как денежную ценность.

Обнаружение Существительных

В дополнение к обнаружению именованных сущностей, существительные также могут быть обнаружены. Для этого используется атрибут noun_chunks . Рассмотрим следующее предложение:

sentence5 = sp(u'Latest Rumours: Manchester United is looking to sign Harry Kane for $90 million')  

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

for noun in sentence5.noun_chunks:
    print(noun.text)

Выход:

Latest Rumours
Manchester United
Harry Kane

Из выходных данных вы можете видеть, что существительное также может быть именованной сущностью и наоборот.

Вытекающий

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

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

В NLTK есть два типа стеммеров: Porter Stemmer и Snowball stemmer . Оба они были реализованы с использованием различных алгоритмов.

Porter Stemmer

Let’s see porter stemmer в действии:

import nltk

from nltk.stem.porter import *

Let’s create a class of PorterStemmer .

stemmer = PorterStemmer()

Предположим, у нас есть следующий список, и мы хотим свести эти слова к stem:

tokens = ['compute', 'computer', 'computed', 'computing']

Следующий сценарий находит основу для слов в списке с помощью porter stemmer:

for token in tokens:
    print(token + ' --> ' + stemmer.stem(token))

Результат выглядит следующим образом:

compute --> comput
computer --> comput
computed --> comput
computing --> comput

Вы можете видеть, что все 4 слова были сведены к “компьютеру”, который на самом деле вообще не является словом.

Стеммер снежного кома

Snowball stemmer является слегка улучшенной версией Porter stemmer и обычно предпочтительнее последнего. Давайте посмотрим снежок стеммер в действии:

from nltk.stem.snowball import SnowballStemmer

stemmer = SnowballStemmer(language='english')

tokens = ['compute', 'computer', 'computed', 'computing']

for token in tokens:
    print(token + ' --> ' + stemmer.stem(token))

В приведенном выше сценарии мы использовали Snowball stemmer, чтобы найти стебель тех же 4 слов, которые мы использовали с porter stemmer. Вывод выглядит следующим образом:

compute --> comput
computer --> comput
computed --> comput
computing --> comput

Вы можете видеть, что результаты те же. У нас все еще есть “компут” в качестве стержня. Опять же, это слово “компьютер” на самом деле не является словарным словом.

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

Лемматизация

Хотя мы не могли бы выполнить стемминг с пространством, мы можем выполнить лемматизацию с использованием пространства.

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

sentence6 = sp(u'compute computer computed computing')

Мы можем найти корни всех слов с помощью пространственной лемматизации следующим образом:

for word in sentence6:
    print(word.text,  word.lemma_)

Вывод приведенного выше скрипта выглядит следующим образом:

compute compute
computer computer
computed compute
computing computing

Вы можете видеть, что в отличие от стемминга, где корень, который мы получили, был “вычислить”, корни, которые мы получили здесь, являются реальными словами в словаре.

Лемматизация преобразует слова во второй или третьей формах в их варианты первой формы. Посмотрите на следующий пример:

sentence7 = sp(u'A letter has been written, asking him to be released')

for word in sentence7:
    print(word.text + '  ===>', word.lemma_)

Выход:

A ===> a
letter ===> letter
has ===> have
been ===> be
written ===> write
, ===> ,
asking ===> ask
him ===> -PRON-
to ===> to
be ===> be
released ===> release

Из выходных данных ясно видно, что слова во второй и третьей формах, такие как “написано”, “выпущено” и т. Д., Были преобразованы в первую форму, т. е.

Вывод

Токенизация, Стеммирование и лемматизация являются одними из самых фундаментальных задач обработки естественного языка. В этой статье мы рассмотрели, как мы можем выполнять токенизацию и лемматизацию с помощью космической библиотеки. Мы также видели, как NLTK можно использовать для стемминга. В следующей статье мы начнем наше обсуждение лексики и сопоставления фраз в Python.