Python для НЛП: начало работы с библиотекой StanfordCoreNLP

Это девятая статья из моей серии статей о Python для НЛП. В предыдущей статье [/ python-for-nlp-Introduction-to-the-pattern-library /] мы увидели, как библиотеку шаблонов Python можно использовать для выполнения множества задач НЛП, от токенизации до тегов POS и классификации текста. к анализу настроений. Перед этим мы исследовали библиотеку TextBlob [/ python-for-nlp-Introduction-to-the-textblob-library /] для выполнения аналогичных задач обработки естественного языка. В этой статье,

Это девятая статья из моей серии статей о 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.

comments powered by Disqus