1. Введение
В прошлой статье мы с вами изучили теоретические основы обработки естественного языка (NLP) и теперь готовы перейти к практике. В мире NLP выбор подходящего языка программирования и инструментов играет ключевую роль в успешной реализации проектов. Одним из наиболее популярных языков для решения задач в этой области является Python. Его простота, читаемость и поддержка мощных библиотек делают его идеальным выбором для разработчиков.
2. Начало работы с NLP
Для начала работы с обработкой естественного языка идеально подойдут Jupyter Lab и Google Colab, так как они позволяют быстро выполнять и тестировать код по частям.
Перед тем как приступить к написанию кода, необходимо установить несколько ключевых библиотек, которые значительно упростят работу в области NLP:
nltk: Natural Language Toolkit — это основная библиотека для обработки естественного языка на Python, предоставляющая доступ ко множеству инструментов и ресурсов для работы с текстовыми данными.
spaCy: Современная и высокопроизводительная библиотека, идеально подходящая для продвинутой обработки текста, включая функции для токенизации и анализа зависимости.
gensim: Библиотека, используемая для тематического моделирования и работы с моделями на основе тем. Она позволяет эффективно обучать и применять модели, использующие векторные представления слов.
scikit-learn: Широко используемая библиотека ML, которая включает множество алгоритмов для классификации, регрессии и кластеризации. Она также предоставляет инструменты для оценки и выбора моделей.
transformers: Библиотека от Hugging Face, позволяющая работать с современными моделями трансформеров, такими как BERT и GPT. Эта библиотека стала стандартом для многих современных приложений в области NLP.\
TensorFlow/Keras или PyTorch: Это фреймворки для глубокого обучения, которые позволяют разрабатывать и обучать нейронные сети для решения сложных задач в NLP.
Чтобы установить все перечисленные библиотеки, выполните следующую команду в терминале:
pip install nltk
pip install gensim
pip install scikit-learn
pip install transformers
pip install tensorflow
pip install keras
pip install torch torchvision torchaudio
pip install -U pip setuptools wheel
pip install -U spacy
После установки spaCy необходимо загрузить языковую модель:
python -m spacy download en_core_web_sm
python -m spacy download ru_core_news_sm
3. Первые шаги с NLTK
Мы будем использовать предложение:
Хабр — это лучший сайт для написания статей, постов и новостей! Всем обязательно советую данную платформу. Она помогает делиться знаниями и узнавать новое.
3.1 Загрузка и чтение текстовых данных
import nltk
# Загрузка необходимых пакетов
nltk.download('punkt') # Токенизация
nltk.download('stopwords') # Стоп-слова
nltk.download('wordnet') # Лемматизация
nltk.download('omw-1.4') # Дополнительные данные для лемматизации
nltk.download('averaged_perceptron_tagger') # POS-теггирование
# Наш текст, с которым мы будем работать
text = "Хабр — это лучший сайт для написания статей, постов и новостей! Всем обязательно советую данную платформу. Она помогает делиться знаниями и узнавать новое."
3.2 Токенизация
Токенизация — процесс разбиения текста на отдельные элементы (токены), такие как слова или предложения.
from nltk.tokenize import sent_tokenize, word_tokenize
# Токенизация на предложения
sentences = sent_tokenize(text, language='russian')
print("Предложения:", sentences)
# Токенизация на слова
words = word_tokenize(text, language='russian')
print("Слова:", words)
Вывод:
Предложения: ['Хабр — это лучший сайт для написания статей, постов и новостей!', 'Всем обязательно советую данную платформу.', 'Она помогает делиться знаниями и узнавать новое.'] Слова: ['Хабр', '—', 'это', 'лучший', 'сайт', 'для', 'написания', 'статей', ',', 'постов', 'и', 'новостей', '!', 'Всем', 'обязательно', 'советую', 'данную', 'платформу', '.', 'Она', 'помогает', 'делиться', 'знаниями', 'и', 'узнавать', 'новое', '.']
3.3 Стемминг
Стемминг — процесс приведения слов к их корню (основе), часто без учета языковых правил.
from nltk.stem.snowball import SnowballStemmer
# Создание стеммера для русского языка
stemmer = SnowballStemmer("russian")
# Применение стеммера к словам
stemmed_words = [stemmer.stem(word) for word in words]
print("После стемминга:", stemmed_words)
Вывод:
После стемминга: ['хабр', '—', 'это', 'лучш', 'сайт', 'для', 'написан', 'стат', ',', 'пост', 'и', 'новост', '!', 'всем', 'обязательн', 'совет', 'данн', 'платформ', '.', 'она', 'помога', 'дел', 'знан', 'и', 'узнава', 'нов', '.']
3.4 Лемматизция
Лемматизация — процесс приведения слов к их нормальной форме (лемме) с учетом контекста и грамматических правил.
Для русского языка в NLTK лемматизация ограничена, поэтому часто используют библиотеку pymorphy2
.
pip install pymorphy2
import pymorphy2
morph = pymorphy2.MorphAnalyzer()
lemmatized_words = [morph.parse(word)[0].normal_form for word in words]
print("После лемматизации:", lemmatized_words)
Вывод:
После лемматизации: ['хабр', '—', 'это', 'хороший', 'сайт', 'для', 'написание', 'статья', ',', 'пост', 'и', 'новость', '!', 'весь', 'обязательно', 'советовать', 'данный', 'платформа', '.', 'она', 'помогать', 'делиться', 'знание', 'и', 'узнавать', 'новый', '.']
3.5 Удаление стоп-слов
Стоп-слова — это часто встречающиеся слова, которые обычно не несут смысловой нагрузки (например, «и», «в», «на»).
from nltk.corpus import stopwords
# Получение списка стоп-слов для русского языка
stop_words = set(stopwords.words('russian'))
# Фильтрация слов
filtered_words = [word for word in lemmatized_words if word.lower() not in stop_words and word.isalpha()]
print("После удаления стоп-слов:", filtered_words)
Вывод:
После удаления стоп-слов: ['хабр', 'хороший', 'сайт', 'написание', 'статья', 'пост', 'новость', 'обязательно', 'советовать', 'данный', 'платформа', 'помогать', 'делиться', 'знание', 'узнавать', 'новый']
3.6 Part-of-Speech (POS) теггирование
POS-теггирование — процесс определения грамматической категории (части речи) для каждого слова в тексте.
NLTK имеет ограниченную поддержку русского языка для POS-теггирования. Поэтому используем библиотеку natasha
.
pip install natasha
from natasha import Doc, MorphVocab, NewsEmbedding, NewsMorphTagger, Segmenter
# Инициализация компонентов
segmenter = Segmenter()
embedding = NewsEmbedding()
morph_tagger = NewsMorphTagger(embedding)
morph_vocab = MorphVocab()
# Обработка текста
doc = Doc(text)
doc.segment(segmenter)
doc.tag_morph(morph_tagger)
# Вывод результатов
for token in doc.tokens:
token.lemmatize(morph_vocab)
print(f"{token.text} -> {token.lemma} ({token.pos})")
Пример вывода:
Хабр -> хабрый (PROPN) — -> — (PUNCT) это -> это (PART) лучший -> хороший (ADJ) сайт -> сайт (NOUN) для -> для (ADP) написания -> написание (NOUN) статей -> стать (NOUN) , -> , (PUNCT) постов -> пост (NOUN) и -> и (CCONJ) новостей -> новость (NOUN) ! -> ! (PUNCT) Всем -> весь (PRON) обязательно -> обязательно (ADV) советую -> советовать (VERB) данную -> данный (ADJ) платформу -> платформа (NOUN) . -> . (PUNCT) Она -> она (PRON) помогает -> помогать (VERB) делиться -> делиться (VERB) знаниями -> знание (NOUN) и -> и (CCONJ) узнавать -> узнавать (VERB) новое -> новый (ADJ) . -> . (PUNCT)
3.7 Примеры кода и упражнения
Напишем функцию, которая принимает текст на русском языке и выполняет следующие операции:
Токенизация предложений и слов.
Лемматизация слов.
Удаление стоп-слов.
Возвращает очищенный список слов.
def preprocess_text(text):
# Токенизация на слова
words = word_tokenize(text, language='russian')
# Лемматизация
lemmatized_words = [morph.parse(word)[0].normal_form for word in words]
# Удаление стоп-слов и знаков пунктуации
filtered_words = [word for word in lemmatized_words if word.lower() not in stop_words and word.isalpha()]
return filtered_words
# Применение функции
clean_words = preprocess_text(text)
print(clean_words)
Вывод:
['хабр', 'хороший', 'сайт', 'написание', 'статья', 'пост', 'новость', 'обязательно', 'советовать', 'данный', 'платформа', 'помогать', 'делиться', 'знание', 'узнавать', 'новый']
4. Работа со spaCy
4.1 Загрузка и обработка текста с помощью пайплайнов
import spacy
# Загрузка модели для русского языка
nlp = spacy.load('ru_core_news_sm')
# Обработка текста
doc = nlp(text)
4.2 Токенизация, лемматизация, POS-тегирование в spaCy
for token in doc:
print(f"Слово: {token.text}, Лемма: {token.lemma_}, Часть речи: {token.pos_}")
Вывод:
Слово: Хабр, Лемма: хабр, Часть речи: PROPN Слово: —, Лемма: —, Часть речи: PUNCT Слово: это, Лемма: это, Часть речи: PART Слово: лучший, Лемма: хороший, Часть речи: ADJ Слово: сайт, Лемма: сайт, Часть речи: NOUN Слово: для, Лемма: для, Часть речи: ADP Слово: написания, Лемма: написание, Часть речи: NOUN Слово: статей, Лемма: стать, Часть речи: NOUN Слово: ,, Лемма: ,, Часть речи: PUNCT Слово: постов, Лемма: пост, Часть речи: NOUN Слово: и, Лемма: и, Часть речи: CCONJ Слово: новостей, Лемма: новость, Часть речи: NOUN Слово: !, Лемма: !, Часть речи: PUNCT Слово: Всем, Лемма: всем, Часть речи: PRON Слово: обязательно, Лемма: обязательно, Часть речи: ADV Слово: советую, Лемма: советую, Часть речи: ADJ Слово: данную, Лемма: данную, Часть речи: ADJ Слово: платформу, Лемма: платформа, Часть речи: NOUN Слово: ., Лемма: ., Часть речи: PUNCT Слово: Она, Лемма: она, Часть речи: PRON Слово: помогает, Лемма: помогать, Часть речи: VERB Слово: делиться, Лемма: делиться, Часть речи: VERB Слово: знаниями, Лемма: знание, Часть речи: NOUN Слово: и, Лемма: и, Часть речи: CCONJ Слово: узнавать, Лемма: узнавать, Часть речи: VERB Слово: новое, Лемма: новый, Часть речи: ADJ Слово: ., Лемма: ., Часть речи: PUNCT
4.3 Вывод глаголов в начальной форме
verbs = [token.lemma_ for token in doc if token.pos_ == 'VERB']
print("Глаголы в тексте:", verbs)
Вывод:
Глаголы в тексте: ['советовать', 'помогать', 'делиться', 'узнавать']
4.4 Синтаксический анализ и визуализация деревьев зависимостей
from spacy import displacy
# Выбор предложения для визуализации
sentence = list(doc.sents)[0]
# Визуализация зависимостей
displacy.render(sentence, style='dep', jupyter=True, options={'compact': True, 'distance': 100})
Вывод:
4.5 Извлечение сущностей
Напишем функцию, которая извлекает все сущности типа ORG
(организации) из нашего текста.
def extract_organizations(text):
doc = nlp(text)
orgs = [ent.text for ent in doc.ents if ent.label_ == 'ORG']
return orgs
# Применение функции
organizations = extract_organizations(text)
print("Организации в тексте:", organizations)
Вывод:
Организации в тексте: ['Хабр']
Извлечение других сущностей
Функция для извлечения сущностей определенного типа:
def extract_entities(text, entity_type):
doc = nlp(text)
entities = [ent.text for ent in doc.ents if ent.label_ == entity_type]
return entities
Функция для извлечения всех сущностей с их типами:
def extract_all_entities(text):
doc = nlp(text)
entities = [(ent.text, ent.label_) for ent in doc.ents]
return entities
Извлечение сущностей:
pers
ons = extract_entities(text, 'PER') # Извлечение персон
dates = extract_entities(text, 'DATE') # Извлечение дат
events = extract_entities(text, 'EVENT') # Извлечение мероприятий
gpes = extract_entities(text, 'GPE') # Извлечение геополитических объектов
5. Заключение
В данной статье мы рассмотрели ключевые этапы обработки текста на русском языке с использованием библиотек NLTK и spaCy. Мы научились:
Токенизировать текст на предложения и слова.
Применять стемминг и лемматизацию для приведения слов к их базовым формам.
Удалять стоп-слова, не несущие смысловой нагрузки.
Проводить POS-теггирование для определения частей речи слов в тексте.
Распознавать именованные сущности, такие как имена собственные и организации.
Выполнять синтаксический анализ для выявления структуры предложений.
В следующей части мы углубимся в сложные техники обработки естественного языка, включая: алгоритмы Word2Vec, GloVe и FastText, методы классификации текста и многое другое.
Комментарии (7)
ENick
08.12.2024 08:27"Напишем функцию, которая извлекает все сущности типа
ORG
(организации) из нашего текста"А как извлекать "свои" сущности при помощи spaCy? Напишите пожалуйста - народу это сильно понравиться, а пишите Вы очень доходчиво!
ceoofmsc Автор
08.12.2024 08:27Спасибо за ваш комментарий!
Добавил извлечение других сущностей в статью. Благодарю за помощь в том, чтобы стать лучше.
ENick
08.12.2024 08:27Спасибо за оперативный ответ! Сразу видно, что Автор ориентируется в теме!
А как извлекать не другие, а именно "свои" сущности , т.е. специфичные для определенного пита документов (нормативная документация, технические или фин отчеты, научные медицинские статьи) при помощи spaCy? Как дообучить spaCy, чтобы было можно находить сущности, отражающие конкретный виде деятельности?
ceoofmsc Автор
08.12.2024 08:27Спасибо за ваш комментарий!
Для того, чтобы извлекать свои сущности из необходимых документов, необходимо дообучить нашу базовую модель. В процесс обучения будут входить данные этапы:
Определение новых сущностей (ЗАТРАТЫ, ЛЕКАРСТВО и др.).
Сбор и разметка данных или использование готового датасета .
Подготовка датасета (представим наши данные в формате, который будет совместим со spaCy).
Настройка модели (добавляем новые метки сущностей)
Дообучение модели на наших данных
Тестирование нашей модели и оценка
Использование (проверим, как наша модель извлекает новые сущности из новых текстов)
Я считаю, что в данной статье нет смыла такое рассматривать, т.к. уж слишком большой скачок. Я рассказал про создание и обучение моделей на уже готовых датасетах в третьей части.
Если вам интересна тема самостоятельного сбора, разметки данных, подготовки датасета и дальнейшего обучения модели на этих данных, то я буду только рад рассказать про это в одной из следующих статей, дайте только знать интересно ли вам это.
Также я поискал уже готовые датасеты, которые могут помочь в обучении модели для дальнейшего извлечения новых меток для "определенного пита документов ".
Мед. сфера (для распознавания мед. статей): The NCBI Disease Corpus
Финансовая сфера: NTCIR-14: FinNum
Тех. сфера: Multi-Task Identification of Entities, Relations, and Coreferencefor Scientific Knowledge Graph Construction
Юридическая сфера: EUR-Lex Dataset
Общий датасет: Universal Dependencies
Если вы хотите сами попробовать обучить модель, то информация ниже может вам помочь))
Преобразование любого формата датасета в формат spaCy:
python -m spacy convert /путьдодатасета.форматдатасета ./output -c ner
Настройка конфигурационного файла:
python -m spacy init config config.cfg --lang ru --pipeline ner --optimize efficiency
После выполнения команды вы получите файл
config.cfg
с базовыми настройками для обучения модели на русском языке.Обучение на нашем датасете:
python -m spacy train config.cfg --paths.train ./output/train.spacy --paths.dev ./output/dev.spacy --output ./model
config.cfg: Файл конфигурации, созданный на предыдущем шаге.
paths.train: Путь к вашему обучающему набору данных (выглядит +- так
train.spacy
).paths.dev: Путь к вашему валидационному набору данных (выглядит +- так
dev.spacy
).output ./model: Директория, куда будет сохранена обученная модель.
ENick
08.12.2024 08:27"Если вам интересна тема самостоятельного сбора, разметки данных, подготовки датасета и дальнейшего обучения модели на этих данных, то я буду только рад рассказать про это в одной из следующих статей, дайте только знать интересно ли вам это. " Да, это очень интересно, а если ещё и на примере русскоязычного текста, то будет большой интерес для всех, кто уже планирует двигаться дальше RAG
ceoofmsc Автор
08.12.2024 08:27Спасибо за ваш комментарий!
Хорошо, тогда обязательно рассмотрю данную тему в одной из следующих статей.
StepanovAlex
Вот бы определение термина "понимание" увидеть.