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.