NLTK

Материал из NLPub
Well.svg Данная статья была создана в рамках учебного задания.
Студент: Участник:Alexey Zakaldaev
Преподаватель: Антон Алексеев
Срок: 1 декабря 2021

В настоящее время задание завершено и проверено. Данная страница может свободно правиться другими участниками NLPub.


nltk (Natural Language ToolKit) — пакет библиотек и программ для символьной и статистической обработки естественного языка, написанных на языке программирования Python. Сопровождается обширной документацией, включая книгу с объяснением основных концепций, стоящих за теми задачами обработки естественного языка, которые можно выполнять с помощью NLTK.

Установка

pip

pip install nltk

conda

conda install -c anaconda nltk

Использование

Загрузка данных

Скачиваем данные, необходимые для работы библиотеки:

import nltk
nltk.download('popular')

Аргумент popular скачивает часто используемые компоненты (данные, словари, заранее обученные модели). Вместо него можно написать аргумент all, который скачает все доступные пакеты, или имя конкретного пакета.
Чтобы исследовать доступное, можно воспользоваться особым интерфейсом:

>>> import nltk                                                                                                         
>>> nltk.download()                                                                                             
NLTK Downloader                                                                                                         ---------------------------------------------------------------------------                                                 
d) Download   l) List    u) Update   c) Config   h) Help   q) Quit                                                  ---------------------------------------------------------------------------
Downloader> l                                                                                                                                                                                                                                   Packages:                                                                                                                 
[ ] abc................. Australian Broadcasting Commission 2006                                                        
[ ] alpino.............. Alpino Dutch Treebank                                                                          
[ ] averaged_perceptron_tagger Averaged Perceptron Tagger                                                               
[ ] averaged_perceptron_tagger_ru Averaged Perceptron Tagger (Russian)                                                  
[ ] basque_grammars..... Grammars for Basque           
...

Деление текста на предложения

Для разбиения на предложения используем nltk.sent_tokenize.
У этой функции есть параметр language, по-умолчанию 'english'. Замена языка на 'russian' иногда может помочь корректно разделить предложения:

>>> text = "Ай да А.С. Пушкин! Ай да хитрец!"
>>> nltk.sent_tokenize(text)
['Ай да А.С.', 'Пушкин!', 'Ай да хитрец!']
>>> nltk.sent_tokenize(text, language="russian")
['Ай да А.С. Пушкин!', 'Ай да хитрец!']

Однако использование этого значения параметра иногда может привести к неожиданным ошибкам:

>>> text = "Ты плохой муж. Я бы этим особо не хвастался."
>>> nltk.sent_tokenize(text)
['Ты плохой муж.', 'Я бы этим особо не хвастался.']
>>> nltk.sent_tokenize(text, language="russian")
['Ты плохой муж. Я бы этим особо не хвастался.']

Токенизация

Для токенизации используем nltk.word_tokenize.
У этой функции также есть параметр language, по-умолчанию 'english' и который тоже можно заменить на 'russian'.

>>> text = "Всё самое лучшее случается неожиданно."
>>> nltk.word_tokenize(text)
['Всё', 'самое', 'лучшее', 'случается', 'неожиданно', '.']

Примеров различий между методами для разных языков найти не удалось, поэтому, возможно, пока всё работает с языком по-умолчанию, то лучше использовать так.
Простое разбиение текста на токены:

import nltk
from nltk.corpus import stopwords
from string import punctuation

russian_stopwords = stopwords.words("russian")

text = "Ты не забывай, что у меня в голове опилки. Длинные слова меня только огорчают!"
tokens = nltk.word_tokenize(text.lower())
tokens = [token for token in tokens if token not in russian_stopwords and token not in punctuation]

В этом примере текст переводится в нижний регистр с помощью стандартной функции lower. После разбиения текста на токены, из их списка удаляется пунктуация по словарю string.punctuation и удаляются стоп-слова в русском языке по словарю, который получаем из nltk.corpus.stopwords[1].

В модуле nltk.tokenize есть множество классов токенизаторов и функции nltk.sent_tokenize и nltk.word_tokenize на самом деле являются обертками, которые делают вызовы к этим классам.

PunktSentenceTokenizer

Класс, разбивающий текст на предложения, к которому под капотом обращается функция nltk.sent_tokenize. Использует алгоритм без учителя для построения модели сокращённых слов, словосочетаний и слов, начинающих предложения, а затем использует эту модель для поиска границ предложений.

>>> from nltk.tokenize import PunktSentenceTokenizer
>>> tokenizer = PunktSentenceTokenizer()
>>> text = 'В этом предложении пять слов. А вот еще пять слов. Предложения из пяти слов хорошие.'
>>> tokenizer.tokenize(text)
['В этом предложении пять слов.', 'А вот еще пять слов.', 'Предложения из пяти слов хорошие.']

TreebankWordTokenizer

Класс используется для разделения предложений на слова и вызывается под капотом в функции nltk.word_tokenize.
Он предполагает, что текст уже был разделён на предложения и выполняет следующие шаги:

  • Разделяет стандартные сокращения, например don't -> do n't and they'll -> they 'll
  • Рассматривает большинство знаков препинания как отдельные токены
  • Отделяет запятые и одинарные кавычки, если за ними следует пробел
  • Отделяет точки в конце предложений
>>> from nltk.tokenize import TreebankWordTokenizer

