На тему Natural Processing Language написано множество статей, однако во многих из них рассказывается о том, как уже используется NLP в различных отраслях. Однако, что делать тем, кто только хочет начать использовать естественный язык для своих задач? В этой статье мы изучим основы обработки естественного языка на Python, используя подход «сначала код», используя Natural Language Toolkit (NLTK).
Установка NLTK
Прежде чем погрузиться в задачи NLP, нам необходимо установить Natural Language Toolkit. NLTK это набор инструментов для обработки текста, содержащий: токенизаторы (средства для разбиения текста на более мелкие единицы — токены), лемматизаторы (инструменты приведения текстовых единиц к их базовой или корневой форме, или лемме), POS-теггеры (средства разметки частей речи) и предустановленные наборы данных. Это скорее швейцарский армейский нож для обработки естественного языка. Настройка включает в себя установку библиотеки и загрузку необходимых наборов данных и моделей.
Для установки необходимо выполнить:
$ pip install nltk
В результате мы установим базовую библиотеку NLTK, содержащую основные модули, необходимые для обработки текста.
После установки скачаем готовые наборы данных и инструменты NLTK. К ним относятся списки стоп-слов, токенизаторы и лексиконы, такие как WordNet:
import nltk
# Загрузка необходимых наборов данных и моделей
nltk.download('punkt') # Токенизаторы для токенизации предложений и слов
nltk.download('stopwords') # Список распространённых стоп-слов
nltk.download('wordnet') # Лексическая база данных WordNet для лемматизации
nltk.download('averaged_perceptron_tagger_eng') # Разметчик частей речи
nltk.download('maxent_ne_chunker_tab') # Модель распознавания именованных сущностей
nltk.download('words') # Корпус слов для NER
nltk.download('punkt_tab')
Предобработка текста
Предобработка текста — важный этап обработки естественного языка, преобразующий исходный текст в понятный и структурированный формат, который упрощает анализ. Цель — сосредоточиться на значимых компонентах текста, одновременно разбивая его на фрагменты, пригодные для обработки.
Прежде всего давайте рассмотрим три важных этапа предварительной обработки: токенизацию, удаление стоп-слов и стемминг.
Токенизация
Токенизация — одна из наиболее распространённых задач предварительной обработки. Она включает в себя разбиение текста на более мелкие фрагменты — токены. Эти токены могут быть словами, предложениями или даже частями слов, в зависимости от задачи. При этом есть два вида токенизации. Токенизация предложений разбивает текст на предложения. А токенизация слов разбивает текст на слова и знаки препинания.
В следующем коде мы используем функцию sent_tokenize из NLTK для разбиения входного текста на предложения и функцию word_tokenize для разбиения его на слова. Но мы также выполняем очень простой этап предварительной обработки, удаляя всю пунктуацию из текста:
import string
from nltk.tokenize import word_tokenize, sent_tokenize
text = "Natural Language Processing (NLP) is cool! Let's explore it."
# Удаляем знаки препинания с помощью string.punctuation
cleaned_text = ''.join(char for char in text if char not in string.punctuation)
print("Текст без знаков препинания:", cleaning_text)
# Токенизация предложений
sentences = sent_tokenize(cleaned_text)
print("Предложения:", sentences)
# Токенизация слов
words = word_tokenize(cleaned_text)
print("Слова:", words)
Это позволяет нам анализировать структуру текста как на уровне предложений, так и на уровне слов. В этом примере функция sent_tokenize(text) разбивает входную строку на предложения, возвращая список строк предложений. Результатом работы этой функции является список из двух элементов: по одному на каждое предложение исходного текста.
Затем к тому же тексту применяется функция word_tokenize(text). Она разбивает текст на отдельные слова и знаки препинания, рассматривая такие элементы, как скобки и восклицательные знаки, как отдельные токены. Но мы удалили все знаки препинания, поэтому вывод выглядит следующим образом:
Текст без знаков препинания: Natural Language Processing NLP is cool, Let's Explore it
Предложения: ['Natural Language Processing NLP is cool, Let's Explore it']
Слова: ['Natural', 'Language', 'Processing', 'NLP', 'is', 'cool', 'Lets', 'explore', 'it']
Удаление стоп-слов
Стоп-слова — это распространённые слова, такие как «the», «and» или «is», которые встречаются часто, но не несут никакой смысловой нагрузки в большинстве анализов. Удаление этих слов помогает сосредоточиться на более значимых словах в тексте.
По сути, вы отфильтровываете стоп-слова, чтобы уменьшить шум в наборе данных. Мы можем использовать корпус стоп-слов NLTK для идентификации и удаления стоп-слов из списка токенов, полученных после токенизации:
from nltk.corpus import stopwords
# Загрузить список стоп-слов NLTK
stop_words = set(stopwords.words('english'))
# Отфильтровать стоп-слова
filtered_words = [word for word in words if word.lower() not in stop_words]
print("Отфильтрованные слова:", filtered_words)
Здесь мы загружаем набор стоп-слов английского языка с помощью stopwords.words(‘english’) из NLTK. Затем мы используем генератор списков для итерации по списку токенов, сгенерированному word_tokenize. Проверяя, входит ли каждый токен (преобразованный в нижний регистр) в набор стоп-слов, мы удаляем распространённые слова, которые не влияют на смысл текста.
Вот отфильтрованный результат:
Отфильтрованные слова: ['Natural', 'Language', 'Processing', 'NLP', 'cool', 'Lets', 'explore']
Стемминг
Стемминг — это процесс приведения слов к их корневой форме путём удаления аффиксов, таких как суффиксы и префиксы. Корневая форма не всегда может быть корректным словом в словаре, но она помогает стандартизировать варианты одного и того же слова.
Стемминг Портера — это распространённый алгоритм стемминга, работающий путём удаления суффиксов. Давайте используем PorterStemmer от NLTK для стеммирования отфильтрованного списка слов:
from nltk.stem import PorterStemmer
# Инициализируем стеммирование Porter
stemmer = PorterStemmer()
# Применяем стеммирование к отфильтрованным словам
stemmed_words = [stemmer.stem(word) for word in filtered_words]
print("Стеммированные слова:", stemmed_words)
Здесь мы инициализируем PorterStemmer и используем его для обработки каждого слова из списка filtered_words.
Функция stemmer.stem() удаляет из слов распространённые суффиксы, такие как «-ing», «-ed» и «-ly», приводя их к корневой форме. Хотя стемминг помогает сократить количество вариаций слов, важно отметить, что полученные результаты не всегда могут быть корректными словарными словами.
Стеммированные слова: ['natur', 'languag', 'process', 'nlp', 'cool', 'let', 'explor']
Лемматизация
Лемматизация похожа на стемминг тем, что также приводит слова к их корневой форме. Но, в отличие от стемминга, лемматизация возвращает корректные слова из словаря. Лемматизация учитывает контекст, например, часть речи (ЧР), чтобы привести слово к лемме. Например, слова «running» и «ran» будут приведены к «run».
Лемматизация, как правило, даёт более точные результаты, чем стемминг, поскольку сохраняет слово в узнаваемой форме. Наиболее распространённым инструментом для лемматизации в NLTK является WordNetLemmatizer, использующий лексическую базу данных WordNet. Лемматизация приводит слово к лемме, учитывая его значение и контекст, а не просто удаляя аффиксы.
WordNetLemmatizer — это инструмент NLTK, обычно используемый для лемматизации. В приведённом ниже фрагменте кода мы используем WordNetLemmatizer из NLTK для лемматизации слов из ранее отфильтрованного списка:
from nltk.stem import WordNetLemmatizer
# Инициализируем лемматизатор
lemmatizer = WordNetLemmatizer()
# Лемматизируем каждое слово
lemmatized_words = [lemmatizer.lemmatize(word, pos='v') for word in filtered_words]
print("Лемматизированные слова:", lemmatized_words)
Здесь мы инициализируем WordNetLemmatizer и используем его метод lemmatize() для обработки каждого слова из списка filtered_words. Мы указываем pos=’v’, чтобы сообщить лемматизатору, что мы хотим привести глаголы в тексте к их корневой форме. Это помогает лемматизатору определить часть речи и применить правильное правило лемматизации.
Лемматизированные слова: ['Natural', 'Language', 'Processing', 'NLP', 'cool', 'Lets', 'explore']
Так чем же полезна лемматизация? Лемматизация особенно полезна, когда нужно привести слова к их корневой форме, сохранив при этом их значение. Это более точный и контекстно-зависимый метод по сравнению со стеммингом. Что делает его идеальным для задач, требующих высокой точности, таких как классификация текстов или анализ тональности.
Разметка частей речи
Разметка частей речи (POS) включает определение грамматической категории каждого слова в предложении, например, существительных, глаголов, прилагательных, наречий и т.д. Разметка POS также помогает понять синтаксическую структуру предложения, что позволяет лучше справляться с такими задачами, как анализ текста, извлечение информации и машинный перевод.
POS-теги, назначаемые словам, могут быть основаны на стандартном наборе, таком как POS-теги Penn Treebank. Например, в предложении «The dog runs fast» «dog» будет помечена как существительное (NN), «runs» — как глагол (VBZ), а «fast» — как наречие (RB).
POS-теги присваивают метки словам в предложении. Теги помогают анализировать синтаксис предложения и понимать функции слов в контексте.
С помощью NLTK вы можете выполнять POS-теги с помощью функции pos_tag, которая помечает каждое слово в списке токенов его частью речи. В следующем примере мы сначала токенизируем текст, а затем используем функцию pos_tag из NLTK для назначения POS-тегов каждому слову.
from nltk import pos_tag
# Токенизируем текст в слова
text = "She enjoys playing soccer on weekends."
# Токенизация (слова)
words = word_tokenize(text)
# POS-теги
tagged_words = pos_tag(words)
print("Tagged Words:", tagged_words)
Должен быть выведен следующий результат:
Tagged Words: [('She', 'PRP'), ('enjoys', 'VBZ'), ('playing', 'VBG'), ('soccer', 'NN'), ('on', 'IN'), ('weekends', 'NNS'), ('.', '.')]
POS-теги необходимы для понимания структуры предложения и для задач, связанных с синтаксическим анализом, таких как распознавание именованных сущностей (NER) и машинный перевод.
Распознавание именованных сущностей
Распознавание именованных сущностей (NER) — это задача обработки естественного языка, используемая для идентификации и классификации именованных сущностей в тексте, таких как имена людей, названия организаций, места и даты. Этот метод необходим для понимания и извлечения полезной информации из текста.
Вот пример:
from nltk import ne_chunk, pos_tag, word_tokenize
# Пример текста
text = "We shall visit the Eiffel Tower on our vacation to Paris."
# Разбить текст на слова
words = word_tokenize(text)
# Разметка частей речи
tagged_words = pos_tag(words)
# Распознавание именованных сущностей
named_entities = ne_chunk(tagged_words)
print("Именованные сущности:", named_entities)
В данном случае NER помогает извлечь географические данные, такие как достопримечательность и город.
Именованные сущности: (S
We/PRP
shall/MD
visit/VB
the/DT
(ORGANIZATION Eiffel/NNP Tower/NNP)
on/IN
our/PRP$
vacation/NN
to/TO
(GPE Paris/NNP)
./.)
Затем этот результат можно использовать в различных задачах, таких как реферирование статей, извлечение информации для графов знаний и многое другое.
Заключение
В этом руководстве мы рассмотрели основные концепции обработки естественного языка с использованием NLTK — от базовой предобработки текста до более сложных методов, таких как лемматизация, POS-теги и распознавание именованных сущностей.
Итак, куда двигаться дальше? Продолжая изучение NLP, вы можете рассмотреть работу над простыми задачами классификации текста, с использованием таких алгоритмов, как логистическая регрессия, машина опорных векторов и наивный байесовский алгоритм.
Также, можно попробовать анализ тональности текста с помощью таких инструментов, как VADER, или обучить свой собственный классификатор.
В NLP есть много интересных тем, позволяющих существенно упростить работу с естественным языком, сделав его понятнее для компьютера.
Если базовый NLTK — это только старт, курс OTUS «NLP / Natural Language Processing» закрывает следующий уровень: классическое NLP, трансформеры и работа с русскоязычными моделями. На практике вы пройдёте весь цикл — от подготовки текстовых данных и NER/QA-задач до собственного Telegram-бота, опираясь на уже имеющиеся ML-скиллы. Пройдите вступительный тест, чтобы узнать, подойдет ли вам программа курса.
Если хотите понять формат обучения — записывайтесь на бесплатные демо-уроки от преподавателей курса:
10 декабря: Секреты дообучения трансформеров на примере BERT. Записаться
15 декабря: Легкий старт в парсинг сайтов на Python. Записаться