Membaca dan menulis kalimat bertanda POS dari file teks menggunakan NLTK dan Python

Adakah yang tahu jika ada modul atau metode mudah untuk membaca dan menulis kalimat yang diberi tag part-of-speech ke dan dari file teks? Saya menggunakan python dan Natural Language Toolkit (NLTK). Misalnya, kode ini:

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

Mengembalikan daftar bersarang ini:

[[('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'), ('.', '.')]]

Saya tahu saya dapat dengan mudah membuang ini ke dalam acar, tetapi saya benar-benar ingin mengekspor ini sebagai segmen file teks yang lebih besar. Saya ingin dapat mengekspor daftar ke file teks, lalu kembali lagi nanti, menguraikannya, dan memulihkan struktur daftar asli. Apakah ada fungsi bawaan di NLTK untuk melakukan ini? Saya telah mencari tetapi tidak dapat menemukannya...

Contoh keluaran:

<headline>Article headline</headline>
<body>Call me Ishmael...</body>
<pos_tags>[[('Call', 'NNP'), ('me', 'PRP'), ('Ishmael', 'NNP')...</pos_tags>

person rjf    schedule 06.04.2011    source sumber


Jawaban (2)


Sepertinya menggunakan acar.dumps dan memasukkan outputnya ke file teks Anda, mungkin dengan pembungkus tag untuk pemuatan otomatis akan memenuhi kebutuhan Anda.

Bisakah Anda lebih spesifik tentang tampilan keluaran teks yang Anda inginkan? Apakah Anda menginginkan sesuatu yang lebih mudah dibaca manusia?

EDIT: menambahkan beberapa kode

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
person so12311    schedule 07.04.2011
comment
Terima kasih. Ya, saya ingin agar dapat dibaca manusia jika memungkinkan. Saya mengekstraksi data dari artikel surat kabar dan membuat catatan yang diberi tag. Saya ingin salah satu bidang berisi kalimat yang diberi tag POS dari artikel. Lihat edit di atas untuk contoh keluaran ideal... - person rjf; 07.04.2011
comment
Sepertinya output yang Anda inginkan sama dengan python repr daftar Anda? - person so12311; 07.04.2011
comment
Ya, tetapi apakah ada cara untuk mengubahnya kembali menjadi daftar setelah saya menjadikannya string dengan repr()? - person rjf; 07.04.2011
comment
Pembaca selanjutnya: Tidak ada yang salah dengan kode ini, tapi ini bukan pendekatan optimal di NLTK. Silakan lihat jawaban saya. - person alexis; 13.09.2012

NLTK memiliki format file standar untuk teks yang diberi tag. Ini terlihat seperti ini:

Hubungi/NNP saya/PRP Ismail/NNP ./.

Anda harus menggunakan format ini, karena ini memungkinkan Anda membaca file Anda dengan TaggedCorpusReader NLTK dan kelas serupa lainnya, dan mendapatkan fungsi pembaca korpus secara lengkap. Yang membingungkan, tidak ada fungsi tingkat tinggi di NLTK untuk menulis korpus yang diberi tag dalam format ini, tapi itu mungkin karena hal ini cukup sepele:

for sent in tagged:
    print " ".join(word+"/"+tag for word, tag in sent)

(NLTK memang menyediakan nltk.tag.tuple2str(), tetapi hanya menangani satu kata-- lebih mudah mengetik word+"/"+tag saja).

Jika Anda menyimpan teks yang diberi tag dalam satu atau lebih file fileN.txt dalam format ini, Anda dapat membacanya kembali dengan nltk.corpus.reader.TaggedCorpusReader seperti ini:

mycorpus = nltk.corpus.reader.TaggedCorpusReader("path/to/corpus", "file.*\.txt")
print mycorpus.fileids()
print mycorpus.sents()[0]
for sent in mycorpus.tagged_sents():
    <etc>

Perhatikan bahwa metode sents() memberi Anda teks yang tidak diberi tag, meskipun spasinya agak aneh. Tidak perlu menyertakan versi yang diberi tag dan tidak diberi tag dalam file, seperti pada contoh Anda.

TaggedCorpusReader tidak mendukung header file (untuk judul, dll.), tetapi jika Anda benar-benar membutuhkannya, Anda dapat memperoleh kelas Anda sendiri yang membaca metadata file dan kemudian menangani sisanya seperti TaggedCorpusReader.

person alexis    schedule 13.09.2012
comment
Kesalahan kecil, Anda perlu membuat daftar di dalam panggilan join: print .join([word+/+tag for word, tag in sent]) - person Rahul Jha; 28.06.2013
comment
@RahulJha, kenapa? Cobalah seperti yang saya tulis. Ini disebut generator, dan berfungsi tanpa membuat daftar hasil terlebih dahulu (bagus untuk daftar yang sangat panjang, tetapi bagus di mana saja). - person alexis; 28.06.2013