>>> s = '''Good muffins cost $3.88\nin New York.  Please buy me\ntwo of them.\nThanks.'''
>>> TreebankWordTokenizer().tokenize(s)
['Good', 'muffins', 'cost', '$', '3.88', 'in', 'New', 'York.', 'Please', 'buy', 'me', 'two', 'of', 'them.', 'Thanks', '.']

>>> s = "They'll save and invest more."
>>> TreebankWordTokenizer().tokenize(s)
['They', "'ll", 'save', 'and', 'invest', 'more', '.']

>>> s = "hi, my name can't hello,"
>>> TreebankWordTokenizer().tokenize(s)
['hi', ',', 'my', 'name', 'ca', "n't", 'hello', ',']

TweetTokenizer

Токенизатор для твитов (не удаляет хэштеги и знаки пунктуации).

>>> from nltk.tokenize import TweetTokenizer
>>> tknzr = TweetTokenizer()
>>> s0 = "This is a cooool #dummysmiley: :-) :-P <3 and some arrows < > -> <--"
>>> tknzr.tokenize(s0)
['This', 'is', 'a', 'cooool', '#dummysmiley', ':', ':-)', ':-P', '<3', 'and', 'some', 'arrows', '<', '>', '->', '<--']

MWETokenizer

Принимает текст, который уже был разбит на токены и объединяет выражения из нескольких слов в один токен, используя словарь.

>>> from nltk.tokenize import MWETokenizer

>>> tokenizer = MWETokenizer([('a', 'little'), ('a', 'little', 'bit'), ('a', 'lot')])
>>> tokenizer.add_mwe(('in', 'spite', 'of'))

>>> tokenizer.tokenize('Testing testing testing one two three'.split())
['Testing', 'testing', 'testing', 'one', 'two', 'three']

>>> tokenizer.tokenize('This is a test in spite'.split())
['This', 'is', 'a', 'test', 'in', 'spite']

>>> tokenizer.tokenize('In a little or a little bit or a lot in spite of'.split())
['In', 'a_little', 'or', 'a_little_bit', 'or', 'a_lot', 'in_spite_of']

TextTilingTokenizer

Используется для разделения текста на абзацы.

import nltk
nltk.download('gutenberg')

alice = nltk.corpus.gutenberg.raw('carroll-alice.txt')
tokenizer = nltk.tokenize.TextTilingTokenizer()
tiles = tokenizer.tokenize(alice[140309 : ])


StanfordTokenizer

Интерфейс для Stanford Tokenizer (работает только с английским языком).

>>> from nltk.tokenize import StanfordTokenizer

>>> s = "Good muffins cost $3.88\nin New York.  Please buy me\ntwo of them.\nThanks."
>>> StanfordTokenizer().tokenize(s)
['Good', 'muffins', 'cost', '$', '3.88', 'in', 'New', 'York', '.', 'Please', 'buy', 'me', 'two', 'of', 'them', '.', 'Thanks', '.']

>>> s = "The colour of the wall is blue."
>>> StanfordTokenizer(options={"americanize": True}).tokenize(s)
['The', 'color', 'of', 'the', 'wall', 'is', 'blue', '.']

WordPunctTokenizer

Разделяет текст на последовательности алфавитных и неалфавитных символов с помощью регулярного выражения \w+|[^\w\s]+.

>>> from nltk.tokenize import WordPunctTokenizer
>>> s = "Good muffins cost $3.88\nin New York.  Please buy me\ntwo of them.\n\nThanks."
>>> WordPunctTokenizer().tokenize(s)
['Good', 'muffins', 'cost', '$', '3', '.', '88', 'in', 'New', 'York',
'.', 'Please', 'buy', 'me', 'two', 'of', 'them', '.', 'Thanks', '.']

Прочие классы

  • nltk.tokenize.RegexpTokenizer — разделяет текст с помощью регулярного выражения, которое необходимо самостоятельно задать.
  • nltk.tokenize.SExprTokenizer — разделяет текст, состоящий из S-выражений.
  • nltk.tokenize.SpaceTokenizer — разделяет токены по пробелам аналогично s.split(' ').
  • nltk.tokenize.TabTokenizer — разделяет токены по символам табуляции аналогично s.split('\t').
  • nltk.tokenize.LineTokenizer — разделяет токены по символам переноса строки аналогично s.split('\n').
  • nltk.tokenize.WhitespaceTokenizer — разделяет токены по символам пробела, табуляции или переноса строки аналогично s.split().
  • nltk.tokenize.BlanklineTokenizer — разделяет токены используя в качестве разделителя любые последовательности пробелов и табуляций.

NLTK и русский язык

Stop.svg Данная статья является непроверенным учебным заданием.
Студент: Участник:Николай Березиков
Преподаватель: Антон Алексеев
Срок: 20 мая 2022

До указанного срока статья не должна редактироваться другими участниками NLPub. По его окончании любой участник вправе исправить данную статью по своему усмотрению и удалить данное предупреждение, выводимое с помощью шаблона {{Задание}}.

См. также методические указания наших коллег с MachineLearning.ru по использованию Вики-ресурсов в учебном процессе.


Ссылки

https://www.nltk.org/ — официальный сайт и документация

См. также

Примечания

  1. В реальности токенизация может использовать капитализацию, а проверку по списку стоп-слов стоит делать после приведения токенов к словарной форме.