วิธีกำจัดเครื่องหมายวรรคตอนโดยใช้โทเค็น NLTK


125

ฉันเพิ่งเริ่มใช้ NLTK และไม่ค่อยเข้าใจวิธีรับรายการคำจากข้อความ ถ้าฉันใช้nltk.word_tokenize()ฉันจะได้รับรายการคำและเครื่องหมายวรรคตอน ฉันต้องการเพียงคำพูดแทน ฉันจะกำจัดเครื่องหมายวรรคตอนได้อย่างไร ยังใช้word_tokenizeไม่ได้กับหลายประโยค: จุดจะถูกเพิ่มเข้าไปในคำสุดท้าย


12
ทำไมคุณไม่ลบเครื่องหมายวรรคตอนเอง nltk.word_tokenize(the_text.translate(None, string.punctuation))ควรจะทำงานในขณะที่อยู่ใน python2 python3 nltk.work_tokenize(the_text.translate(dict.fromkeys(string.punctuation)))ที่คุณสามารถทำได้
Bakuriu

3
วิธีนี้ใช้ไม่ได้ ไม่มีอะไรเกิดขึ้นกับข้อความ
lizarisk

ขั้นตอนการทำงานที่ NLTK สันนิษฐานคือคุณจะโทเค็นเป็นประโยคก่อนจากนั้นทุกประโยคเป็นคำ นั่นคือเหตุผลที่ใช้word_tokenize()ไม่ได้กับหลายประโยค ในการกำจัดเครื่องหมายวรรคตอนคุณสามารถใช้นิพจน์ทั่วไปหรือisalnum()ฟังก์ชันของไพธ อน
Suzana

2
มันใช้งานได้: >>> 'with dot.'.translate(None, string.punctuation) 'with dot'( 'end of sentence.No space'อย่าลืมจุดที่ท้ายผลลัพธ์) อาจทำให้เกิดปัญหาหากคุณมีสิ่งต่างๆเช่นในกรณีนี้ให้ทำสิ่งนี้แทนthe_text.translate(string.maketrans(string.punctuation, ' '*len(string.punctuation)))ซึ่งจะแทนที่เครื่องหมายวรรคตอนทั้งหมดด้วยช่องว่างสีขาว
Bakuriu

อ๊ะมันใช้งานได้จริง แต่ไม่ใช่กับสตริง Unicode
lizarisk

คำตอบ:


162

ลองดูที่ตัวเลือกอื่น ๆ tokenizing ที่ nltk ให้ที่นี่ ตัวอย่างเช่นคุณสามารถกำหนดโทเค็นที่เลือกลำดับของอักขระที่เป็นตัวอักษรและตัวเลขคละกันเป็นโทเค็นและวางทุกอย่างอื่น:

from nltk.tokenize import RegexpTokenizer

tokenizer = RegexpTokenizer(r'\w+')
tokenizer.tokenize('Eighty-seven miles to go, yet.  Onward!')

เอาท์พุท:

['Eighty', 'seven', 'miles', 'to', 'go', 'yet', 'Onward']

55
โปรดทราบว่าหากคุณใช้ตัวเลือกนี้คุณจะสูญเสียคุณสมบัติภาษาธรรมชาติที่พิเศษword_tokenizeเช่นการแยกการหดตัวออกจากกัน คุณสามารถแยก regex \w+ได้อย่างไร้เดียงสาโดยไม่ต้องใช้ NLTK
sffc

3
หากต้องการแสดงความคิดเห็นของ @sffc คุณอาจสูญเสียคำเช่น "Mr. "
geekazoid

มันแทนที่ 'n't' เป็น 't' จะกำจัดสิ่งนี้ได้อย่างไร?
Md. Ashikur Rahman

46

คุณไม่จำเป็นต้องใช้ NLTK เพื่อลบเครื่องหมายวรรคตอน คุณสามารถลบออกได้ด้วย python แบบธรรมดา สำหรับสตริง:

import string
s = '... some string with punctuation ...'
s = s.translate(None, string.punctuation)

หรือสำหรับ Unicode:

import string
translate_table = dict((ord(char), None) for char in string.punctuation)   
s.translate(translate_table)

จากนั้นใช้สตริงนี้ในโทเค็นไนเซอร์ของคุณ

โมดูลสตริงPSมีชุดองค์ประกอบอื่น ๆ ที่สามารถลบออกได้ (เช่นตัวเลข)


3
ลบเครื่องหมายวรรคตอนทั้งหมดโดยใช้นิพจน์รายการที่ใช้ได้เช่นกัน a = "*fa,fd.1lk#$" print("".join([w for w in a if w not in string.punctuation]))
Johnny Zhang

32

โค้ดด้านล่างนี้จะลบเครื่องหมายวรรคตอนทั้งหมดและอักขระที่ไม่ใช่ตัวอักษร คัดลอกมาจากหนังสือของพวกเขา

