Следует отметить, что библиотека python stanfordnlp - это не просто оболочка Python для StanfordCoreNLP.
1.Разница StanfordNLP / CoreNLP
Как сказано в репозитории Github stanfordnlp :
Официальная библиотека Python NLP группы Stanford NLP.Он содержит пакеты для запуска нашего последнего полностью нейронного конвейера из Shared Task CoNLL 2018 и для доступа к серверу Java Stanford CoreNLP.
Stanfordnlp содержит новый набор моделей нейронных сетей, обученных на общей CONLL 2018задача.Онлайн-анализатор основан на Java-библиотеке CoreNLP 3.9.2.Это два разных конвейера и наборы моделей, как объяснено здесь .
Ваш код обращается только к их нейронному конвейеру, обученному на данных CONLL 2018.Это объясняет различия, которые вы видели по сравнению с онлайн-версией.По сути, это две разные модели.
Я считаю, что путаница заключается в том, что оба репозитория принадлежат пользователю с именем stanfordnlp (это название команды).Не обманывайтесь между java stanfordnlp / CoreNLP и питоном stanfordnlp / stanfordnlp.
Что касается вашей проблемы с "neg", то, похоже, в python libabry stanfordnlp они решили рассмотреть отрицание с помощью аннотации advmod.По крайней мере, это то, с чем я столкнулся для нескольких примеров предложений.
2.Использование CoreNLP через пакет stanfordnlp
Однако вы все равно можете получить доступ к CoreNLP через пакет stanfordnlp.Это требует еще нескольких шагов, хотя.Ссылаясь на репозиторий Github,
Существует несколько начальных шагов настройки.
- Загрузите Stanford CoreNLP и модели для языка, который вы хотите использовать. (вы можете скачать CoreNLP и языковые модели здесь)
- Поместите jar-файлы моделей в папку дистрибутива
- Сообщите коду Python, где находится Stanford CoreNLP: export CORENLP_HOME =/ path / to / stanford-corenlp-full-2018-10-05
Как только это будет сделано, вы можете запустить клиента с кодом, который можно найти в demo :
from stanfordnlp.server import CoreNLPClient
with CoreNLPClient(annotators=['tokenize','ssplit','pos','depparse'], timeout=60000, memory='16G') as client:
# submit the request to the server
ann = client.annotate(text)
# get the first sentence
sentence = ann.sentence[0]
# get the dependency parse of the first sentence
print('---')
print('dependency parse of first sentence')
dependency_parse = sentence.basicDependencies
print(dependency_parse)
#get the tokens of the first sentence
#note that 1 token is 1 node in the parse tree, nodes start at 1
print('---')
print('Tokens of first sentence')
for token in sentence.token :
print(token)
Поэтому ваше предложение будет проанализировано, если вы укажете аннотатор depparse (а также обязательные аннотаторы tokenize, ssplit и pos).Читая демо, кажется, что мы можем получить доступ только к базовым зависимостям.Мне не удалось заставить работать зависимости Enhanced ++ через stanfordnlp.
Но отрицания все равно будут появляться, если вы используете basicDependencies!
Вот вывод, который я получил с помощью stanfordnlp и вашего примера предложения.Это объект DependencyGraph, не очень красивый, но, к сожалению, это всегда тот случай, когда мы используем очень глубокие инструменты CoreNLP.Вы увидите, что между узлами 4 и 5 («не» и «рожденный») есть и край «нег».
node {
sentenceIndex: 0
index: 1
}
node {
sentenceIndex: 0
index: 2
}
node {
sentenceIndex: 0
index: 3
}
node {
sentenceIndex: 0
index: 4
}
node {
sentenceIndex: 0
index: 5
}
node {
sentenceIndex: 0
index: 6
}
node {
sentenceIndex: 0
index: 7
}
node {
sentenceIndex: 0
index: 8
}
edge {
source: 2
target: 1
dep: "compound"
isExtra: false
sourceCopy: 0
targetCopy: 0
language: UniversalEnglish
}
edge {
source: 5
target: 2
dep: "nsubjpass"
isExtra: false
sourceCopy: 0
targetCopy: 0
language: UniversalEnglish
}
edge {
source: 5
target: 3
dep: "auxpass"
isExtra: false
sourceCopy: 0
targetCopy: 0
language: UniversalEnglish
}
edge {
source: 5
target: 4
dep: "neg"
isExtra: false
sourceCopy: 0
targetCopy: 0
language: UniversalEnglish
}
edge {
source: 5
target: 7
dep: "nmod"
isExtra: false
sourceCopy: 0
targetCopy: 0
language: UniversalEnglish
}
edge {
source: 5
target: 8
dep: "punct"
isExtra: false
sourceCopy: 0
targetCopy: 0
language: UniversalEnglish
}
edge {
source: 7
target: 6
dep: "case"
isExtra: false
sourceCopy: 0
targetCopy: 0
language: UniversalEnglish
}
root: 5
---
Tokens of first sentence
word: "Barack"
pos: "NNP"
value: "Barack"
before: ""
after: " "
originalText: "Barack"
beginChar: 0
endChar: 6
tokenBeginIndex: 0
tokenEndIndex: 1
hasXmlContext: false
isNewline: false
word: "Obama"
pos: "NNP"
value: "Obama"
before: " "
after: " "
originalText: "Obama"
beginChar: 7
endChar: 12
tokenBeginIndex: 1
tokenEndIndex: 2
hasXmlContext: false
isNewline: false
word: "was"
pos: "VBD"
value: "was"
before: " "
after: " "
originalText: "was"
beginChar: 13
endChar: 16
tokenBeginIndex: 2
tokenEndIndex: 3
hasXmlContext: false
isNewline: false
word: "not"
pos: "RB"
value: "not"
before: " "
after: " "
originalText: "not"
beginChar: 17
endChar: 20
tokenBeginIndex: 3
tokenEndIndex: 4
hasXmlContext: false
isNewline: false
word: "born"
pos: "VBN"
value: "born"
before: " "
after: " "
originalText: "born"
beginChar: 21
endChar: 25
tokenBeginIndex: 4
tokenEndIndex: 5
hasXmlContext: false
isNewline: false
word: "in"
pos: "IN"
value: "in"
before: " "
after: " "
originalText: "in"
beginChar: 26
endChar: 28
tokenBeginIndex: 5
tokenEndIndex: 6
hasXmlContext: false
isNewline: false
word: "Hawaii"
pos: "NNP"
value: "Hawaii"
before: " "
after: ""
originalText: "Hawaii"
beginChar: 29
endChar: 35
tokenBeginIndex: 6
tokenEndIndex: 7
hasXmlContext: false
isNewline: false
word: "."
pos: "."
value: "."
before: ""
after: ""
originalText: "."
beginChar: 35
endChar: 36
tokenBeginIndex: 7
tokenEndIndex: 8
hasXmlContext: false
isNewline: false
2.Использование CoreNLP через пакет NLTK
Я не буду вдаваться в подробности этого, но есть также решение для доступа к серверу CoreNLP через библиотеку NLTK, если ничего не помогает.Он выводит отрицания, но требует немного больше работы для запуска серверов.Подробности на этой странице
РЕДАКТИРОВАТЬ
Я подумал, что мог бы также поделиться с вами кодом, чтобы получить DependencyGraph в хороший список 'зависимости, аргумента1, аргумента2' вформа, похожая на ту, что выводит stanfordnlp.
from stanfordnlp.server import CoreNLPClient
text = "Barack Obama was not born in Hawaii."
# set up the client
with CoreNLPClient(annotators=['tokenize','ssplit','pos','depparse'], timeout=60000, memory='16G') as client:
# submit the request to the server
ann = client.annotate(text)
# get the first sentence
sentence = ann.sentence[0]
# get the dependency parse of the first sentence
dependency_parse = sentence.basicDependencies
#print(dir(sentence.token[0])) #to find all the attributes and methods of a Token object
#print(dir(dependency_parse)) #to find all the attributes and methods of a DependencyGraph object
#print(dir(dependency_parse.edge))
#get a dictionary associating each token/node with its label
token_dict = {}
for i in range(0, len(sentence.token)) :
token_dict[sentence.token[i].tokenEndIndex] = sentence.token[i].word
#get a list of the dependencies with the words they connect
list_dep=[]
for i in range(0, len(dependency_parse.edge)):
source_node = dependency_parse.edge[i].source
source_name = token_dict[source_node]
target_node = dependency_parse.edge[i].target
target_name = token_dict[target_node]
dep = dependency_parse.edge[i].dep
list_dep.append((dep,
str(source_node)+'-'+source_name,
str(target_node)+'-'+target_name))
print(list_dep)
Он выводит следующее
[('compound', '2-Obama', '1-Barack'), ('nsubjpass', '5-born', '2-Obama'), ('auxpass', '5-born', '3-was'), ('neg', '5-born', '4-not'), ('nmod', '5-born', '7-Hawaii'), ('punct', '5-born', '8-.'), ('case', '7-Hawaii', '6-in')]