Files
AIM-PIbd-32-kuznetsov-A-V/lab8/lab8.ipynb
2025-05-16 21:05:37 +04:00

48 KiB
Raw Blame History

Начало лабораторной

Выгрузка документов и ресурсов NLTK

In [2]:
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()
[nltk_data] Downloading package stopwords to
[nltk_data]     C:\Users\User\AppData\Roaming\nltk_data...
[nltk_data]   Package stopwords is already up-to-date!
[nltk_data] Downloading package punkt to
[nltk_data]     C:\Users\User\AppData\Roaming\nltk_data...
[nltk_data]   Package punkt is already up-to-date!
[nltk_data] Downloading package wordnet to
[nltk_data]     C:\Users\User\AppData\Roaming\nltk_data...
[nltk_data]   Package wordnet is already up-to-date!

Предобработка и ее применение к каждому документу

In [3]:
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]

Обработка на основе лемматизации

In [4]:
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)

Удаление частых и редких слов на основе лемматизации

In [5]:
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-грамм

In [6]:
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}")
Количество признаков (N-грамм): 5000
Размерность данных N-грамм: (41, 5000)

Индексирование текста TF-IDF

In [7]:
tfidf_vectorizer = TfidfVectorizer(max_features=5000)
X_tfidf = tfidf_vectorizer.fit_transform(lemmatized_texts)

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

In [8]:
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
F1-мера: 0.40

Точность модели (0.44): Это значение означает, что модель правильно классифицировала 44% примеров из тестового набора. Это довольно низкий показатель, что указывает на слабую производительность модели.

F1-мерa (0.40): Эта метрика является гармоническим средним между точностью и полнотой. Низкое значение F1-меры (40%) дополнительно подчеркивает, что модель плохо справляется с задачей классификации.

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

In [9]:
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()
Силуэт-коэффициент: 0.07140435701058531
No description has been provided for this image

Силуэт-коэффициент варьируется от -1 до 1, где значения близкие к 1 указывают на хорошее разделение между кластерами, значения близкие к 0 на возможность наложения кластеров