Как избавиться от знаков препинания с помощью токенизатора 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()функцию Python .
— 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

Взгляните на другие варианты токенизации, которые предоставляет здесь 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как разделение сокращений. Вы можете наивно разделить на регулярное выражение \w+без необходимости в NLTK.
— sffc 08

3
Чтобы проиллюстрировать комментарий @sffc, вы можете потерять такие слова, как "Mr."
— geekazoid

его замена «n't» на «t», как от этого избавиться?
— Md. Ashikur Rahman

46

Для удаления знаков препинания вам действительно не нужен NLTK. Вы можете удалить его простым питоном. Для струнных:

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

Или для юникода:

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]))
— Джонни Чжан

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
Просто имейте в виду, что при использовании этого метода вы потеряете слово «не» в таких случаях, как «не могу» или «не делать», что может быть очень важно для понимания и классификации предложения. Лучше использовать предложение .translate (string.maketrans ("", "",), chars_to_remove), где chars_to_remove может быть "., ':;!?"
— MikeL

3
@MikeL Вы не можете обойти такие слова, как «не могу» и «не делать», импортируя сокращение и сокращение.fix (предложение_здесь) перед токанизацией. Он превратит «не могу» в «не могу», а «не могу» - в «не надо».
— zipline86

16

Как отмечалось в комментариях, начинаются с sent_tokenize (), потому что word_tokenize () работает только с одним предложением. Вы можете отфильтровать знаки препинания с помощью filter (). И если у вас есть строки 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.
— Курт Бурбаки

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
зачем преобразовывать токены в текст?
— Садик

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", которые не могут быть получены из токенизаторов регулярных выражений, таких как wordpunct_tokenize.


Это также удалит такие вещи, как ...и --при сохранении схваток, чего s.translate(None, string.punctuation)не будет,
— CJ Jackson

5

Искренне спрашиваю, что такое слово? Если ваше предположение состоит в том, что слово состоит только из буквенных символов, вы ошибаетесь, поскольку такие слова, как, can'tбудут уничтожены на части (например, canи t), если вы удалите пунктуацию до токенизации. , что, скорее всего, отрицательно повлияет на вашу программу.

Следовательно, решение состоит в том, чтобы разметить, а затем удалить знаки препинания .

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

... а затем , если вы хотите, вы можете заменить некоторые маркеры , такие как 'mс am.


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не является буквенно-цифровым и теряется в процессе.
— Диего Ферри

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!')

Это создает один токен для каждой буквы.
— Ришаб Гупта

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.