From 3d91ba78f1886a92adf89180b9a771c5a4ba54f7 Mon Sep 17 00:00:00 2001 From: Anatoliy Date: Fri, 16 May 2025 21:05:37 +0400 Subject: [PATCH] lab8 done --- lab8/lab8.ipynb | 359 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 359 insertions(+) create mode 100644 lab8/lab8.ipynb diff --git a/lab8/lab8.ipynb b/lab8/lab8.ipynb new file mode 100644 index 0000000..fddb0e4 --- /dev/null +++ b/lab8/lab8.ipynb @@ -0,0 +1,359 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Начало лабораторной" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Выгрузка документов и ресурсов NLTK" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[nltk_data] Downloading package stopwords to\n", + "[nltk_data] C:\\Users\\User\\AppData\\Roaming\\nltk_data...\n", + "[nltk_data] Package stopwords is already up-to-date!\n", + "[nltk_data] Downloading package punkt to\n", + "[nltk_data] C:\\Users\\User\\AppData\\Roaming\\nltk_data...\n", + "[nltk_data] Package punkt is already up-to-date!\n", + "[nltk_data] Downloading package wordnet to\n", + "[nltk_data] C:\\Users\\User\\AppData\\Roaming\\nltk_data...\n", + "[nltk_data] Package wordnet is already up-to-date!\n" + ] + } + ], + "source": [ + "import os\n", + "import win32com.client\n", + "import re\n", + "from nltk.corpus import stopwords\n", + "from nltk.stem import WordNetLemmatizer\n", + "import nltk\n", + "from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer\n", + "from sklearn.cluster import KMeans\n", + "from sklearn.decomposition import PCA\n", + "import matplotlib.pyplot as plt\n", + "import spacy\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.linear_model import LogisticRegression\n", + "from sklearn.metrics import accuracy_score, f1_score\n", + "\n", + "nltk.download('stopwords')\n", + "nltk.download('punkt')\n", + "nltk.download('wordnet')\n", + "stop_words = set(stopwords.words('russian'))\n", + "lemmatizer = WordNetLemmatizer()\n", + "nlp = spacy.load(\"ru_core_news_sm\")\n", + "\n", + "data_path = os.path.abspath(\".//static//csv//www\")\n", + "\n", + "if not os.path.exists(data_path):\n", + " raise FileNotFoundError(f\"Папка {data_path} не найдена.\")\n", + "\n", + "word = win32com.client.Dispatch(\"Word.Application\")\n", + "word.visible = False\n", + "\n", + "texts = []\n", + "for filename in os.listdir(data_path):\n", + " if filename.endswith(\".doc\"):\n", + " file_path = os.path.join(data_path, filename)\n", + " try:\n", + " doc = word.Documents.Open(file_path)\n", + " text = doc.Content.Text\n", + " texts.append(text)\n", + " doc.Close(SaveChanges=False)\n", + " except Exception as e:\n", + " print(f\"Ошибка при чтении файла {filename}: {e}\")\n", + "word.Quit()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Предобработка и ее применение к каждому документу" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def preprocess_text(text):\n", + " # Удаление спецсимволов\n", + " text = re.sub(r'\\W+', ' ', text)\n", + " # Приведение к нижнему регистру\n", + " text = text.lower()\n", + " # Токенизация\n", + " tokens = text.split()\n", + " # Удаление стоп-слов, лемматизация и фильтрация по длине токенов\n", + " tokens = [\n", + " lemmatizer.lemmatize(word) \n", + " for word in tokens \n", + " if word not in stop_words and len(word) > 2\n", + " ]\n", + " # Удаление лишних пробелов\n", + " tokens = ' '.join(tokens).strip()\n", + " return tokens\n", + "\n", + "# Применение предобработки к каждому документу\n", + "texts = [preprocess_text(text) for text in texts]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Обработка на основе лемматизации" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def lemmatize_text(texts):\n", + " lemmatized_texts = []\n", + " for doc in nlp.pipe(texts):\n", + " lemmatized_texts.append(\" \".join([token.lemma_ for token in doc]))\n", + " return lemmatized_texts\n", + "\n", + "# Лемматизация текстов\n", + "lemmatized_texts = lemmatize_text(texts)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Удаление частых и редких слов на основе лемматизации" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.feature_extraction.text import TfidfVectorizer\n", + "\n", + "vectorizer = TfidfVectorizer(max_df=0.8, min_df=3, max_features=5000)\n", + "X_filtered = vectorizer.fit_transform(lemmatized_texts)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Формирование N-грамм" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Количество признаков (N-грамм): 5000\n", + "Размерность данных N-грамм: (41, 5000)\n" + ] + } + ], + "source": [ + "from sklearn.feature_extraction.text import TfidfVectorizer\n", + "\n", + "# Формирование N-грамм (одиночные слова до триады) с использованием TF-IDF векторизации\n", + "vectorizer_ngrams = TfidfVectorizer(ngram_range=(1, 3), max_features=5000)\n", + "\n", + "# Подготовка N-грамм из лемматизированных текстов\n", + "X_ngrams = vectorizer_ngrams.fit_transform(lemmatized_texts)\n", + "\n", + "# Вывод информации о сформированных N-граммах для проверки\n", + "print(f\"Количество признаков (N-грамм): {X_ngrams.shape[1]}\")\n", + "print(f\"Размерность данных N-грамм: {X_ngrams.shape}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Индексирование текста TF-IDF" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "tfidf_vectorizer = TfidfVectorizer(max_features=5000)\n", + "X_tfidf = tfidf_vectorizer.fit_transform(lemmatized_texts)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Классификация" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Точность модели: 0.44\n", + "F1-мера: 0.40\n" + ] + } + ], + "source": [ + "from sklearn.model_selection import train_test_split\n", + "from sklearn.linear_model import LogisticRegression\n", + "from sklearn.metrics import accuracy_score, f1_score, classification_report\n", + "import numpy as np\n", + "\n", + "# Определяем метки для классификации: 0 - Техническое задание (ТЗ), 1 - статья\n", + "# Исходя из примера, создаем метки для 41 текста: 20 \"ТЗ\" и 21 \"статья\"\n", + "labels = [0, 1] * 20 + [0]\n", + "\n", + "# Разделение данных на обучающую и тестовую выборки (80% на обучение, 20% на тестирование)\n", + "X_train, X_test, y_train, y_test = train_test_split(X_tfidf, labels, test_size=0.2, random_state=42)\n", + "\n", + "# Инициализируем модель логистической регрессии с максимальным количеством итераций для достижения сходимости\n", + "model = LogisticRegression(max_iter=1000)\n", + "\n", + "# Обучаем модель на обучающей выборке\n", + "model.fit(X_train, y_train)\n", + "\n", + "# Выполняем предсказание на тестовой выборке\n", + "y_pred = model.predict(X_test)\n", + "\n", + "# Оценка производительности модели\n", + "accuracy = accuracy_score(y_test, y_pred)\n", + "f1 = f1_score(y_test, y_pred, average='weighted') # Используем взвешенное среднее для F1-меры\n", + "\n", + "# Выводим результаты оценки\n", + "print(f\"Точность модели: {accuracy:.2f}\")\n", + "print(f\"F1-мера: {f1:.2f}\")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Точность модели (0.44): Это значение означает, что модель правильно классифицировала 44% примеров из тестового набора. Это довольно низкий показатель, что указывает на слабую производительность модели.\n", + "\n", + "F1-мерa (0.40): Эта метрика является гармоническим средним между точностью и полнотой. Низкое значение F1-меры (40%) дополнительно подчеркивает, что модель плохо справляется с задачей классификации." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Кластеризация" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Силуэт-коэффициент: 0.07140435701058531\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAApwAAAGzCAYAAACCWcfbAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABpI0lEQVR4nO3dd3wT9f8H8NclbdPSDaUthbJH2WALCMhQCi1DAREU+MoeKuBAUdCfDFGLAgIigiCCAsoGAZUhQxQqe2+RWWihFLppm+Tz+6MkNs1oU3pJm7yej0ce0LvPXd65u9y98/l87nOSEEKAiIiIiEgmCnsHQERERESOjQknEREREcmKCScRERERyYoJJxERERHJigknEREREcmKCScRERERyYoJJxERERHJigknEREREcmKCScRERERyYoJJxGRA7tx4wbc3d2xb98+e4dCRKXc1q1b4eXlhbt371q9rFUJ59KlSyFJEg4fPmw0b9GiRZAkCT169IBGo7E6ECIiKn4fffQRWrRogdatW+unDRo0CF5eXkZl1Wo1atasCUmSMHr0aFuGSUSlQHR0NGrWrImYmBirly2WGs4NGzbg1VdfRZs2bbBy5UoolcriWC0RET2Gu3fv4vvvv8crr7xSqPLLly/H5cuXZY6KiEqzkSNH4ptvvkFqaqpVyz12wrlnzx707dsX9erVw+bNm+Hu7v64qyQiomKwfPlyuLi44Nlnny2wrEajwSeffIImTZrIHxgRlVq9evVCVlYW1qxZY9Vyj5VwHj9+HN27d0eFChWwbds2+Pr6GpW5evUqJEky+cprxowZaNWqFcqVKwcPDw+Eh4dj7dq1Jt93+fLlaN68OcqUKQN/f3+0bdsW27dvBwBUrVrV7PtJkoSqVavq16PVajF79mzUr18f7u7uCAoKwsiRI3H//n2D96tatSq6deuG7du3o0mTJnB3d0e9evWwfv16g3K6LgdXr141eI9GjRpBkiQsXbpUP33y5MmoV68evLy84OPjgyeffBIbN240WN+ff/6J3r17o3LlylCpVAgNDcVbb72FzMxMg3LmmsfWrl0LSZKwZ88e/bQ9e/YYTQOArl27QpIkTJ482WD67t270aZNG/j7+xtsx8I2t02ePNnkfmjfvr1R2TVr1iA8PBweHh4ICAjA//73P8TFxRl91rz7EMg9HhQKBaZNmwYA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pojk5GSjZZcvX64/pzdt2tRo/96/f19/7Hh5eYmoqChx/vx5oyGHdNv1jz/+ECNGjBD+/v7Cy8tL9O/fX9y7d09f7q233hJKpVIcOHDA4H0OHz4sXFxcxKuvvmoQoyRJ4siRIwZl27VrZ3SMm5I/RiGESE1NFRMmTBA1a9YUbm5uIiAgQLRq1UrMmDHDYDgntVotpk+fLsLCwoSbm5soX7686Ny5s0Esec/FOomJiaJ8+fIGQ0tt2rRJNGrUSLi7u4uqVauKzz77THz33XcG55BLly4JT09PMWHCBIP1FWVYpLzyHqufffaZaNasmdHwZXnfJ+85rTBx5y3bqlUr4eHhIXx8fETz5s2Nhu4RwvKwSDrr1q0TTz31lPD09BSenp4iLCxMjBo1Sly4cEFfRnfOP3z4sGjZsqVwd3cXVapUEV999ZXBugp7LRVCiFdffVVUq1ZNf2178sknDYaKFEKImzdvip49ewo/Pz/h6+srevfuLW7dumW0Lt05yNJLd2zqtomHh4eIi4szeL/8x/CIESNEuXLlTJbLf16dP3++KFOmTKGHvtNvF6tKO6mCLmQlXbt27SyOCSaHKlWqWPzi79692+xFvTjdvXtXuLi4iI8++kj29yIqiYYMGSKeeuopm71fYX6QWqOwiRFRcSioEqKkGzhwoNGPoeLWpEkT8eabb1q9XLE0qROVVEuXLoVGoynS05GIHMGkSZNQu3Zt7Nu3z2CcXyIia23duhWXLl2yeEe+OUw4nUDz5s0f+y4/a/Xs2dPiI/+CgoIKvFHhcezatQtnz57FJ598gh49ehRbv0Wi0qZy5cpFftgAEZUueftuyiE6OrrIfdyZcDqBzz//3ObvOWvWLIvz69atW2CZx/HRRx9h//79aN26NebOnSvb+xAREZUUb7/9tr1DMEsSwsrxBYiIiIiIrFAs43ASEREREZnDhJOIiIiIZMU+nDLQarW4desWvL29i/UZ4kRERCQfIQRSU1MREhJi8MheenxMOGVw69YthIaG2jsMIiIiKoIbN26gUqVK9g7DoTDhlIHukX43btwwepwcERERlUwpKSkIDQ0tlkfzkiEmnDLQNaP7+Pgw4SQiIipl2B2u+LGDAhERERHJigknEREREcmKCScRERERyYoJJxERERHJigknEREREcmKCScRERERyYoJJxERERHJigknEREREcmKA78TkU3kZOfg6O+nkHw3BYGVA9CoXT0+q5iIyEkw4SQi2f367U58O345UpPS9NMCKwfg9XnD0KJruB0jIyIiW2D1AhHJass3OzBrxAKDZBMA7t64hw+7f4ZD247bJzAiIrIZJpxEJJuszCwsem+5yXlCCEAAC8f9kPt/IiJyWEw4iUg2B389hoyUDLPzhRC4evoGrpy6bsOoiIjI1phwEpFskuIfQJKkAsvdu33fBtEQEZG9MOEkItmUC/EvVHN5QMWyNoiGiIjshQknEcmmeZcn4OXnaXa+pJBQo0lVVGtQ2YZRERGRrTHhJCLZuKlc8drswSbnSQoJCoWEV78YZNugiIjI5jgOJ1ERpT1Ix2+Ld2Hnir1ITUpDaJ0QdB3ZCa17NOOA5nl0HNAOSlclFr27DIlxSfrplWqH4PV5w9C4fX07RkdERLYgCY5HUuxSUlLg6+uL5ORk+Pj42DscksHtfxMwtt1E3Lt9H0Kb+xVSKBXQarRo1aMZPlw1Fi6ujvt7TqPR4I/Vsdj09TZcP3cTHl7uaP9ia3QfHY3A0ACzy5zZd0H/pKHaETUKdUMREZGt8PotHyacMuAB69iEEBjR+G3cOB8HjVprNF+SJLw8sTdentTbDtHJT6PWYOqLX2DfhoNQKCRo8yTcHl7u+GzHRNSJqGHnKImIrMfrt3zY7kdkpZN7z+Lq6Rsmk00gNyHdMPdX5GTn2Dgy21j7xRbs33gQAPTJJgBoNVpkpj3ExOemQZ2jtld4RERUAjHhJLLSqb3noFBa/uqkJqXh5oVbNorIdjQaDTZ8+QvMtYtoNVokxT/Avo2HbBsYERGVaEw4iawkSRJQmK6HDtg/8d6t+7h3y/Ig7UpXJc7uv2CjiIiIqDRgwklkpUbt6kFrpjldxzfAG5VqV7BRRLZTUM2uteWIiMg58KpAZKUGT4WheqMqULqY/vpIEtDz9a5wdXO1cWTyK1fBHxVrVbBYw6vJ0eCJyIa2C4qIiEo8JpxEVpIkCZM3jEPZCv4Gw/roavWeer4FXhrfw07RyUuSJPQZ1x0w04dT6aJApTohCO/U2LaBERFRiea4AwUSyahCtSAsOjkT25buwa4f/0RqUhoq1Q5B15Ed8WS3cIce+L3z0Gdw/ewNrJv9C5QuCmjUWkiSBAGBshX88ekv7zv05yciIutxHE4ZcBwvcgZn/76IX77ZgSunr6OMtwfa9WmFyP+1gYeXh71DIyIqEl6/5cMaTiIqknpP1ka9J2vbOwwiIioF2O5FRERERLJiwklEREREsmLCSURERESyYsJJRERERLJiwklEREREsmLCSURERESyYsJJRERERLJiwklEREREsmLCSURERESyYsJJRERERLJiwklEREREsmLCSURERESyYsJJRERERLJiwklEREREsmLCSURERESyYsJJRERERLJiwklEREREsmLCSURERESyYsJJRERERLJiwklEREREsmLCSURERESyYsJJRERERLJiwklEREREsnKahHPevHmoWrUq3N3d0aJFCxw8eLBQy61cuRKSJKFHjx7yBkhERETkoJwi4Vy1ahXGjh2LSZMm4ejRo2jcuDGioqJw584di8tdvXoV77zzDtq0aWOjSImIiIgcj1MknF988QWGDx+OwYMHo169eliwYAHKlCmD7777zuwyGo0G/fv3x5QpU1C9enUbRktERETkWBw+4czOzsaRI0cQGRmpn6ZQKBAZGYnY2Fizy3300UcIDAzE0KFDC3yPrKwspKSkGLyIiIiIKJfDJ5yJiYnQaDQICgoymB4UFIT4+HiTy/z1119YvHgxFi1aVKj3iImJga+vr/4VGhr62HETEREROQqHTzitlZqaipdffhmLFi1CQEBAoZaZMGECkpOT9a8bN27IHCURERFR6eFi7wDkFhAQAKVSiYSEBIPpCQkJCA4ONip/+fJlXL16Fc8++6x+mlarBQC4uLjgwoULqFGjhsEyKpUKKpVKhuiJiIiISj+Hr+F0c3NDeHg4du7cqZ+m1Wqxc+dOtGzZ0qh8WFgYTp06hePHj+tfzz33HJ5++mkcP36czeVEREREVnL4Gk4AGDt2LAYOHIiIiAg0b94cs2fPRnp6OgYPHgwAGDBgACpWrIiYmBi4u7ujQYMGBsv7+fkBgNF0IiIiIiqYUyScL774Iu7evYuJEyciPj4eTZo0wdatW/U3El2/fh0KhcNX9pIDuH0lAVdP34DKww0NngqDm7ubvUMiIiIqkCSEEPYOwtGkpKTA19cXycnJ8PHxsXc45ABuX0nAnFcX4cj2E/ppnr5l8OK7PfDie935g4mIqBjw+i0fp6jhJCrNEm8l4Y1WHyDlXqrB9PTkDHz3wY+4n/AAr80ebKfoiIiICsZqEaISbmXMBiQnpkKj1pqcv+HLX3Hz4i0bR0VERFR4TDiJSjCNRoNtS3dDqzGdbAKA0kWBbUv32C4oIiIiKzHhJCrBMlMf4mF6lsUyQgCJcfdsFBEREZH1mHASlWAeXu5wVVnuai1JgF95XxtFREREZD0mnEQlmNJFiWf6tYHSxfxXVaPWIvLltjaMioiIyDpMOIlKuH7vPw93T3colMZfV0mS0KF/G9RoXNX2gRERERUSE06iEi6kRjBm7f0IVesbPlbVxc0FPV7vjHe+e81OkRERERUOB36XAQeOJTkIIXDx8GVcOXUdbh5uiOjUGD7lvO0dFhGRw+D1Wz4c+J2olJAkCXWa1USdZjXtHQoREZFV2KRORERERLJiwklEREREsmLCSURERESyYsJJRERERLJiwklEREREsmLCSURERESyYsJJRERERLJiwklEREREsmLCSURERESyYsJJRERERLJiwklEREREsmLCSURERESyYsJJRERERLJiwklEREREsmLCSURERESycrF3AETFSWjTgIfbAe1tQFEWcI+CpChr77CIiIicGhNOchgiYyVESgyATOQe2hogZSqE50hIXq9DkiQ7R0hEROScmHCSQxCZmyFSJuaZov7v3/R5gOQKeL1mj9CIiIicHvtwUqknhBYidYblMmkLcpvbiYiIyOaYcFLpl3Mqt8+mRQ+BrD22iIaIiIjyYcJJpZ9ILmS5FHnjICIiIpPYh5NKP2Vo8ZajUkEIgTP7L2DH93uQGJcE/yA/dBzQDo3a1eMNYkREJQwTTir1JJdqEK5PADnHAWhNlQAUgYBbKxtHRnJR56gx7eW5+GP1fihdFNCotVC6KLBt6W482S0cH64eCzd3N3uHSUREj7BJnRyC5DMJkFQAlPnmKABIkHw/gSTln0el1Xfv/4i9a2IBABq11uDfA78exddvLbVXaEREZAITTnIIkmtdSGVXP6rFzNOc6toIUtkfIKna2i02Kl7pKRn4ed5WCCFMzhdaga2LdyE5kX12iYhKCjapk8OQXOtAKrsYQpMAaBMAqSwkl0r2DouK2ek/zyH7YY7FMhq1Bsd2nkL7F1vbKCoiIrKECSc5HEkZBCiD7B0GySQnW11wISvKERGR/NikTkSlSs2m1Qx6TZhTO7y6/MEQEVGhMOEkolIluGogmnd5AgoX06cvhYsCDdrURZV6HAaLiKik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RETu88Hnzp2LLl26YMaMGQgJCTG77PHjxzFz5kwcPnwYFSpUsFXIRERERA7HoWs4Y2Nj4efnp082ASAyMhIKhQIHDhwwu1xGRgb69euHefPmITg4uMD3ycrKQkpKisGLiIiIiHI5dMIZHx+PwMBAg2kuLi4oW7Ys4uPjzS731ltvoVWrVujevXuh3icmJga+vr76V2ho6GPFTURERORISmXCOX78+Nxnglt4nT9/vkjr3rRpE3bt2oXZs2cXepkJEyYgOTlZ/7px40aR3puIiIjIEZXKPpxvv/02Bg0aZLFM9erVERwcjDt37hhMV6vVSEpKMttUvmvXLly+fBl+fn4G03v16oU2bdpgz549RsuoVCqoVCprPgIRERGR0yiVCWf58uVRvnz5Asu1bNkSDx48wJEjRxAeHg4gN6HUarVo0aKFyWXGjx+PYcOGGUxr2LAhZs2ahWefffbxg3cyIucsoL4ASB6AWytICh97h0REREQ2VioTzsKqW7cuoqOjMXz4cCxYsAA5OTkYPXo0XnrpJf0d6nFxcejQoQN++OEHNG/eHMHBwSZrPytXroxq1arZ+iOUWiLnIkTyeEB9Os9UNwjPgZC83oIkOfShR0RERHmUyj6c1lixYgXCwsLQoUMHdOnSBU899RQWLlyon5+Tk4MLFy4gIyPDjlE6FqG+DpHUF1CfyzcnG0j/FiJlkl3iIiIiIvuQhBDC3kE4mpSUFPj6+iI5ORk+Ps7XhKx9MAF4uBGAxmwZKeBXSC41bRYTERFRQZz9+i0nh6/hJNsSIht4uBmWkk1ACZG50UYRERERkb0x4aTiJdIBZBdcTpsoeyhERERUMjDhpOIleQEoxBBRiiDZQyEiIqKSgQknFStJcgU8egJQWiilgeTRw0YRERERkb0x4aRiJ3m9Akg+MJt0erwMyYVDTBERETkLJpxU7CRlCKRyqwHX8HwzPCF5vQHJ5wP7BEZERER2wdG3SRaSSxVI5ZZDqK8A6kuPnjQUAUnysHdoREREZGNMOElWkks1gM3nRERETo1N6kREREQkKyacRERERCQrJpxEREREJCsmnEREREQkKyacRERERCQrJpxEREREJCsmnEREREQkKyacRERERCQrJpxEREREJCs+aUgGQggAQEpKip0jISIiosLSXbd113EqPkw4ZZCamgoACA0NtXMkREREZK3U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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from sklearn.cluster import AgglomerativeClustering\n", + "from sklearn.metrics import silhouette_score\n", + "from sklearn.decomposition import PCA\n", + "import matplotlib.pyplot as plt\n", + "\n", + "# Кластеризация с использованием иерархической кластеризации\n", + "n_clusters = 3 \n", + "hierarchical_clustering = AgglomerativeClustering(n_clusters=n_clusters)\n", + "hierarchical_clustering.fit(X_tfidf.toarray()) # type: ignore # Преобразуем X_tfidf в массив, если это необходимо\n", + "\n", + "# Получение меток кластеров\n", + "cluster_labels = hierarchical_clustering.labels_\n", + "\n", + "# Оценка качества кластеризации\n", + "silhouette_avg = silhouette_score(X_tfidf.toarray(), cluster_labels) # Преобразуем X_tfidf в массив# type: ignore\n", + "print(f\"Силуэт-коэффициент: {silhouette_avg}\")\n", + "\n", + "# Визуализация кластеров*\n", + "pca = PCA(n_components=2) \n", + "X_pca = pca.fit_transform(X_tfidf.toarray())# Преобразуем X_tfidf в массив# type: ignore\n", + "\n", + "plt.scatter(X_pca[:, 0], X_pca[:, 1], c=cluster_labels, cmap='viridis')\n", + "plt.title(\"Кластеризация документов по тематике (Иерархическая кластеризация)\")\n", + "plt.show()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Силуэт-коэффициент варьируется от -1 до 1, где значения близкие к 1 указывают на хорошее разделение между кластерами, значения близкие к 0 на возможность наложения кластеров" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "aisenv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.6" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}