การอ่านและการเขียนประโยคที่ติดแท็ก POS จากไฟล์ข้อความโดยใช้ NLTK และ Python

ไม่มีใครรู้ว่ามีโมดูลที่มีอยู่หรือวิธีการง่ายๆ ในการอ่านและเขียนประโยคที่แท็กส่วนของคำพูดเข้าและออกจากไฟล์ข้อความหรือไม่? ฉันใช้ 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'), ('.', '.')]]

ฉันรู้ว่าฉันสามารถทิ้งสิ่งนี้ลงในผักดองได้อย่างง่ายดาย แต่ฉันต้องการส่งออกเป็นส่วนของไฟล์ข้อความที่มีขนาดใหญ่กว่า ฉันต้องการส่งออกรายการเป็นไฟล์ข้อความ จากนั้นกลับมาที่รายการในภายหลัง แยกวิเคราะห์ และกู้คืนโครงสร้างรายการดั้งเดิม มีฟังก์ชันในตัวใน NLTK สำหรับการทำเช่นนี้หรือไม่ ฉันค้นหาแล้ว แต่ไม่พบเลย...

ตัวอย่างผลลัพธ์:

<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 แหล่งที่มา


คำตอบ (2)


ดูเหมือนว่าการใช้ Pickle.dumps และแทรกเอาต์พุตลงในไฟล์ข้อความของคุณ บางทีการใช้ tag wrapper สำหรับการโหลดอัตโนมัติอาจตรงตามความต้องการของคุณ

คุณช่วยระบุให้เจาะจงมากขึ้นได้ไหมว่าต้องการให้ข้อความออกมาเป็นอย่างไร? คุณกำลังมุ่งเป้าไปที่สิ่งที่มนุษย์สามารถอ่านได้มากขึ้นหรือไม่?

แก้ไข: เพิ่มโค้ดบางส่วน

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
ขอบคุณ. ใช่ ฉันอยากให้มนุษย์อ่านได้ถ้าเป็นไปได้ ฉันกำลังดึงข้อมูลจากบทความในหนังสือพิมพ์และสร้างบันทึกที่ติดแท็ก ฉันต้องการให้ฟิลด์ใดฟิลด์หนึ่งมีประโยคที่แท็ก POS จากบทความ ดูการแก้ไขด้านบนสำหรับตัวอย่างผลลัพธ์ในอุดมคติ... - person rjf; 07.04.2011
comment
ดูเหมือนว่าผลลัพธ์ที่คุณต้องการจะเหมือนกับ python repr ในรายการของคุณใช่ไหม - person so12311; 07.04.2011
comment
ใช่ แต่มีวิธีแปลงกลับเป็นรายการเมื่อฉันสร้างเป็นสตริงด้วย repr() หรือไม่ - person rjf; 07.04.2011
comment
ผู้อ่านในอนาคต: ไม่มีอะไรผิดปกติกับโค้ดนี้ แต่ไม่ใช่แนวทางที่เหมาะสมที่สุดใน NLTK โปรดดูคำตอบของฉัน - person alexis; 13.09.2012

NLTK มีรูปแบบไฟล์มาตรฐานสำหรับข้อความที่แท็ก ดูเหมือนว่านี้:

โทร/NNP ฉัน/PRP อิชมาเอล/NNP ./.

คุณควรใช้รูปแบบนี้ เนื่องจากจะทำให้คุณสามารถอ่านไฟล์ของคุณด้วย TaggedCorpusReader ของ NLTK และคลาสอื่นๆ ที่คล้ายกัน และรับฟังก์ชันตัวอ่านคลังข้อมูลอย่างเต็มรูปแบบ น่าสับสนที่ไม่มีฟังก์ชันระดับสูงใน 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

person alexis    schedule 13.09.2012
comment
เกิดข้อผิดพลาดเล็กน้อย คุณต้องสร้างรายการภายในการโทรเข้าร่วม: print .join([word+/+tag for word, tag in sent]) - person Rahul Jha; 28.06.2013
comment
@RahulJha ทำไม? ลองตามที่ผมเขียนดูนะครับ มันถูกเรียกว่าตัวสร้าง และทำงานโดยไม่ต้องสร้างรายการผลลัพธ์ล่วงหน้า (เหมาะสำหรับรายการที่ยาวมาก แต่ก็ดีในทุกที่) - person alexis; 28.06.2013