http://www.nltk.org/book/ch01.html

import nltk

s = "I can't do this now, because I'm so tired.  Please give me some time. @ sd  4 232"

words = nltk.word_tokenize(s)

words=[word.lower() for word in words if word.isalpha()]

print(words)

เอาท์พุต

['i', 'ca', 'do', 'this', 'now', 'because', 'i', 'so', 'tired', 'please', 'give', 'me', 'some', 'time', 'sd']

17
โปรดทราบว่าการใช้วิธีนี้คุณจะสูญเสียคำว่า "not" ในกรณีเช่น "can't" หรือ "don't" ซึ่งอาจสำคัญมากในการทำความเข้าใจและจัดประเภทประโยค จะดีกว่าโดยใช้ประโยคแปล (string.maketrans ("", "",), chars_to_remove) โดยที่ chars_to_remove สามารถเป็น "., ':;!?"
MikeL

3
@MikeL คุณไม่สามารถเข้าใจคำต่างๆเช่น "ไม่ได้" และ "ไม่" โดยการนำเข้าหดและหดตัว (ประโยค _ ที่นี่) ก่อนที่จะ tokanizing มันจะเปลี่ยน "ไม่ได้" เป็น "ไม่ได้" และ "ไม่" เป็น "ห้าม"
zipline86

16

ดังที่สังเกตเห็นในความคิดเห็นเริ่มต้นด้วย sent_tokenize () เนื่องจาก word_tokenize () ใช้งานได้กับประโยคเดียวเท่านั้น คุณสามารถกรองเครื่องหมายวรรคตอนด้วยตัวกรอง () และหากคุณมีสตริง Unicode ตรวจสอบให้แน่ใจว่าเป็นอ็อบเจ็กต์ Unicode (ไม่ใช่ 'str' ที่เข้ารหัสด้วยการเข้ารหัสบางอย่างเช่น 'utf-8')

from nltk.tokenize import word_tokenize, sent_tokenize

text = '''It is a blue, small, and extraordinary ball. Like no other'''
tokens = [word for sent in sent_tokenize(text) for word in word_tokenize(sent)]
print filter(lambda word: word not in ',-', tokens)

14
ความซับซ้อนส่วนใหญ่ที่เกี่ยวข้องกับโทเค็นไนเซอร์ Penn Treebank เกี่ยวข้องกับการจัดการเครื่องหมายวรรคตอนที่เหมาะสม เหตุใดจึงต้องใช้โทเค็นไนเซอร์ราคาแพงที่จัดการกับเครื่องหมายวรรคตอนได้ดีหากคุณจะตัดเครื่องหมายวรรคตอนออกเท่านั้น
rmalouf

3
word_tokenize[token for sent in sent_tokenize(text, language) for token in _treebank_word_tokenize(sent)]เป็นฟังก์ชั่นที่ให้ผลตอบแทน ดังนั้นผมคิดว่าคำตอบของคุณจะทำในสิ่ง nltk แล้วไม่: การใช้ก่อนที่จะใช้sent_tokenize() word_tokenize()อย่างน้อยนี่ก็สำหรับ nltk3
Kurt Bourbaki

2
@rmalouf เพราะคุณไม่จำเป็นต้องใช้เครื่องหมายวรรคตอนเท่านั้น? ดังนั้นคุณจึงต้องการdidและn'tแต่ไม่.
ปริTomoiagă

11

ฉันเพิ่งใช้รหัสต่อไปนี้ซึ่งลบเครื่องหมายวรรคตอนทั้งหมด:

tokens = nltk.wordpunct_tokenize(raw)

type(tokens)

text = nltk.Text(tokens)

type(text)  

words = [w.lower() for w in text if w.isalpha()]

2
ทำไมต้องแปลงโทเค็นเป็นข้อความ
Sadik

6

ฉันคิดว่าคุณต้องการการจับคู่นิพจน์ทั่วไป (รหัสต่อไปนี้อยู่ใน Python 3):

import string
import re
import nltk

s = "I can't do this now, because I'm so tired.  Please give me some time."
l = nltk.word_tokenize(s)
ll = [x for x in l if not re.fullmatch('[' + string.punctuation + ']+', x)]
print(l)
print(ll)

เอาท์พุท:

['I', 'ca', "n't", 'do', 'this', 'now', ',', 'because', 'I', "'m", 'so', 'tired', '.', 'Please', 'give', 'me', 'some', 'time', '.']
['I', 'ca', "n't", 'do', 'this', 'now', 'because', 'I', "'m", 'so', 'tired', 'Please', 'give', 'me', 'some', 'time']

ควรทำงานได้ดีในกรณีส่วนใหญ่เนื่องจากจะลบเครื่องหมายวรรคตอนในขณะที่รักษาโทเค็นเช่น "n't" ซึ่งไม่สามารถหาได้จากโทเค็น regex เช่นwordpunct_tokenize.


