#python #nlp #text-files #nltk
#python #nlp #текстовые файлы #nltk
Вопрос:
Кто-нибудь знает, существует ли существующий модуль или простой метод для чтения и записи предложений с тегами частей речи в текстовые файлы и из них? Я использую python и Natural Language Toolkit (NLTK). Например, этот код:
import nltk
sentences = "Call me Ishmael. Some years ago - never mind how long precisely - having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world."
tagged = nltk.sent_tokenize(sentences.strip())
tagged = [nltk.word_tokenize(sent) for sent in tagged]
tagged = [nltk.pos_tag(sent) for sent in tagged]
print tagged
Возвращает этот вложенный список:
[[('Call', 'NNP'), ('me', 'PRP'), ('Ishmael', 'NNP'), ('.', '.')], [('Some', 'DT'), ('years', 'NNS'), ('ago', 'RB'), ('-', ':'), ('never', 'RB'), ('mind', 'VBP'), ('how', 'WRB'), ('long', 'JJ'), ('precisely', 'RB'), ('-', ':'), ('having', 'VBG'), ('little', 'RB'), ('or', 'CC'), ('no', 'DT'), ('money', 'NN'), ('in', 'IN'), ('my', 'PRP$'), ('purse', 'NN'), (',', ','), ('and', 'CC'), ('nothing', 'NN'), ('particular', 'JJ'), ('to', 'TO'), ('interest', 'NN'), ('me', 'PRP'), ('on', 'IN'), ('shore', 'NN'), (',', ','), ('I', 'PRP'), ('thought', 'VBD'), ('I', 'PRP'), ('would', 'MD'), ('sail', 'VB'), ('about', 'IN'), ('a', 'DT'), ('little', 'RB'), ('and', 'CC'), ('see', 'VB'), ('the', 'DT'), ('watery', 'NN'), ('part', 'NN'), ('of', 'IN'), ('the', 'DT'), ('world', 'NN'), ('.', '.')]]
Я знаю, что мог бы легко сбросить это в pickle, но я действительно хочу экспортировать это как сегмент текстового файла большего размера. Я хотел бы иметь возможность экспортировать список в текстовый файл, а затем вернуться к нему позже, проанализировать его и восстановить исходную структуру списка. Есть ли в NLTK какие-либо встроенные функции для этого? Я искал, но не могу найти ни одного…
Пример вывода:
<headline>Article headline</headline>
<body>Call me Ishmael...</body>
<pos_tags>[[('Call', 'NNP'), ('me', 'PRP'), ('Ishmael', 'NNP')...</pos_tags>
Ответ №1:
NLTK имеет стандартный формат файла для текста с тегами. Это выглядит следующим образом:
Позвоните/NNP мне/PRP Ишмаэлю/NNP ./.
Вам следует использовать этот формат, поскольку он позволяет вам читать ваши файлы с помощью NLTK TaggedCorpusReader
и других подобных классов и получать полный набор функций corpus reader. К сожалению, в NLTK нет высокоуровневой функции для записи корпуса с тегами в этом формате, но это, вероятно, потому, что это довольно тривиально:
for sent in tagged:
print " ".join(word "/" tag for word, tag in sent)
(NLTK предоставляет nltk.tag.tuple2str()
, но обрабатывает только одно слово — его проще просто ввести word "/" tag
).
Если вы сохраните текст с тегами в одном или нескольких файлах fileN.txt
в этом формате, вы сможете прочитать его обратно nltk.corpus.reader.TaggedCorpusReader
следующим образом:
mycorpus = nltk.corpus.reader.TaggedCorpusReader("path/to/corpus", "file.*.txt")
print mycorpus.fileids()
print mycorpus.sents()[0]
for sent in mycorpus.tagged_sents():
<etc>
Обратите внимание, что sents()
метод выдает текст без тегов, хотя и с немного странными интервалами. Нет необходимости включать в файл как помеченные, так и непомеченные версии, как в вашем примере.
TaggedCorpusReader
Не поддерживает заголовки файлов (для заголовка и т.д.), Но если вам это действительно нужно, вы можете создать свой собственный класс, который считывает метаданные файла, а затем обрабатывает остальное следующим образом TaggedCorpusReader
.
Комментарии:
1. Небольшая ошибка, вам нужно создать список внутри вызова join: print » «.join([word «/» тег для word, тег в отправленном])
2. @RahulJha, почему? Попробуйте сделать так, как я написал. Это называется генератором, и он работает без предварительного построения списка результатов (отлично подходит для очень длинных списков, но хорош везде).
Ответ №2:
Похоже, что используется pickle.дампы и вставка их выходных данных в ваш текстовый файл, возможно, с теговой оболочкой для автоматической загрузки, удовлетворят вашим требованиям.
Не могли бы вы более конкретно указать, как бы вы хотели, чтобы выглядел текстовый вывод? Вы стремитесь к чему-то более удобочитаемому для человека?
РЕДАКТИРОВАТЬ: добавление некоторого кода
from xml.dom.minidom import Document, parseString
import nltk
sentences = "Call me Ishmael. Some years ago - never mind how long precisely - having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world."
tagged = nltk.sent_tokenize(sentences.strip())
tagged = [nltk.word_tokenize(sent) for sent in tagged]
tagged = [nltk.pos_tag(sent) for sent in tagged]
# Write to xml string
doc = Document()
base = doc.createElement("Document")
doc.appendChild(base)
headline = doc.createElement("headline")
htext = doc.createTextNode("Article Headline")
headline.appendChild(htext)
base.appendChild(headline)
body = doc.createElement("body")
btext = doc.createTextNode(sentences)
headline.appendChild(btext)
base.appendChild(body)
pos_tags = doc.createElement("pos_tags")
tagtext = doc.createTextNode(repr(tagged))
pos_tags.appendChild(tagtext)
base.appendChild(pos_tags)
xmlstring = doc.toxml()
# Read back tagged
doc2 = parseString(xmlstring)
el = doc2.getElementsByTagName("pos_tags")[0]
text = el.firstChild.nodeValue
tagged2 = eval(text)
print "Equal? ", tagged == tagged2
Комментарии:
1. Спасибо. Да, я бы хотел, чтобы это было доступно для чтения человеком, если это возможно. Я извлекаю данные из газетных статей и создаю записи с тегами. Я бы хотел, чтобы одно из полей содержало предложения с POS-тегами из статьи. Пример идеального вывода смотрите в редактировании выше…
2. Похоже, что результат, который вы хотите, такой же, как в python repr вашего списка?
3. Да, но есть ли способ преобразовать это обратно в список, как только я превращу его в строку с помощью repr ()?
4. Будущие читатели: В этом коде нет ничего плохого, но это не оптимальный подход в NLTK. Пожалуйста, посмотрите мой ответ.