Python NLP Libary: NLTK

NLTK – это довольно сложная библиотека. Непрерывно развиваясь с 2009 года, она подходит лоя решения всех классических задач НЛП, начиная с токенизации, стемминга, лемматизации и заканчивая семантическим разбором зависимостей. Кроме того, она обладает богатым набором дополнительных возможностей, содержит различные модели для решения задач НЛП, подходит для интеграции с SciKit Learn и другими библиотеками Python.

Эта статья представляет собой краткое введение в NLTK. Вы увидите NLTK в действии, пример кода, который можно использовать для решения различных задач НЛП.

нам понадобятся: Python версии 3.11 и NLTK версии 3.8.1. Все примеры должны работать и с более новыми версиями.

Установка библиотеки NLTK

NLTK может быть установлен через Python pip:

python3 -m pip install nltk

Некоторые функции NLTK требуют использования дополнительных данных, например, загрузку стоп-слов. Для этого используется встроенный загрузчик. Вот пример:

import nltk

nltk.download('stopwords')
nltk.download('punkt')
nltk.download('averaged_perceptron_tagger')
nltk.download('reuters')

Другие части, такие как специализированный токенизатор или стоп-слова, требуют установки библиотек Java.

Примеры загрузки корпусов различных языков Github Gist.

Задачи НЛП

NLTK поддерживает функционал для решения нескольких задач НЛП. Здесь представлен их краткий обзор:

  • Обработка текста
    • Токенизация
    • Стемминг
    • Лемматизация
  • Синтаксис текста
    • Тегирование части речи
  • Семантика текста
    • Распознавание именованных сущностей
  • Семантика документа
    • Кластеризация
    • Классификация

Кроме того, NLTK поддерживает следующие дополнительные возможности:

  • Генерация синтетических датасетов
  • Управление корпусами данных
  • Использование моделей кластеризации и классификации в машинном обучении

Обработка текста

Токенизация

Токенизация – важный первый шаг в обработке текста. В целом подход к токенизации должен выбираться в зависимости от требований проекта и последующих задач НЛП. Например, если текст содержит многозначные слова, обозначающие сущности или лица, а токенизатор просто разделяет их пробелами, распознавание именованных сущностей становится затруднительным.

NLTK предоставляет простой токенизатор символов пробела, несколько встроенных токенизаторов, таких как NIST или Stanford, а также опции для создания собственных токенизаторов на основе регулярных выражений.

Приведем пример работы встроенного токенизатора предложений и слов:

from nltk.tokenize import sent_tokenize, word_tokenize

# Source: Wikipedia, Artificial Intelligence, https://en.wikipedia.org/wiki/Artificial_intelligence
paragraph = '''Artificial intelligence was founded as an academic discipline in 1956, and in the years since it has experienced several waves of optimism, followed by disappointment and the loss of funding (known as an "AI winter"), followed by new approaches, success, and renewed funding. AI research has tried and discarded many different approaches, including simulating the brain, modeling human problem solving, formal logic, large databases of knowledge, and imitating animal behavior. In the first decades of the 21st century, highly mathematical and statistical machine learning has dominated the field, and this technique has proved highly successful, helping to solve many challenging problems throughout industry and academia.'''

sentences = []
for sent in sent_tokenize(paragraph):
  sentences.append(word_tokenize(sent))

sentences[0]
# ['Artificial', 'intelligence', 'was', 'founded', 'as', 'an', 'academic', 'discipline'

Стемминг и лемматизация

Стемминг – удаление окончаний слов. Например: для слов “красивый“, “красивое“, “красивые” результатом будет – “красив“. Используется для тех же целей, что и лемматизация

Лемматизация – приведение слова в его начальную форму в зависимости от конекста. Например: для слов “решал“, “решала“, “решаемые” начальная форма будет – “решать”. Чтобы ваша модель классификации не считала эти слова разными – используем лемматизацию, чем повысим производительность и точность

Лемматизация играет особую роль, поскольку для корректной идентификации групп слов.

NLTK предоставляет несколько модулей для стемминга, таких как Porter, Lancaster и Isri. Для лемматизации предоставляется только Wordnet.

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

from nltk.stem import LancasterStemmer

sent = 'Artificial intelligence was founded as an academic discipline in 1956, and in the years since it has experienced several waves of optimism, followed by disappointment and the loss of funding (known as an "AI winter"), followed by new approaches, success, and renewed funding.'

