Лучший вопрос был бы что это за ("()", "'",",")
в выводе ngram?
>>> from nltk import ngrams
>>> from nltk import word_tokenize
# Split a sentence into a list of "words"
>>> word_tokenize("This is a foo bar sentence")
['This', 'is', 'a', 'foo', 'bar', 'sentence']
>>> type(word_tokenize("This is a foo bar sentence"))
<class 'list'>
# Extract bigrams.
>>> list(ngrams(word_tokenize("This is a foo bar sentence"), 2))
[('This', 'is'), ('is', 'a'), ('a', 'foo'), ('foo', 'bar'), ('bar', 'sentence')]
# Okay, so the output is a list, no surprise.
>>> type(list(ngrams(word_tokenize("This is a foo bar sentence"), 2)))
<class 'list'>
Но какой тип ('This', 'is')
?
>>> list(ngrams(word_tokenize("This is a foo bar sentence"), 2))[0]
('This', 'is')
>>> first_thing_in_output = list(ngrams(word_tokenize("This is a foo bar sentence"), 2))[0]
>>> type(first_thing_in_output)
<class 'tuple'>
Ах, это кортеж, см. https://realpython.com/python-lists-tuples/
Что происходит при печати кортежа?
>>> print(first_thing_in_output)
('This', 'is')
Что произойдет, если вы преобразуете их в str()
?
>>> print(str(first_thing_in_output))
('This', 'is')
Но Мне нужен вывод This is
вместо ('This', 'is')
, поэтому я буду использовать функцию str.join()
, см. https://www.geeksforgeeks.org/join-function-python/:
>>> print(' '.join((first_thing_in_output)))
This is
Теперь это хороший момент, чтобы действительно пройти учебник по базовым типам Python , чтобы понять, что происходит. Кроме того, было бы хорошо понять, как работают «контейнерные» типы, например, https://github.com/usaarhat/pywarmups/blob/master/session2.md
Проходя через оригинальный пост, с кодом довольно много проблем.
Полагаю, цель кода:
- Токенизация текста и удаление стоп-слов
- Извлечение нграмм (без стоп-слов)
- Распечатайте их строковые формы и их количество
Сложная часть: stopwords.words('english')
не содержит знаков препинания, так что в итоге вы получите странные нграммы с пунктуацией:
from nltk import word_tokenize
from nltk.util import ngrams
from nltk.corpus import stopwords
text = '''The pure amnesia of her face,
newborn. I looked so far into her that, for a while, looked so far into her that, for a while looked so far into her that, for a while looked so far into her that, for a while the visual
held no memory. Little by little, I returned to myself, waking to nurse the visual held no memory. Little by little, I returned to myself, waking to nurse
'''
stoplist = set(stopwords.words('english'))
tokens = [token for token in nltk.word_tokenize(text) if token not in stoplist]
list(ngrams(tokens, 2))
[выход]:
[('The', 'pure'),
('pure', 'amnesia'),
('amnesia', 'face'),
('face', ','),
(',', 'newborn'),
('newborn', '.'),
('.', 'I'),
('I', 'looked'),
('looked', 'far'),
('far', ','),
(',', ','), ...]
Возможно, вы хотели бы дополнить стоп-лист пунктуацией, например,
from string import punctuation
from nltk import word_tokenize
from nltk.util import ngrams
from nltk.corpus import stopwords
text = '''The pure amnesia of her face,
newborn. I looked so far into her that, for a while, looked so far into her that, for a while looked so far into her that, for a while looked so far into her that, for a while the visual
held no memory. Little by little, I returned to myself, waking to nurse the visual held no memory. Little by little, I returned to myself, waking to nurse
'''
stoplist = set(stopwords.words('english') + list(punctuation))
tokens = [token for token in nltk.word_tokenize(text) if token not in stoplist]
list(ngrams(tokens, 2))
[выход]:
[('The', 'pure'),
('pure', 'amnesia'),
('amnesia', 'face'),
('face', 'newborn'),
('newborn', 'I'),
('I', 'looked'),
('looked', 'far'),
('far', 'looked'),
('looked', 'far'), ...]
Тогда вы поняли, что токены типа I
должны быть стоп-словом, но все еще существуют в вашем списке нграмм. Это потому, что список из stopwords.words('english')
в нижнем регистре, например
>>> stopwords.words('english')
[вне]:
['i',
'me',
'my',
'myself',
'we',
'our',
'ours',
'ourselves',
'you',
"you're", ...]
Поэтому, когда вы проверяете, есть ли токен в стоп-листе, вы должны также нижний регистр. ( Избегайте в нижнем регистре предложения до word_tokenize
, потому что word_tokenize
может получить подсказки от заглавных букв). Таким образом:
from string import punctuation
from nltk import word_tokenize
from nltk.util import ngrams
from nltk.corpus import stopwords
text = '''The pure amnesia of her face,
newborn. I looked so far into her that, for a while, looked so far into her that, for a while looked so far into her that, for a while looked so far into her that, for a while the visual
held no memory. Little by little, I returned to myself, waking to nurse the visual held no memory. Little by little, I returned to myself, waking to nurse
'''
stoplist = set(stopwords.words('english') + list(punctuation))
tokens = [token for token in nltk.word_tokenize(text) if token.lower() not in stoplist]
list(ngrams(tokens, 2))
[выход]:
[('pure', 'amnesia'),
('amnesia', 'face'),
('face', 'newborn'),
('newborn', 'looked'),
('looked', 'far'),
('far', 'looked'),
('looked', 'far'),
('far', 'looked'),
('looked', 'far'),
('far', 'looked'), ...]
Теперь нграммы выглядят так, как будто достигают целей:
- Токенизация текста и удаление стоп-слов
- Извлечение нграмм (без стоп-слов)
Затем в последней части, где вы хотите распечатать нграммы в файл в отсортированном порядке, вы можете использовать Freqdist.most_common()
, который будет отображаться в порядке убывания, например,
from string import punctuation
from nltk import word_tokenize
from nltk.util import ngrams
from nltk.corpus import stopwords
from nltk import FreqDist
text = '''The pure amnesia of her face,
newborn. I looked so far into her that, for a while, looked so far into her that, for a while looked so far into her that, for a while looked so far into her that, for a while the visual
held no memory. Little by little, I returned to myself, waking to nurse the visual held no memory. Little by little, I returned to myself, waking to nurse
'''
stoplist = set(stopwords.words('english') + list(punctuation))
tokens = [token for token in nltk.word_tokenize(text) if token.lower() not in stoplist]
FreqDist(ngrams(tokens, 2)).most_common()
[выход]:
[(('looked', 'far'), 4),
(('far', 'looked'), 3),
(('visual', 'held'), 2),
(('held', 'memory'), 2),
(('memory', 'Little'), 2),
(('Little', 'little'), 2),
(('little', 'returned'), 2),
(('returned', 'waking'), 2),
(('waking', 'nurse'), 2),
(('pure', 'amnesia'), 1),
(('amnesia', 'face'), 1),
(('face', 'newborn'), 1),
(('newborn', 'looked'), 1),
(('far', 'visual'), 1),
(('nurse', 'visual'), 1)]
(См. Также: Разница между коллекциями Python.Counter и nltk.probability.FreqDist )
Наконец, наконец, распечатывая это в файл, вы действительно должны использовать контекстный менеджер, http://eigenhombre.com/introduction-to-context-managers-in-python.html
with open('bigrams-list.tsv', 'w') as fout:
for bg, count in FreqDist(ngrams(tokens, 2)).most_common():
print('\t'.join([' '.join(bg), str(count)]), end='\n', file=fout)
[биграммы-list.tsv]:
looked far 4
far looked 3
visual held 2
held memory 2
memory Little 2
Little little 2
little returned 2
returned waking 2
waking nurse 2
pure amnesia 1
amnesia face 1
face newborn 1
newborn looked 1
far visual 1
nurse visual 1
Пища для размышлений
Теперь вы видите этот странный биграмм Little little
, имеет ли смысл?
Это побочный продукт удаления by
из
Мало-помалу
Так что теперь, в зависимости от того, что является конечной задачей для извлеченных вами ngram, вы, возможно, на самом деле не захотите удалять стоп-слова из списка.