นอกจากนี้ยังจะลบสิ่งต่าง ๆ เช่น...และ--ในขณะที่รักษาการหดตัวซึ่งs.translate(None, string.punctuation)จะไม่
CJ Jackson

5

ถามด้วยความจริงใจคำว่าอะไร? หากสมมติฐานของคุณคือคำที่ประกอบด้วยอักขระตามตัวอักษรเท่านั้นคุณคิดผิดเนื่องจากคำเช่นcan'tจะถูกทำลายเป็นชิ้น ๆ (เช่นcanและt) หากคุณลบเครื่องหมายวรรคตอนก่อนที่จะใช้โทเค็นนซึ่งมีแนวโน้มที่จะส่งผลกระทบต่อโปรแกรมของคุณในเชิงลบ

ดังนั้นวิธีการแก้ปัญหาคือการtokenise แล้วเอาราชสกุลเครื่องหมายวรรคตอน

import string

from nltk.tokenize import word_tokenize

tokens = word_tokenize("I'm a southern salesman.")
# ['I', "'m", 'a', 'southern', 'salesman', '.']

tokens = list(filter(lambda token: token not in string.punctuation, tokens))
# ['I', "'m", 'a', 'southern', 'salesman']

... และแล้วถ้าคุณต้องการคุณสามารถแทนที่ราชสกุลบางอย่างเช่นกับ'mam


4

ฉันใช้รหัสนี้เพื่อลบเครื่องหมายวรรคตอน:

import nltk
def getTerms(sentences):
    tokens = nltk.word_tokenize(sentences)
    words = [w.lower() for w in tokens if w.isalnum()]
    print tokens
    print words

getTerms("hh, hh3h. wo shi 2 4 A . fdffdf. A&&B ")

และหากคุณต้องการตรวจสอบว่าโทเค็นเป็นคำภาษาอังกฤษที่ถูกต้องหรือไม่คุณอาจต้องใช้PyEnchant

กวดวิชา:

 import enchant
 d = enchant.Dict("en_US")
 d.check("Hello")
 d.check("Helo")
 d.suggest("Helo")

2
ระวังว่าวิธีนี้จะฆ่าการหดตัว นั่นเป็นเพราะword_tokenizeใช้โทเค็นมาตรฐานTreebankWordTokenizerซึ่งแยกการหดตัว (เช่นcan'tถึง ( ca, n't) อย่างไรก็ตามn'tไม่ใช่ตัวอักษรและตัวเลขและหลงทางในกระบวนการ
Diego Ferri

1

ลบเครื่องหมายวรรคตอน (จะลบออกรวมทั้งเป็นส่วนหนึ่งของการจัดการเครื่องหมายวรรคตอนโดยใช้โค้ดด้านล่าง)

        tbl = dict.fromkeys(i for i in range(sys.maxunicode) if unicodedata.category(chr(i)).startswith('P'))
        text_string = text_string.translate(tbl) #text_string don't have punctuation
        w = word_tokenize(text_string)  #now tokenize the string 

อินพุต / เอาต์พุตตัวอย่าง:

direct flat in oberoi esquire. 3 bhk 2195 saleable 1330 carpet. rate of 14500 final plus 1% floor rise. tax approx 9% only. flat cost with parking 3.89 cr plus taxes plus possession charger. middle floor. north door. arey and oberoi woods facing. 53% paymemt due. 1% transfer charge with buyer. total cost around 4.20 cr approx plus possession charges. rahul soni

['direct', 'flat', 'oberoi', 'esquire', '3', 'bhk', '2195', 'saleable', '1330', 'carpet', 'rate', '14500', 'final', 'plus', '1', 'floor', 'rise', 'tax', 'approx', '9', 'flat', 'cost', 'parking', '389', 'cr', 'plus', 'taxes', 'plus', 'possession', 'charger', 'middle', 'floor', 'north', 'door', 'arey', 'oberoi', 'woods', 'facing', '53', 'paymemt', 'due', '1', 'transfer', 'charge', 'buyer', 'total', 'cost', 'around', '420', 'cr', 'approx', 'plus', 'possession', 'charges', 'rahul', 'soni']


ขอบคุณมาก

1

เพียงเพิ่มคำตอบโดย @rmalouf จะไม่รวมตัวเลขใด ๆ เนื่องจาก \ w + เทียบเท่ากับ [a-zA-Z0-9_]

from nltk.tokenize import RegexpTokenizer
tokenizer = RegexpTokenizer(r'[a-zA-Z]')
tokenizer.tokenize('Eighty-seven miles to go, yet.  Onward!')

อันนี้สร้างหนึ่งโทเค็นสำหรับแต่ละตัวอักษร
Rishabh Gupta

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.