stemmer = LancasterStemmer()

stemmed_sent = [stemmer.stem(word) for word in word_tokenize(sent)]
print(stemmed_sent)
# ['art', 'intellig', 'was', 'found', 'as', 'an', 'academ', 'disciplin',

И то же предложение, обработанное лемматизатором WordNet:

from nltk.stem import WordNetLemmatizer

sent = 'Artificial intelligence was founded as an academic discipline in 1956, and in the years since it has experienced several waves of optimism, followed by disappointment and the loss of funding (known as an "AI winter"), followed by new approaches, success, and renewed funding.'

lemmatizer = WordNetLemmatizer()

lemmas = [lemmatizer.lemmatize(word) for word in word_tokenize(sent)]
print(lemmas)
# ['Artificial', 'intelligence', 'wa', 'founded', 'a', 'an', 'academic', 'discipline'

Синтаксис текста

Тегирование части речи

NLTK также предоставляет различные теггеры частей речи (pos). С помощью встроенного теггера создаются следующие аннотации:

TagMeaning
ADJadjective
ADPadposition
ADVadverb
CONJconjunction
DETdeterminer, article
NOUNnoun
NUMnumeral
PRTparticle
PRONpronoun
VERBverb
.punctuation marks
Xother

Если взять первое предложение из статьи Википедии об искусственном интеллекте, то с помощью тегов частей речи можно получить следующий результат.

from nltk import pos_tag

sent = 'Artificial intelligence was founded as an academic discipline in 1956, and in the years since it has experienced several waves of optimism, followed by disappointment and the loss of funding (known as an "AI winter"), followed by new approaches, success, and renewed funding.'

pos_tag(sentences[0])

# [('Artificial', 'JJ'),
#  ('intelligence', 'NN'),
#  ('was', 'VBD'),
#  ('founded', 'VBN'),
#  ('as', 'IN'),
#  ('an', 'DT'),
#  ('academic', 'JJ'),
#  ('discipline', 'NN'),

Для использования других pos-теггеров NLTK, таких как Stanford или Brill, необходимо загрузить дополнительные библиотеки.

Семантика текста

Распознавание именованных сущностей

NLTK включает в себя предварительно обученные теггеры NER, однако для этого необходимо загрузить несколько дополнительных пакетов.

import nltk
nltk.download('maxent_ne_chunker')
nltk.download('punkt')
nltk.download('averaged_perceptron_tagger')
nltk.download('words')

NER-теггер использует POS-тегированное предложение и добавляет классификационные метки в представление. Его использование на примере абзаца не дало результатов, поэтому в следующем примере берется другое предложение из статьи Википедии, в которой упоминаются субъекты.

from nltk.tokenize import sent_tokenize

# Source: Wikipedia, Artificial Intelligence, https://en.wikipedia.org/wiki/Artificial_intelligence
sentence= '''
In 2011, in a Jeopardy! quiz show exhibition match, IBM's question answering system, Watson, defeated the two greatest Jeopardy! champions, Brad Rutter and Ken Jennings, by a significant margin.
'''

tagged_sentence = nltk.pos_tag(word_tokenize(sentence))
tagged_sentence
# [('In', 'IN'),
#  ('2011', 'CD'),
#  (',', ','),
#  ('in', 'IN'),
#  ('a', 'DT'),
#  ('Jeopardy', 'NN'),

print(nltk.ne_chunk(tagged_sentence))
# (S
#   In/IN
#   2011/CD
#   ,/,
#   in/IN
#   a/DT
#   Jeopardy/NN
#   !/.
#   quiz/NN
#   show/NN
#   exhibition/NN
#   match/NN
#   ,/,
#   (ORGANIZATION IBM/NNP)
#   's/POS
#   question/NN
#   answering/NN
#   system/NN
#   ,/,
#   (PERSON Watson/NNP)

Как видите, человек Watson и организация IBM получили признание.

Семантика документа

Кластеризация

В библиотеке поддерживаются три алгоритма кластеризации:

  • K-Means
  • EM-кластер
  • Среднегрупповой агломеративный кластер (GAAC)

Классификация

