Это девятая статья из моей серии статей о Python для НЛП. В предыдущей статье мы увидели, как библиотеку шаблонов Python можно использовать для выполнения множества задач НЛП, начиная от токенизации и заканчивая тегированием POS и классификацией текста до анализа тональности. Перед этим мы исследовали библиотеку TextBlob для выполнения аналогичных задач обработки естественного языка.
В этой статье мы рассмотрим библиотеку StanfordCoreNLP, которая является еще одной чрезвычайно удобной библиотекой для обработки естественного языка. Мы увидим различные возможности StanfordCoreNLP на примерах. Итак, прежде чем тратить время впустую, давайте начнем.
Настройка среды
Процесс установки StanfordCoreNLP не так прост, как других библиотек Python. На самом деле StanfordCoreNLP - это библиотека, написанная на Java. Поэтому убедитесь, что в вашей системе установлена Java. Вы можете бесплатно скачать последнюю версию Java .
После установки Java вам необходимо загрузить файлы JAR для библиотек StanfordCoreNLP. Файл JAR содержит модели, которые используются для выполнения различных задач НЛП. Чтобы загрузить файлы JAR для английских моделей, загрузите и распакуйте папку, расположенную на официальном сайте StanfordCoreNLP .
Следующее, что вам нужно сделать, это запустить сервер, который будет обслуживать запросы, отправленные оболочкой Python в библиотеку StanfordCoreNLP. Перейдите по пути, по которому вы распаковали папку с файлами JAR. Перейдите в папку и выполните следующую команду в командной строке:
$ java -mx6g -cp "*" edu.stanford.nlp.pipeline.StanfordCoreNLPServer -timeout 10000
Приведенная выше команда запускает сервер StanfordCoreNLP. Параметр
-mx6g
указывает, что объем памяти, используемой сервером, не должен
превышать 6 гигабайт. Важно отметить, что вы должны использовать
64-разрядную систему, чтобы размер кучи составлял 6 ГБ. Если вы
используете 32-разрядную систему, возможно, вам придется уменьшить объем
памяти, выделенной для сервера.
После того, как вы запустите указанную выше команду, вы должны увидеть следующий результат:
[main] INFO CoreNLP - --- StanfordCoreNLPServer#main() called ---
[main] INFO CoreNLP - setting default constituency parser
[main] INFO CoreNLP - warning: cannot find edu/stanford/nlp/models/srparser/englishSR.ser.gz
[main] INFO CoreNLP - using: edu/stanford/nlp/models/lexparser/englishPCFG.ser.gz instead
[main] INFO CoreNLP - to use shift reduce parser download English models jar from:
[main] INFO CoreNLP - http://stanfordnlp.github.io/CoreNLP/download.html
[main] INFO CoreNLP - Threads: 8
[main] INFO CoreNLP - Starting server...
[main] INFO CoreNLP - StanfordCoreNLPServer listening at /0:0:0:0:0:0:0:0:9000
Сервер работает на порту 9000.
Теперь последний шаг - установка оболочки Python для библиотеки
StanfordCoreNLP. Мы будем использовать pycorenlp
. Следующий скрипт
загружает библиотеку оболочки:
$ pip install pycorenlp
Теперь мы готовы подключиться к серверу StanfordCoreNLP и выполнить желаемые задачи NLP.
Для подключения к серверу, мы должны передать адрес сервера
StanfordCoreNLP , что мы инициализированы ранее в StanfordCoreNLP
класс pycorenlp
модуля. Затем возвращенный объект можно использовать
для выполнения задач НЛП. Взгляните на следующий сценарий:
from pycorenlp import StanfordCoreNLP
nlp_wrapper = StanfordCoreNLP('http://localhost:9000')
Выполнение задач НЛП
В этом разделе мы кратко рассмотрим использование библиотеки StanfordCoreNLP для выполнения общих задач НЛП.
Лемматизация, теги POS и распознавание именованных сущностей
Лемматизация, тегирование частей речи и распознавание именованных сущностей - самые основные задачи НЛП. Библиотека StanfordCoreNLP поддерживает функциональные возможности конвейера, которые можно использовать для выполнения этих задач в структурированном виде.
В следующем скрипте мы создадим аннотатор, который сначала разбивает документ на предложения, а затем далее разбивает предложения на слова или токены. Затем слова аннотируются тегами распознавания POS и именованными объектами.
doc = "Ronaldo has moved from Real Madrid to Juventus. While messi still plays for Barcelona"
annot_doc = nlp_wrapper.annotate(doc,
properties={
'annotators': 'ner, pos',
'outputFormat': 'json',
'timeout': 1000,
})
В приведенном выше сценарии у нас есть документ с двумя предложениями.
Мы используем annotate
объекта-оболочки StanfordCoreNLP, который мы
инициализировали ранее. Метод принимает три параметра. Параметр
annotator
принимает тип аннотации, которую мы хотим применить к
тексту. Мы передаем 'ner, pos'
в качестве значения annotator
который
указывает, что мы хотим аннотировать наш документ для тегов POS и
именованных объектов.
outputFormat
определяет формат, в котором вы хотите аннотировать
текст. Возможные значения: json
для объектов JSON, xml
для формата
XML, text
для простого текста и serialize
для сериализованных
данных.
Последний параметр - это время ожидания в миллисекундах, которое определяет время, в течение которого оболочка должна ждать ответа от сервера до истечения времени ожидания.
В выводе вы должны увидеть объект JSON, как показано ниже:
{'sentences': [{'index': 0,
'entitymentions': [{'docTokenBegin': 0,
'docTokenEnd': 1,
'tokenBegin': 0,
'tokenEnd': 1,
'text': 'Ronaldo',
'characterOffsetBegin': 0,
'characterOffsetEnd': 7,
'ner': 'PERSON'},
{'docTokenBegin': 4,
'docTokenEnd': 6,
'tokenBegin': 4,
'tokenEnd': 6,
'text': 'Real Madrid',
'characterOffsetBegin': 23,
'characterOffsetEnd': 34,
'ner': 'ORGANIZATION'},
{'docTokenBegin': 7,
'docTokenEnd': 8,
'tokenBegin': 7,
'tokenEnd': 8,
'text': 'Juventus',
'characterOffsetBegin': 38,
'characterOffsetEnd': 46,
'ner': 'ORGANIZATION'}],
'tokens': [{'index': 1,
'word': 'Ronaldo',
'originalText': 'Ronaldo',
'lemma': 'Ronaldo',
'characterOffsetBegin': 0,
'characterOffsetEnd': 7,
'pos': 'NNP',
'ner': 'PERSON',
'before': '',
'after': ' '},
{'index': 2,
'word': 'has',
'originalText': 'has',
'lemma': 'have',
'characterOffsetBegin': 8,
'characterOffsetEnd': 11,
'pos': 'VBZ',
'ner': 'O',
'before': ' ',
'after': ' '},
{'index': 3,
'word': 'moved',
'originalText': 'moved',
'lemma': 'move',
'characterOffsetBegin': 12,
'characterOffsetEnd': 17,
'pos': 'VBN',
'ner': 'O',
'before': ' ',
'after': ' '},
{'index': 4,
'word': 'from',
'originalText': 'from',
'lemma': 'from',
'characterOffsetBegin': 18,
'characterOffsetEnd': 22,
'pos': 'IN',
'ner': 'O',
'before': ' ',
'after': ' '},
{'index': 5,
'word': 'Real',
'originalText': 'Real',
'lemma': 'real',
'characterOffsetBegin': 23,
'characterOffsetEnd': 27,
'pos': 'JJ',
'ner': 'ORGANIZATION',
'before': ' ',
'after': ' '},
{'index': 6,
'word': 'Madrid',
'originalText': 'Madrid',
'lemma': 'Madrid',
'characterOffsetBegin': 28,
'characterOffsetEnd': 34,
'pos': 'NNP',
'ner': 'ORGANIZATION',
'before': ' ',
'after': ' '},
{'index': 7,
'word': 'to',
'originalText': 'to',
'lemma': 'to',
'characterOffsetBegin': 35,
'characterOffsetEnd': 37,
'pos': 'TO',
'ner': 'O',
'before': ' ',
'after': ' '},
{'index': 8,
'word': 'Juventus',
'originalText': 'Juventus',
'lemma': 'Juventus',
'characterOffsetBegin': 38,
'characterOffsetEnd': 46,
'pos': 'NNP',
'ner': 'ORGANIZATION',
'before': ' ',
'after': ''},
{'index': 9,
'word': '.',
'originalText': '.',
'lemma': '.',
'characterOffsetBegin': 46,
'characterOffsetEnd': 47,
'pos': '.',
'ner': 'O',
'before': '',
'after': ' '}]},
{'index': 1,
'entitymentions': [{'docTokenBegin': 14,
'docTokenEnd': 15,
'tokenBegin': 5,
'tokenEnd': 6,
'text': 'Barcelona',
'characterOffsetBegin': 76,
'characterOffsetEnd': 85,
'ner': 'ORGANIZATION'}],
'tokens': [{'index': 1,
'word': 'While',
'originalText': 'While',
'lemma': 'while',
'characterOffsetBegin': 48,
'characterOffsetEnd': 53,
'pos': 'IN',
'ner': 'O',
'before': ' ',
'after': ' '},
{'index': 2,
'word': 'messi',
'originalText': 'messi',
'lemma': 'messus',
'characterOffsetBegin': 54,
'characterOffsetEnd': 59,
'pos': 'NNS',
'ner': 'O',
'before': ' ',
'after': ' '},
{'index': 3,
'word': 'still',
'originalText': 'still',
'lemma': 'still',
'characterOffsetBegin': 60,
'characterOffsetEnd': 65,
'pos': 'RB',
'ner': 'O',
'before': ' ',
'after': ' '},
{'index': 4,
'word': 'plays',
'originalText': 'plays',
'lemma': 'play',
'characterOffsetBegin': 66,
'characterOffsetEnd': 71,
'pos': 'VBZ',
'ner': 'O',
'before': ' ',
'after': ' '},
{'index': 5,
'word': 'for',
'originalText': 'for',
'lemma': 'for',
'characterOffsetBegin': 72,
'characterOffsetEnd': 75,
'pos': 'IN',
'ner': 'O',
'before': ' ',
'after': ' '},
{'index': 6,
'word': 'Barcelona',
'originalText': 'Barcelona',
'lemma': 'Barcelona',
'characterOffsetBegin': 76,
'characterOffsetEnd': 85,
'pos': 'NNP',
'ner': 'ORGANIZATION',
'before': ' ',
'after': ''}]}]}
Если вы внимательно посмотрите на приведенный выше сценарий, вы можете найти теги POS, именованные объекты и лемматизированную версию каждого слова.
Лемматизация
Давайте теперь исследуем аннотированные результаты. Сначала мы напечатаем лемматизацию слов в двух предложениях в нашем наборе данных:
for sentence in annot_doc["sentences"]:
for word in sentence["tokens"]:
print(word["word"] + " => " + word["lemma"])
В приведенном выше сценарии внешний цикл выполняет итерацию по каждому предложению в документе, а внутренний цикл выполняет итерацию по каждому слову в предложении. Внутри внутреннего цикла слово и соответствующая ему лемматизированная форма печатаются на консоли. Результат выглядит так:
Ronaldo=>Ronaldo
has=>have
moved=>move
from=>from
Real=>real
Madrid=>Madrid
to=>to
Juventus=>Juventus
.=>.
While=>while
messi=>messus
still=>still
plays=>play
for=>for
Barcelona=>Barcelona
Например, вы можете увидеть слово moved
было lemmatized в move
,
аналогично слово plays
была lemmatized для play
.
POS-теги
Таким же образом мы можем найти теги POS для каждого слова. Взгляните на следующий сценарий:
for sentence in annot_doc["sentences"]:
for word in sentence["tokens"]:
print (word["word"] + "=>" + word["pos"])
На выходе вы должны увидеть следующие результаты:
Ronaldo=>NNP
has=>VBZ
moved=>VBN
from=>IN
Real=>JJ
Madrid=>NNP
to=>TO
Juventus=>NNP
.=>.
While=>IN
messi=>NNS
still=>RB
plays=>VBZ
for=>IN
Barcelona=>NNP
Набор тегов, используемый для тегов POS, представляет собой набор тегов Penn Treebank, и его можно найти здесь .
Признание именованных сущностей
Чтобы найти именованные объекты в нашем документе, мы можем использовать следующий скрипт:
for sentence in annot_doc["sentences"]:
for word in sentence["tokens"]:
print (word["word"] + "=>" + word["ner"])
Результат выглядит так:
Ronaldo=>PERSON
has=>O
moved=>O
from=>O
Real=>ORGANIZATION
Madrid=>ORGANIZATION
to=>O
Juventus=>ORGANIZATION
.=>O
While=>O
messi=>O
still=>O
plays=>O
for=>O
Barcelona=>ORGANIZATION
Мы видим, что Ronaldo
был идентифицирован как PERSON
а « Barcelona
- как
Organization
, что в данном случае верно.
Анализ настроений
Чтобы найти тональность предложения, все, что вам нужно, это передать
sentiment
в качестве значения свойства annotators
Взгляните на
следующий сценарий:
doc = "I like this chocolate. This chocolate is not good. The chocolate is delicious. Its a very tasty chocolate. This is so bad"
annot_doc = nlp_wrapper.annotate(doc,
properties={
'annotators': 'sentiment',
'outputFormat': 'json',
'timeout': 1000,
})
Чтобы найти тональность, мы можем перебрать каждое предложение, а затем
использовать sentimentValue
чтобы найти тональность. sentimentValue
возвращает значение от 1 до 4, где 1 соответствует крайне отрицательному
настроению, а 4 - очень положительному настроению. Свойство sentiment
можно использовать для получения настроения в вербальной форме, т. Е.
positive
, negative
или neutral
.
Следующий скрипт находит тональность каждого предложения в документе, который мы определили выше.
for sentence in annot_doc["sentences"]:
print ( " ".join([word["word"] for word in sentence["tokens"]]) + " => " \
+ str(sentence["sentimentValue"]) + " = "+ sentence["sentiment"])
Выход:
I like this chocolate . => 2 = Neutral
This chocolate is not good . => 1 = Negative
The chocolate is delicious . => 3 = Positive
Its a very tasty chocolate . => 3 = Positive
This is so bad => 1 = Negative
Заключение
StanfordCoreNLP
- еще одна чрезвычайно удобная библиотека для
обработки естественного языка. В этой статье мы изучили, как настроить
среду для запуска StanfordCoreNLP. Затем мы изучили использование
библиотеки StanfordCoreNLP для общих задач NLP, таких как лемматизация,
тегирование POS и распознавание именованных сущностей, и, наконец, мы
завершили статью сентиментальным анализом с использованием
StanfordCoreNLP.