Лаб. работа “Обработка естественного языка”
Введение в обработку естественного языка (NLP)
Обработка естественного языка (NLP - Natural Language Processing) — это область искусственного интеллекта, которая занимается взаимодействием между компьютерами и человеческим языком. NLP объединяет методы лингвистики и машинного обучения для анализа, понимания и генерации человеческой речи и текста.
Основные задачи NLP:
- Токенизация — разделение текста на слова и предложения
- Лемматизация и стемминг — приведение слов к начальной форме
- Удаление стоп-слов — фильтрация служебных слов
- Векторизация текста — преобразование текста в числовые векторы
- Классификация текста — определение категории или тональности
- Извлечение именованных сущностей (NER) — поиск имен, организаций, дат
- Машинный перевод — перевод текста между языками
- Семантический анализ — понимание смысла текста
Теоретические основы NLP
Предобработка текста
1. Токенизация Разделение текста на отдельные элементы (токены) — слова, предложения, символы.
2. Нормализация
- Лемматизация — приведение слова к словарной форме (lemma)
- Стемминг — удаление окончаний и суффиксов для получения основы слова
3. Удаление шума
- Удаление стоп-слов (the, is, at, which, on)
- Удаление пунктуации и специальных символов
- Приведение к нижнему регистру
4. Векторизация Преобразование текста в числовые векторы:
- Bag of Words (BoW) — мешок слов
- TF-IDF — частота-обратная частота документа
- Word embeddings — векторные представления слов (Word2Vec, GloVe)
Базовая предобработка текста
import nltk
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from collections import Counter
import re
import string
# Загрузка необходимых данных NLTK
nltk.download('punkt')
nltk.download('stopwords')
nltk.download('wordnet')
nltk.download('averaged_perceptron_tagger')
from nltk.tokenize import word_tokenize, sent_tokenize
from nltk.corpus import stopwords
from nltk.stem import PorterStemmer, SnowballStemmer
from nltk.stem import WordNetLemmatizer
from nltk.tag import pos_tag
# Пример текста для анализа
sample_text = """
Machine learning is a subset of artificial intelligence that focuses on the development of algorithms
and statistical models that enable computer systems to improve their performance on a specific task
through experience. Deep learning, a subset of machine learning, uses neural networks with multiple
layers to model and understand complex patterns in data. Natural language processing is another
important field that combines computer science and linguistics to enable computers to understand,
interpret, and generate human language.
"""
print("=== Исходный текст ===")
print(sample_text)Токенизация
# Токенизация на предложения
sentences = sent_tokenize(sample_text)
print(f"\n=== Токенизация на предложения ({len(sentences)} предложений) ===")
for i, sent in enumerate(sentences, 1):
print(f"{i}: {sent.strip()}")
# Токенизация на слова
words = word_tokenize(sample_text)
print(f"\n=== Токенизация на слова ({len(words)} слов) ===")
print("Первые 20 слов:", words[:20])Удаление стоп-слов и пунктуации
# Получение списка стоп-слов
stop_words = set(stopwords.words('english'))
print(f"\n=== Стоп-слова (первые 10) ===")
print(list(stop_words)[:10])
# Удаление стоп-слов и пунктуации
def clean_text(text):
# Приведение к нижнему регистру
text = text.lower()
# Удаление цифр и специальных символов
text = re.sub(r'[^a-zA-Z\s]', '', text)
# Токенизация
words = word_tokenize(text)
# Удаление стоп-слов
words = [word for word in words if word not in stop_words and len(word) > 2]
return words
cleaned_words = clean_text(sample_text)
print(f"\n=== Очищенные слова ({len(cleaned_words)} слов) ===")
print("Первые 20:", cleaned_words[:20])Стемминг и лемматизация
# Инициализация стеммеров и лемматизатора
porter_stemmer = PorterStemmer()
snowball_stemmer = SnowballStemmer('english')
lemmatizer = WordNetLemmatizer()
# Сравнение стемминга и лемматизации
sample_words = ['running', 'flies', 'leaves', 'better', 'computers', 'learning']
comparison_df = pd.DataFrame({
'Original': sample_words,
'Porter Stemmer': [porter_stemmer.stem(word) for word in sample_words],
'Snowball Stemmer': [snowball_stemmer.stem(word) for word in sample_words],
'WordNet Lemmatizer': [lemmatizer.lemmatize(word) for word in sample_words]
})
print("\n=== Сравнение стемминга и лемматизации ===")
print(comparison_df)Векторизация текста
Bag of Words (BoW)
from sklearn.feature_extraction.text import CountVectorizer
# Подготовка корпуса текстов
corpus = [
"Machine learning is great for data analysis",
"Deep learning uses neural networks",
"Natural language processing helps computers understand text",
"Artificial intelligence includes machine learning and deep learning",
"Text analysis is important for natural language processing"
]
# Создание векторизатора
bow_vectorizer = CountVectorizer(max_features=20, stop_words='english')
bow_matrix = bow_vectorizer.fit_transform(corpus)
# Получение словаря
feature_names = bow_vectorizer.get_feature_names_out()
# Преобразование в DataFrame для удобства
bow_df = pd.DataFrame(bow_matrix.toarray(), columns=feature_names)
print("=== Bag of Words векторизация ===")
print(bow_df)
# Визуализация
plt.figure(figsize=(12, 8))
sns.heatmap(bow_df, annot=True, cmap='Blues', fmt='d')
plt.title('Bag of Words представление текстов')
plt.xlabel('Слова')
plt.ylabel('Документы')
plt.show()TF-IDF (Term Frequency - Inverse Document Frequency)
from sklearn.feature_extraction.text import TfidfVectorizer
# Создание TF-IDF векторизатора
tfidf_vectorizer = TfidfVectorizer(max_features=20, stop_words='english')
tfidf_matrix = tfidf_vectorizer.fit_transform(corpus)
# Получение словаря
feature_names_tfidf = tfidf_vectorizer.get_feature_names_out()
# Преобразование в DataFrame
tfidf_df = pd.DataFrame(tfidf_matrix.toarray(), columns=feature_names_tfidf)
print("\n=== TF-IDF векторизация ===")
print(tfidf_df.round(3))
# Визуализация
plt.figure(figsize=(12, 8))
sns.heatmap(tfidf_df, annot=True, cmap='viridis', fmt='.3f')
plt.title('TF-IDF представление текстов')
plt.xlabel('Слова')
plt.ylabel('Документы')
plt.show()Классификация текста
Загрузка и подготовка данных
from sklearn.datasets import fetch_20newsgroups
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import MultinomialNB
from sklearn.svm import SVC
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report, accuracy_score, confusion_matrix
# Загрузка датасета (берем 4 категории для простоты)
categories = ['alt.atheism', 'sci.space', 'talk.politics.misc', 'rec.sport.baseball']
newsgroups = fetch_20newsgroups(subset='all', categories=categories,
remove=('headers', 'footers', 'quotes'))
print(f"=== Датасет 20 Newsgroups ===")
print(f"Количество текстов: {len(newsgroups.data)}")
print(f"Количество категорий: {len(newsgroups.target_names)}")
print(f"Названия категорий: {newsgroups.target_names}")
# Пример текстов
print(f"\n=== Примеры текстов ===")
for i in range(2):
print(f"\nКатегория: {newsgroups.target_names[newsgroups.target[i]]}")
print(f"Текст (первые 200 символов): {newsgroups.data[i][:200]}...")Предобработка и векторизация
# Разделение на train/test
X_train, X_test, y_train, y_test = train_test_split(newsgroups.data, newsgroups.target,
test_size=0.3, random_state=42,
stratify=newsgroups.target)
# Создание TF-IDF векторизатора
vectorizer = TfidfVectorizer(max_features=5000, stop_words='english',
ngram_range=(1, 2), min_df=2, max_df=0.95)
# Векторизация текстов
X_train_tfidf = vectorizer.fit_transform(X_train)
X_test_tfidf = vectorizer.transform(X_test)
print(f"Размерность обучающей выборки: {X_train_tfidf.shape}")
print(f"Размерность тестовой выборки: {X_test_tfidf.shape}")Обучение и оценка моделей
# 1. Наивный байесовский классификатор
nb_model = MultinomialNB()
nb_model.fit(X_train_tfidf, y_train)
nb_pred = nb_model.predict(X_test_tfidf)
# 2. Логистическая регрессия
lr_model = LogisticRegression(max_iter=1000, random_state=42)
lr_model.fit(X_train_tfidf, y_train)
lr_pred = lr_model.predict(X_test_tfidf)
# 3. SVM
svm_model = SVC(kernel='linear', random_state=42)
svm_model.fit(X_train_tfidf, y_train)
svm_pred = svm_model.predict(X_test_tfidf)
# Оценка качества
models = {
'Naive Bayes': (nb_model, nb_pred),
'Logistic Regression': (lr_model, lr_pred),
'SVM': (svm_model, svm_pred)
}
print("=== Результаты классификации ===")
for name, (model, predictions) in models.items():
accuracy = accuracy_score(y_test, predictions)
print(f"\n{name}:")
print(f"Accuracy: {accuracy:.3f}")
print("Classification Report:")
print(classification_report(y_test, predictions, target_names=newsgroups.target_names))Визуализация результатов
# Сравнение accuracy моделей
model_names = list(models.keys())
accuracies = [accuracy_score(y_test, pred) for _, pred in models.values()]
plt.figure(figsize=(10, 6))
bars = plt.bar(model_names, accuracies, color=['skyblue', 'lightgreen', 'salmon'])
plt.title('Сравнение точности моделей классификации текстов')
plt.xlabel('Модель')
plt.ylabel('Accuracy')
plt.ylim(0, 1)
# Добавление значений на столбцы
for bar, acc in zip(bars, accuracies):
plt.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.01,
f'{acc:.3f}', ha='center', va='bottom')
plt.grid(True, alpha=0.3)
plt.show()
# Матрицы ошибок
fig, axes = plt.subplots(1, 3, figsize=(18, 5))
for idx, (name, (_, predictions)) in enumerate(models.items()):
cm = confusion_matrix(y_test, predictions)
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues',
xticklabels=newsgroups.target_names,
yticklabels=newsgroups.target_names,
ax=axes[idx])
axes[idx].set_title(f'Confusion Matrix - {name}')
axes[idx].set_xlabel('Предсказанная категория')
axes[idx].set_ylabel('Истинная категория')
plt.tight_layout()
plt.show()Анализ тональности (Sentiment Analysis)
# Создание простого датасета для анализа тональности
sentiment_data = {
'text': [
"This movie is absolutely fantastic and amazing!",
"I love this product, it's the best I've ever used.",
"The service was terrible and the staff was rude.",
"This is the worst experience I've ever had.",
"The food was okay, nothing special.",
"Average quality, meets expectations.",
"Great customer service and fast delivery!",
"I'm disappointed with the quality of this item.",
"Excellent work, very professional and efficient.",
"Not bad, but could be much better."
],
'sentiment': [1, 1, 0, 0, 2, 2, 1, 0, 1, 2] # 1: positive, 0: negative, 2: neutral
}
sentiment_df = pd.DataFrame(sentiment_data)
print("=== Датасент для анализа тональности ===")
print(sentiment_df)
# Векторизация
sentiment_vectorizer = TfidfVectorizer(max_features=100, stop_words='english')
X_sentiment = sentiment_vectorizer.fit_transform(sentiment_df['text'])
y_sentiment = sentiment_df['sentiment']
# Обучение модели
sentiment_model = MultinomialNB()
sentiment_model.fit(X_sentiment, y_sentiment)
# Тестирование на новых текстах
test_texts = [
"This is absolutely wonderful and perfect!",
"I'm very unhappy with this purchase.",
"It's fine, nothing extraordinary."
]
X_test_sentiment = sentiment_vectorizer.transform(test_texts)
predictions = sentiment_model.predict(X_test_sentiment)
# Вывод результатов
sentiment_labels = {0: 'Negative', 1: 'Positive', 2: 'Neutral'}
print("\n=== Результаты анализа тональности ===")
for text, pred in zip(test_texts, predictions):
print(f"Text: {text}")
print(f"Predicted sentiment: {sentiment_labels[pred]}\n")Извлечение именованных сущностей (NER)
import spacy
from collections import Counter
# Загрузка модели spaCy (если не установлена, нужно скачать: python -m spacy download en_core_web_sm)
try:
nlp = spacy.load("en_core_web_sm")
# Текст для анализа
ner_text = """
Apple Inc. was founded by Steve Jobs, Steve Wozniak, and Ronald Wayne in Cupertino, California
in 1976. The company went public on December 12, 1980. Tim Cook is the current CEO of Apple,
which is headquartered at One Apple Park Way in Cupertino. Microsoft Corporation, founded by
Bill Gates and Paul Allen in 1975, is based in Redmond, Washington.
"""
# Обработка текста
doc = nlp(ner_text)
# Извлечение сущностей
entities = []
for ent in doc.ents:
entities.append((ent.text, ent.label_))
print("=== Извлеченные именованные сущности ===")
for entity, label in entities:
print(f"{entity} ({label})")
# Подсчет типов сущностей
entity_counts = Counter([label for _, label in entities])
# Визуализация
plt.figure(figsize=(10, 6))
plt.bar(entity_counts.keys(), entity_counts.values())
plt.title('Распределение типов именованных сущностей')
plt.xlabel('Тип сущности')
plt.ylabel('Количество')
plt.show()
except OSError:
print("Модель spaCy не найдена. Установите: python -m spacy download en_core_web_sm")Самостоятельные задания
Задание 1: Создание чат-бота с базовым пониманием намерений
Цель: Разработать простого чат-бота, который может распознавать намерения пользователя.
Задачи:
- Создайте датасет с примерами фраз и их намерениями (например: приветствие, прощание, вопрос о погоде, запрос помощи)
- Реализуйте предобработку текстов (токенизация, удаление стоп-слов, лемматизация)
- Обучите классификатор (Naive Bayes или Logistic Regression) для распознавания намерений
- Создайте простой интерфейс взаимодействия с ботом
- Протестируйте бота на новых фразах и оцените точность распознавания
Пример намерений:
- greeting: “Hello”, “Hi there”, “Good morning”
- weather: “What’s the weather like?”, “Is it going to rain?”
- goodbye: “Bye”, “See you later”, “Goodbye”
- help: “I need help”, “Can you assist me?”
Формат отчета:
- Описание созданного датасета
- Код предобработки и обучения модели
- Примеры диалогов с ботом
- Оценка точности распознавания намерений
- Проблемы и пути улучшения
Задание 2: Классификация новостей по тематике
Цель: Создать систему автоматической классификации новостных статей.
Задачи:
- Используйте расширенный датасет 20 Newsgroups (все 20 категорий)
- Сравните различные методы векторизации (BoW, TF-IDF, n-граммы разной длины)
- Реализуйте и сравните несколько алгоритмов классификации
- Проанализируйте наиболее информативные слова для каждой категории
- Визуализируйте результаты с помощью матриц ошибок и графиков
Дополнительные задачи:
- Используйте GridSearchCV для подбора оптимальных параметров
- Примените технику feature selection для улучшения результатов
- Сравните бинарную и многоклассовую классификацию
Формат отчета:
- Сравнение методов векторизации
- Таблица результатов различных алгоритмов
- Анализ важных признаков для каждой категории
- Рекомендации по выбору параметров
Задание 3: Анализ тональности отзывов на фильмы
Цель: Разработать систему анализа тональности для отзывов на фильмы.
Задачи:
- Создайте или найдите датасет отзывов на фильмы с метками (позитивный/негативный)
- Реализуйте предобработку текста с учетом специфики отзывов
- Обучите несколько моделей для бинарной классификации тональности
- Проанализируйте ошибки модели и найдите причины неправильной классификации
- Создайте визуализацию наиболее характерных слов для каждого класса
Расширенные задачи:
- Используйте Word2Vec или другие word embeddings
- Реализуйте систему объяснений (почему отзыв классифицирован как позитивный/негативный)
- Добавьте категорию “нейтральный” и сравните результаты
Формат отчета:
- Описание датасета и предобработки
- Сравнение моделей и их точности
- Примеры правильно и неправильно классифицированных отзывов
- Анализ характерных слов и фраз
Задание 4: Извлечение ключевой информации из текста
Цель: Создать систему извлечения ключевой информации из новостных текстов.
Задачи:
- Используйте датасет новостных статей или создайте свой
- Реализуйте извлечение следующей информации:
- Именованные сущности (люди, организации, места)
- Даты и временные выражения
- Ключевые слова и фразы
- Сводка текста (summarization)
- Создайте структурированное представление извлеченной информации
- Разработайте простой интерфейс для отображения результатов
- Оцените точность извлечения информации
Дополнительные задачи:
- Реализуйте простую систему вопросно-ответной системы на основе извлеченной информации
- Создайте граф знаний (knowledge graph)