В NLTK реализованы следующие классификаторы (смотрите документацию):

  • Дерево решений
  • Моделирование на основе максимальной энтропии
  • Оптимизация по максимуму энтропии
  • Наивный Байес (и его варианты)

Поддерживаются внешние пакеты, такие как TextCat для идентификации языка, Java-библиотека Weka или классификаторы SciKitLearn.

Дополнительные функции

Наборы данных

NLTK предоставляет более 100 встроенных датасктов. Напрмиер новостные статьи Reuters, Treebank 2 Wall Street Journal Campus, новости Twitter или лексическая база данных WordNet.

Ниже приведен пример доступа к корпусу Reuters.

from nltk.corpus import reuters

print(reuters.categories()[:10])
#['acq', 'alum', 'barley', 'bop', 'carcass', 'castor-oil', 'cocoa', 'coconut', 'coconut-oil', 'coffee']

print(reuters.fileids()[:10])
# ['test/14826', 'test/14828', 'test/14829', 'test/14832', 'test/14833', 'test/14839', 'test/14840', 'test/14841', 'test/14842', 'test/14843']

sample = 'test/14829'
categories = reuters.categories(sample)

print(categories)
# ['acq', 'alum', 'barley', 'bop', 'carcass', 'castor-oil', 'cocoa', 'coconut', 'coconut-oil', 'coffee']

content = ""
with reuters.open(sample) as stream:
    content = stream.read()

print(f"Categories #{categories} / file #{sample}")
# Categories #['crude', 'nat-gas'] / file #test/14829

print(f"Content:\#{content}")
# Content:\#JAPAN TO REVISE LONG-TERM ENERGY DEMAND DOWNWARDS
# The Ministry of International Trade and
# Industry (MITI) will revise its long-term energy supply/demand
# outlook by August to meet a forecast downtrend in Japanese
# energy demand, ministry officials said.
#     MITI is expected to lower the projection for primary energy
# supplies in the year 2000 to 550 mln kilolitres (kl) from 600
# mln, they said.
#     The decision follows the emergence of structural changes in
# Japanese industry following the rise in the value of the yen
# and a decline in domestic electric power demand.
#     MITI is planning to work out a revised energy supply/demand
# outlook through deliberations of committee meetings of the
# Agency of Natural Resources and Energy, the officials said.
#     They said MITI will also review the breakdown of energy
# supply sources, including oil, nuclear, coal and natural gas.
#     Nuclear energy provided the bulk of Japan's electric power
# in the fiscal year ended March 31, supplying an estimated 27
# pct on a kilowatt/hour basis, followed by oil (23 pct) and
# liquefied natural gas (21 pct), they noted.

Управление корпусом

Загрузка корпуса

Объекты NLTKs corpus reader обеспечивают чтение, фильтрацию, декодирование и предварительную обработку структурированных списков файлов или zip-файлов.

Существует множество различных объектов чтения корпусов, см. полный список. Наиболее распространенными являются:

  • PlaintextCorpusReader: Чтение текстовых документов, в которых абзацы разбиты на пустые строки.
  • Markdown: Обрабатывает файлы формата markdown, в которых его категории представлены в именах файлов
  • Tagged: Специальный объект чтения корпусов, который ожидает уже помеченный корпус, например, Conl. Заметим, что для некоторых встроенных корпусных объектов уже существуют версии с тегами.
  • Twitter: Обработка твитов в формате JSON
  • XML: Обработка XML-файлов

В качестве небольшого примера загрузим PlaintextCorpusReader:

from  nltk.corpus.reader.plaintext import PlaintextCorpusReader

corpus = PlaintextCorpusReader('wikipedia_articles', r'.*\.txt')

print(corpus.fileids())
# ['AI_alignment.txt', 'AI_safety.txt', 'Artificial_intelligence.txt', 'Machine_learning.txt']

print(corpus.sents())
# [['In', 'the', 'field', 'of', 'artificial', 'intelligence', '(', 'AI', '),', 'AI', 'alignment', 'research', 'aims', 'to', 'steer', 'AI', 'systems', 'towards', 'humans', '’', 'intended', 'goals', ',', 'preferences', ',', 'or', 'ethical', 'principles', '.'], ['An', 'AI', 'system', 'is', 'considered', 'aligned', 'if', 'it', 'advances', 'the', 'intended', 'objectives', '.'], ...]

Коллекция текстов

