NLTK belirteç kullanarak noktalama işaretlerinden nasıl kurtulurum?


125

NLTK kullanmaya yeni başlıyorum ve metinden bir kelime listesini nasıl alacağımı tam olarak anlamıyorum. Kullanırsam nltk.word_tokenize(), bir kelime ve noktalama işareti listesi alırım. Bunun yerine sadece kelimelere ihtiyacım var. Noktalama işaretlerinden nasıl kurtulabilirim? Ayrıca word_tokenizebirden fazla cümlede çalışmaz: Son kelimeye noktalar eklenir.


12
Neden noktalama işaretlerini kendiniz kaldırmıyorsunuz? nltk.word_tokenize(the_text.translate(None, string.punctuation))python3'te yapabilirsiniz, python2'de çalışmalısınız nltk.work_tokenize(the_text.translate(dict.fromkeys(string.punctuation))).
Bakuriu

3
Bu çalışmıyor. Metinde hiçbir şey olmuyor.
lizarisk

NLTK'nın varsaydığı iş akışı, önce cümlelere, ardından her cümleyi kelimelere dönüştürmenizdir. Bu yüzden word_tokenize()birden çok cümle ile çalışmaz. Noktalama işaretlerinden kurtulmak için normal bir ifade veya python isalnum()işlevini kullanabilirsiniz.
Suzana

2
Bu does : işi >>> 'with dot.'.translate(None, string.punctuation) 'with dot'(not hiçbir sonuç sonundaki nokta) gibi şeyler varsa o sorunlara neden olabilir 'end of sentence.No space'ki bu durumda onun yerine bunu: the_text.translate(string.maketrans(string.punctuation, ' '*len(string.punctuation)))beyaz boşluklarla tüm noktalama değiştirir hangi.
Bakuriu

Hay aksi, gerçekten çalışıyor, ancak Unicode dizeleriyle değil.
lizarisk

Yanıtlar:


162

Nltk'nin burada sağladığı diğer belirteçlere bir göz atın . Örneğin, simge olarak alfasayısal karakter dizilerini seçip diğer her şeyi düşüren bir simge belirleyici tanımlayabilirsiniz:

from nltk.tokenize import RegexpTokenizer

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

Çıktı:

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

55
Bu seçeneği kullanırsanız, word_tokenizekasılmaları bölmeyi sevmeye özel doğal dil özelliklerini kaybedeceğinizi unutmayın . \w+NLTK'ye ihtiyaç duymadan normal ifadede saf bir şekilde bölebilirsiniz .
sffc

3
@Sffc yorumunu açıklamak için, "Bay" gibi kelimeleri kaybedebilirsiniz.
geekazoid

'n't' yerine 't' bundan nasıl kurtulabilirim?
Md. Ashikur Rahman

46

Noktalama işaretlerini kaldırmak için gerçekten NLTK'ye ihtiyacınız yok. Basit bir python ile kaldırabilirsiniz. Dizeler için:

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

Veya unicode için:

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

ve sonra bu dizeyi belirteçleştiricinizde kullanın.

PS string modülünde, kaldırılabilen bazı başka elemanlar vardır (rakamlar gibi).


3
Aynı zamanda çalışan liste ifadesini kullanarak tüm noktalama işaretlerini kaldırın. a = "*fa,fd.1lk#$" print("".join([w for w in a if w not in string.punctuation]))
Johnny Zhang

32

Aşağıdaki kod, tüm noktalama işaretlerini ve alfabetik olmayan karakterleri kaldıracaktır. Kitaplarından kopyalandı.

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)

çıktı

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

17
Unutmayın ki bu yöntemi kullanarak, "yapamam" veya "yapamıyorum" gibi durumlarda "değil" kelimesini kaybedeceğinizi unutmayın, bu cümleyi anlamak ve sınıflandırmak için çok önemli olabilir. Cümle.translate (string.maketrans ("", "",), chars_to_remove) kullanmak daha iyidir, burada chars_to_remove "., ':;!?" Olabilir
MikeL

3
@MikeL "Yapamam" ve "Yapma" gibi sözcükleri tokanize etmeden önce kısaltmalar ve kısaltmalar.fix (cümle_burada) içe aktararak geçemezsiniz. "Yapamam" ı "yapamaz" ve "yapma", "yapma" haline dönüşecektir.
zipline86

