48 KiB
Начало лабораторной¶
Выгрузка документов и ресурсов NLTK
import os
import win32com.client
import re
from nltk.corpus import stopwords
from nltk.stem import WordNetLemmatizer
import nltk
from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
import spacy
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, f1_score
nltk.download('stopwords')
nltk.download('punkt')
nltk.download('wordnet')
stop_words = set(stopwords.words('russian'))
lemmatizer = WordNetLemmatizer()
nlp = spacy.load("ru_core_news_sm")
data_path = os.path.abspath(".//static//csv//www")
if not os.path.exists(data_path):
raise FileNotFoundError(f"Папка {data_path} не найдена.")
word = win32com.client.Dispatch("Word.Application")
word.visible = False
texts = []
for filename in os.listdir(data_path):
if filename.endswith(".doc"):
file_path = os.path.join(data_path, filename)
try:
doc = word.Documents.Open(file_path)
text = doc.Content.Text
texts.append(text)
doc.Close(SaveChanges=False)
except Exception as e:
print(f"Ошибка при чтении файла {filename}: {e}")
word.Quit()
Предобработка и ее применение к каждому документу
def preprocess_text(text):
# Удаление спецсимволов
text = re.sub(r'\W+', ' ', text)
# Приведение к нижнему регистру
text = text.lower()
# Токенизация
tokens = text.split()
# Удаление стоп-слов, лемматизация и фильтрация по длине токенов
tokens = [
lemmatizer.lemmatize(word)
for word in tokens
if word not in stop_words and len(word) > 2
]
# Удаление лишних пробелов
tokens = ' '.join(tokens).strip()
return tokens
# Применение предобработки к каждому документу
texts = [preprocess_text(text) for text in texts]
Обработка на основе лемматизации
def lemmatize_text(texts):
lemmatized_texts = []
for doc in nlp.pipe(texts):
lemmatized_texts.append(" ".join([token.lemma_ for token in doc]))
return lemmatized_texts
# Лемматизация текстов
lemmatized_texts = lemmatize_text(texts)
Удаление частых и редких слов на основе лемматизации
from sklearn.feature_extraction.text import TfidfVectorizer
vectorizer = TfidfVectorizer(max_df=0.8, min_df=3, max_features=5000)
X_filtered = vectorizer.fit_transform(lemmatized_texts)
Формирование N-грамм
from sklearn.feature_extraction.text import TfidfVectorizer
# Формирование N-грамм (одиночные слова до триады) с использованием TF-IDF векторизации
vectorizer_ngrams = TfidfVectorizer(ngram_range=(1, 3), max_features=5000)
# Подготовка N-грамм из лемматизированных текстов
X_ngrams = vectorizer_ngrams.fit_transform(lemmatized_texts)
# Вывод информации о сформированных N-граммах для проверки
print(f"Количество признаков (N-грамм): {X_ngrams.shape[1]}")
print(f"Размерность данных N-грамм: {X_ngrams.shape}")
Индексирование текста TF-IDF
tfidf_vectorizer = TfidfVectorizer(max_features=5000)
X_tfidf = tfidf_vectorizer.fit_transform(lemmatized_texts)
Классификация¶
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, f1_score, classification_report
import numpy as np
# Определяем метки для классификации: 0 - Техническое задание (ТЗ), 1 - статья
# Исходя из примера, создаем метки для 41 текста: 20 "ТЗ" и 21 "статья"
labels = [0, 1] * 20 + [0]
# Разделение данных на обучающую и тестовую выборки (80% на обучение, 20% на тестирование)
X_train, X_test, y_train, y_test = train_test_split(X_tfidf, labels, test_size=0.2, random_state=42)
# Инициализируем модель логистической регрессии с максимальным количеством итераций для достижения сходимости
model = LogisticRegression(max_iter=1000)
# Обучаем модель на обучающей выборке
model.fit(X_train, y_train)
# Выполняем предсказание на тестовой выборке
y_pred = model.predict(X_test)
# Оценка производительности модели
accuracy = accuracy_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred, average='weighted') # Используем взвешенное среднее для F1-меры
# Выводим результаты оценки
print(f"Точность модели: {accuracy:.2f}")
print(f"F1-мера: {f1:.2f}")
Точность модели (0.44): Это значение означает, что модель правильно классифицировала 44% примеров из тестового набора. Это довольно низкий показатель, что указывает на слабую производительность модели.
F1-мерa (0.40): Эта метрика является гармоническим средним между точностью и полнотой. Низкое значение F1-меры (40%) дополнительно подчеркивает, что модель плохо справляется с задачей классификации.
Кластеризация¶
from sklearn.cluster import AgglomerativeClustering
from sklearn.metrics import silhouette_score
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
# Кластеризация с использованием иерархической кластеризации
n_clusters = 3
hierarchical_clustering = AgglomerativeClustering(n_clusters=n_clusters)
hierarchical_clustering.fit(X_tfidf.toarray()) # type: ignore # Преобразуем X_tfidf в массив, если это необходимо
# Получение меток кластеров
cluster_labels = hierarchical_clustering.labels_
# Оценка качества кластеризации
silhouette_avg = silhouette_score(X_tfidf.toarray(), cluster_labels) # Преобразуем X_tfidf в массив# type: ignore
print(f"Силуэт-коэффициент: {silhouette_avg}")
# Визуализация кластеров*
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_tfidf.toarray())# Преобразуем X_tfidf в массив# type: ignore
plt.scatter(X_pca[:, 0], X_pca[:, 1], c=cluster_labels, cmap='viridis')
plt.title("Кластеризация документов по тематике (Иерархическая кластеризация)")
plt.show()
Силуэт-коэффициент варьируется от -1 до 1, где значения близкие к 1 указывают на хорошее разделение между кластерами, значения близкие к 0 на возможность наложения кластеров