Еще одной утилитой для доступа к структурированной информации из корпуса является класс TextCollection. ОН предоставляет следующие функции:

  • collocation_list(num, window_size): Выводит список кортежей с совпадающими словами
  • common_contexts(word, num): Вывод контекста, в котором встречается слово
  • concordance(word, width, lines): Выводит алфавитный перечень всех слов какого-либо текста с указанием контекстов их употребления для данного слова (отдельные слова или предложения)
  • concordance_list(word, width, lines): Выводит теж слова списоком
  • count(word): Количество появления слова
  • tf, idf, tf_idf: Частоты слов
  • generate: Создание случайного текста на основе языковой модели.
  • vocab: частотное распределение всех лексем

Приведем пример:

from  nltk.corpus.reader.plaintext import PlaintextCorpusReader
from nltk.text import TextCollection

corpus = PlaintextCorpusReader('wikipedia_articles', r'.*\.txt')
col = TextCollection(corpus.sents())

print(col.count('the'))
# 973

print(col.common_contexts(['intelligence']))
# artificial_( general_( artificial_. artificial_is general_,
# artificial_, artificial_in artificial_". artificial_and "_"
# artificial_was general_and general_. artificial_; artificial_" of_or
# artificial_– artificial_to artificial_: and_.

Модели кластеризации и классификации в машинном обучении

NLTK предоставляет несколько алгоритмов кластеризации и классификации. Однако прежде чем использовать тот или иной алгоритм, необходимо вручную разработать и извлечь из текстов признаки.

На странице документации API, посвященной классификации, этапы определяются следующим образом:

  • Определение признаков, релевантных задаче ML
  • Реализовать методы, извлекающие признаки из корпораций (например, частоту слов в документах)
  • Создать объект словаря Python, содержащий отдельные кортежи с (имя_функции, метки), и передать их алгоритму обучения

Проиллюстрируем это на примере из справочника NLTK по построению текстового классификатора.

Во-первых, мы составляем словарь всех слов:

from  nltk.corpus.reader.plaintext import PlaintextCorpusReader
corpus = PlaintextCorpusReader('wikipedia_articles', r'.*\.txt')

vocab = nltk.FreqDist(w.lower() for w in corpus.words())
#  FreqDist({'the': 65590, ',': 63310, '.': 52247, 'of': 39000, 'and': 30868, 'a': 30130, 'to': 27881, 'in': 24501, '-': 19867, '(': 18243, ...})

all_words = nltk.FreqDist(w.lower() for w in corpus.words())
word_features = list(all_words)
# ['the', ':']

Во-вторых, мы определяем метод, который возвращает вектор слов с однократным кодированием, выражающий наличие или отсутствие слова в документе. Полученный вектор признаков должен содержать булевы значения, чтобы его можно было использовать для задач классификации.

def document_features(document):
    document_words = set(corpus.words(document))
    features = {}
    for word in word_features:
        features['contains({})'.format(word)] = (word in document_words)
    return features

f = document_features('Artificial_intelligence.txt')
# {'contains(the)': True,
#  'contains(,)': True,
#  'contains(.)': True,

В-третьих, мы выбираем алгоритм классификации и передаем ему перлюстрированные документы.

featuresets = [(document_features(d), d) for d in corpus.fileids()]
featuresets
# featuresets = [(document_features(d), d) for d in corpus.fileids()]

train_set, test_set = featuresets[100:], featuresets[:100]
classifier = nltk.NaiveBayesClassifier.train(train_set)
# <nltk.classify.naivebayes.NaiveBayesClassifier at 0x185ec5dd0>

Резюме

NLTK – это универсальная библиотека, поддерживающая несколько задач НЛП. Для основных задач – токенизации, стемминга/лемматизации и тегирования частей речи – используются встроенные методы, а также методы из научных работ. Для управления корпусом документов NLTK работает с форматами Text, Markdown, XML и другими, а также предоставляет API для получения файлов, категорий, предложений и слов. Особенно полезен класс TextCollection, позволяющий собирать словосочетания и вычислять частоту терминов. Наконец, NLTK также предлагает алгоритмы кластеризации и классификации, такие как KMeans, Decision Trees или Naive Bayes.

+1
0
+1
0
+1
0
+1
0
+1
0

Ответить

Ваш адрес email не будет опубликован. Обязательные поля помечены *