Как мне выполнить анализ зависимостей в NLTK?
Просматривая книгу NLTK, не ясно, как генерировать дерево зависимостей из данного предложения.
Соответствующий раздел книги: подглава по грамматике зависимостей дает пример рисунка, но он не показывает, как разобрать предложение, чтобы придумать эти отношения - или, может быть, я упускаю что-то фундаментальное в НЛП?
РЕДАКТИРОВАТЬ: я хочу что-то похожее на то, что делает Стэнфордский парсер: учитывая предложение "Я выстрелил слоном во сне", он должен вернуть что-то вроде:
nsubj(shot-2, I-1)
det(elephant-4, an-3)
dobj(shot-2, elephant-4)
prep(shot-2, in-5)
poss(sleep-7, my-6)
pobj(in-5, sleep-7)
6 ответов
Мы можем использовать Stanford Parser из NLTK.
Требования
Вам нужно скачать две вещи с их сайта:
- Парсер Stanford CoreNLP.
- Модель языка для вашего желаемого языка (например, модель английского языка)
Предупреждение!
Убедитесь, что версия вашей языковой модели соответствует версии вашего анализатора Stanford CoreNLP!
Текущая версия CoreNLP по состоянию на 22 мая 2018 года - 3.9.1.
После загрузки двух файлов распакуйте zip-файл в любое место.
Код Python
Далее загрузите модель и используйте ее через NLTK
from nltk.parse.stanford import StanfordDependencyParser
path_to_jar = 'path_to/stanford-parser-full-2014-08-27/stanford-parser.jar'
path_to_models_jar = 'path_to/stanford-parser-full-2014-08-27/stanford-parser-3.4.1-models.jar'
dependency_parser = StanfordDependencyParser(path_to_jar=path_to_jar, path_to_models_jar=path_to_models_jar)
result = dependency_parser.raw_parse('I shot an elephant in my sleep')
dep = result.next()
list(dep.triples())
Выход
Вывод последней строки:
[((u'shot', u'VBD'), u'nsubj', (u'I', u'PRP')),
((u'shot', u'VBD'), u'dobj', (u'elephant', u'NN')),
((u'elephant', u'NN'), u'det', (u'an', u'DT')),
((u'shot', u'VBD'), u'prep', (u'in', u'IN')),
((u'in', u'IN'), u'pobj', (u'sleep', u'NN')),
((u'sleep', u'NN'), u'poss', (u'my', u'PRP$'))]
Я думаю, что это то, что вы хотите.
Я думаю, что вы могли бы использовать основанный на корпусе синтаксический анализатор вместо основанного на NLTK грамматики.
Выполнение синтаксического анализа зависимостей даже на небольшом объеме текста в Python не является идеальным решением для повышения производительности. Таким образом, в NLTK они предоставляют оболочку для MaltParser, анализатора зависимостей на основе корпуса.
Вы могли бы найти этот другой вопрос о представлении предложений RDF соответствующим.
Если вам нужна лучшая производительность, тогда spacy ( https://spacy.io/) - лучший выбор. Использование очень просто:
import spacy
nlp = spacy.load('en')
sents = nlp(u'A woman is walking through the door.')
Вы получите дерево зависимостей в качестве выходных данных, и вы сможете очень легко найти любую нужную вам информацию. Вы также можете определить свои собственные конвейеры. Смотрите больше на их сайте.
Использовать Stanford Parser от NLTK
1) Запустите сервер CoreNLP на локальном хосте
Загрузите Stanford CoreNLP здесь (а также файл модели для вашего языка). Сервер можно запустить, выполнив следующую команду (подробнее здесь)
# Run the server using all jars in the current directory (e.g., the CoreNLP home directory)
java -mx4g -cp "*" edu.stanford.nlp.pipeline.StanfordCoreNLPServer -port 9000 -timeout 15000
или с помощью NLTK API (необходимо настроить CORENLP_HOME
сначала переменная окружения)
os.environ["CORENLP_HOME"] = "dir"
client = corenlp.CoreNLPClient()
# do something
client.stop()
2) Вызов парсера зависимостей из NLTK
>>> from nltk.parse.corenlp import CoreNLPDependencyParser
>>> dep_parser = CoreNLPDependencyParser(url='http://localhost:9000')
>>> parse, = dep_parser.raw_parse(
... 'The quick brown fox jumps over the lazy dog.'
... )
>>> print(parse.to_conll(4))
The DT 4 det
quick JJ 4 amod
brown JJ 4 amod
fox NN 5 nsubj
jumps VBZ 0 ROOT
over IN 9 case
the DT 9 det
lazy JJ 9 amod
dog NN 5 nmod
. . 5 punct
Смотрите подробную документацию здесь, также этот вопрос NLTK CoreNLPDependencyParser: Не удалось установить соединение.
Если вы хотите серьезно относиться к анализу зависимостей, не используйте NLTK, все алгоритмы устарели и работают медленно. Попробуйте что-то вроде этого: https://spacy.io/
Немного опоздал на вечеринку, но я хотел добавить пример кода с SpaCy, который даст вам желаемый результат:
import spacy
nlp = spacy.load("en_core_web_sm")
doc = nlp("I shot an elephant in my sleep")
for token in doc:
print("{2}({3}-{6}, {0}-{5})".format(token.text, token.tag_, token.dep_, token.head.text, token.head.tag_, token.i+1, token.head.i+1))
И вот вывод, очень похожий на ваш желаемый вывод:
nsubj(shot-2, I-1)
ROOT(shot-2, shot-2)
det(elephant-4, an-3)
dobj(shot-2, elephant-4)
prep(shot-2, in-5)
poss(sleep-7, my-6)
pobj(in-5, sleep-7)
Надеюсь, это поможет!
Из документации Stanford Parser: "зависимости могут быть получены с помощью нашего программного обеспечения [...] на деревьях фраз-структуры с использованием класса EnglishGrammaticStructure, доступного в пакете parser". http://nlp.stanford.edu/software/stanford-dependencies.shtml
В руководстве по зависимостям также упоминается: "Или наш инструмент преобразования может преобразовать выходные данные других анализаторов групп в представление Стэнфордских зависимостей". http://nlp.stanford.edu/software/dependencies_manual.pdf
Кажется, что ни одна из этих функций в настоящее время не реализована в NLTK.