16

Yorumlarda fark edildiği gibi sent_tokenize () ile başlar, çünkü word_tokenize () yalnızca tek bir cümle üzerinde çalışır. Noktalama işaretlerini filter () ile filtreleyebilirsiniz. Unicode dizeleriniz varsa, bunun bir unicode nesnesi olduğundan emin olun ('utf-8' gibi bir kodlama ile kodlanmış bir 'str' değil).

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 belirteç oluşturucuda yer alan karmaşıklığın çoğu, noktalama işaretlerinin uygun şekilde işlenmesiyle ilgilidir. Yalnızca noktalama işaretlerini kaldıracaksanız neden noktalama işaretlerini iyi işleyen pahalı bir belirteç kullanasınız?
rmalouf

3
word_tokenizedönen bir işlevdir [token for sent in sent_tokenize(text, language) for token in _treebank_word_tokenize(sent)]. Bu yüzden cevabınızın nltk'nin zaten yaptığı şeyi yapmak olduğunu düşünüyorum: kullanmadan sent_tokenize()önce kullanmak word_tokenize(). En azından bu nltk3 içindir.
Kurt Bourbaki

2
@rmalouf çünkü sadece noktalama işaretlerine ihtiyacınız yok mu? İstediğiniz Yani didve n'tancak.
Ciprian Tomoiagă

11

Az önce tüm noktalama işaretlerini kaldıran aşağıdaki kodu kullandım:

tokens = nltk.wordpunct_tokenize(raw)

type(tokens)

text = nltk.Text(tokens)

type(text)  

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

2
neden belirteçleri metne dönüştürmek?
Sadık

6

Sanırım bir tür düzenli ifade eşleştirmesine ihtiyacınız var (aşağıdaki kod Python 3'tedir):

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)

Çıktı:

['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" gibi belirteçleri korurken noktalama işaretlerini kaldırdığı için çoğu durumda iyi çalışmalıdır; bu wordpunct_tokenize,.


Bu aynı zamanda kasılmaları koruyarak ...ve gibi şeyleri de ortadan kaldıracak --, ki s.translate(None, string.punctuation)bu olmayacak
CJ Jackson

5

Saygılarımla soruyorum, kelime nedir? Varsayımınız bir kelimenin yalnızca alfabetik karakterlerden oluştuğuysa yanılıyorsunuz çünkü belirteçlemeden önce noktalama işaretlerini kaldırırsanızcan't gibi kelimeler parçalara ayrılacak ( canve gibi t) , , ki bu da programınızı olumsuz yönde etkileyecektir.

Dolayısıyla çözüm, noktalama işaretlerini belirtmek ve ardından kaldırmaktır .

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']

... ve sonra dilerseniz, 'mile gibi belirli simgeleri değiştirebilirsiniz am.


4

Noktalama işaretlerini kaldırmak için bu kodu kullanıyorum:

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 ")

Ve eğer bir simgenin geçerli bir İngilizce kelime olup olmadığını kontrol etmek istiyorsan, ihtiyacın olabilir PyEnchant'a olabilir.

öğretici:

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

2
Bu çözümün kasılmaları öldürdüğüne dikkat edin. Bunun nedeni , kasılmaları bölen word_tokenizestandart jetonlaştırıcıyı kullanmanızdır TreebankWordTokenizer(örneğin can't( ca, n't). Ancak n'talfanümerik değildir ve bu süreçte kaybolur.
Diego Ferri

1

Noktalama işaretini kaldırın (Aşağıdaki kodu kullanarak noktalama işaretlerinin bir kısmını kaldıracaktır)

        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 

Örnek Giriş / Çıkış:

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']


Çok teşekkür ederim

1

Çözüme @rmalouf ekleyerek, bu herhangi bir sayı içermeyecektir çünkü \ w + [a-zA-Z0-9_] ile eşdeğerdir

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

Bu, her harf için bir jeton oluşturur.
Rishabh Gupta

1

Bunu nltk (python 3.x) olmadan tek satırda yapabilirsiniz.

import string
string_text= string_text.translate(str.maketrans('','',string.punctuation))
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.