R - синтаксический анализ деревьев Python NLTK через сетку

Я пытаюсь использовать пакет Python NLTK изнутри R, используя пакет Reticulate. По большей части, я был успешным.

Теперь я хотел бы выполнить распознавание именованных сущностей (т.е. определить, какие токены представляют именованные сущности и какой тип именованных сущностей они представляют), используя NLTK. ne_chunk() функция. Моя проблема в том, что функция возвращает объект класса nltk.tree.Tree, который я не могу понять, как разобрать в R.

Если ne_chunk() подается до десяти пар токен-тегов, он возвращает результат, который можно преобразовать в символ с помощью as.character(), который может быть проанализирован с помощью функций регулярных выражений (это просто взлом, и я не удовлетворен этим). Тем не менее, более десяти пар, и он вернет сокращенное представление дерева, из которого никакие значимые данные не могут быть извлечены с использованием методов R.

Вот минимально воспроизводимый пример:

library(reticulate)
nltk <- import("nltk")

sent_tokenize <- function(text, language = "english") {
  nltk$tokenize$sent_tokenize(text, language)
}
word_tokenize <- function(text, language = "english", preserve_line = FALSE) {
  nltk$tokenize$word_tokenize(text, language, preserve_line)
}
pos_tag <- function(tokens, tagset = NULL, language = "eng") {
  nltk$pos_tag(tokens, tagset, language)
}
ne_chunk <- function(tagged_tokens, binary = FALSE) {
  nltk$ne_chunk(tagged_tokens, binary)
}

text <- "Christopher is having a difficult time parsing NLTK Trees in R."
tokens <- word_tokenize(text)
tagged_tokens <- pos_tag(tokens)
ne_tagged_tokens <- ne_chunk(tagged_tokens)

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

> ne_tagged_tokens
List (11 items)

Вот классы, к которым ne_tagged_tokens принадлежит:

> class(ne_tagged_tokens)
[1] "nltk.tree.Tree"        "python.builtin.list"   "python.builtin.object"

Меня не интересуют предложения по использованию альтернативных, ранее существующих пакетов R.

1 ответ

Решение

Я думаю, что проблема заключается в reticulate неспособность читать настроенные объекты Python, что является обычным явлением, поэтому вы должны передавать объекты Python так же близко, как и нативные типы Python, между интерфейсами R и Python.

Есть способ изменить формат вывода ne_chunks в строку (в формате разбора в скобках), используя Tree.pformat():

>>> from nltk import word_tokenize, pos_tag, ne_chunk
>>> sent = "Christopher is having a difficult time parsing NLTK Trees in R."
>>> ne_chunk(pos_tag(word_tokenize(sent)))
Tree('S', [Tree('GPE', [('Christopher', 'NNP')]), ('is', 'VBZ'), ('having', 'VBG'), ('a', 'DT'), ('difficult', 'JJ'), ('time', 'NN'), ('parsing', 'VBG'), Tree('ORGANIZATION', [('NLTK', 'NNP'), ('Trees', 'NNP')]), ('in', 'IN'), Tree('GPE', [('R', 'NNP')]), ('.', '.')])
>>> ne_chunk(pos_tag(word_tokenize(sent))).pformat()
'(S\n  (GPE Christopher/NNP)\n  is/VBZ\n  having/VBG\n  a/DT\n  difficult/JJ\n  time/NN\n  parsing/VBG\n  (ORGANIZATION NLTK/NNP Trees/NNP)\n  in/IN\n  (GPE R/NNP)\n  ./.)'

И чтобы прочитать его обратно, используйте Tree.fromstring():

>>> tree_str = ne_chunk(pos_tag(word_tokenize(sent))).pformat()
>>> from nltk import Tree
>>> Tree.fromstring(tree_str)
Tree('S', [Tree('GPE', ['Christopher/NNP']), 'is/VBZ', 'having/VBG', 'a/DT', 'difficult/JJ', 'time/NN', 'parsing/VBG', Tree('ORGANIZATION', ['NLTK/NNP', 'Trees/NNP']), 'in/IN', Tree('GPE', ['R/NNP']), './.'])

Так что я думаю, что выполнение этого в R может работать:

text <- "Christopher is having a difficult time parsing NLTK Trees in R."
ne_tagged_tokens <- ne_chunk(pos_tag(word_tokenize(tagged_tokens)))$pformat()
print(ne_tagged_tokens)

Но чтение строк обратно в объекты R не должно быть возможным, так как он не может обрабатывать не собственные объекты Python Tree, поэтому some_func <- function(...{nltk$some_func(...)}) не будет работать с Tree так как это не функция.


Если вы хотите манипулировать выводом ne_chunk Дерево объектов в список именованных сущностей, тогда вам придется сделать что-то вроде этого в Python: NLTK Распознавание именованных сущностей в списке Python

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

Другие вопросы по тегам