472 lines
54 KiB
Plaintext
472 lines
54 KiB
Plaintext
|
{
|
|||
|
"cells": [
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"# Начало лабораторной работы, ух"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"### Выгрузим документы и ресурсы NLTK\n",
|
|||
|
"\n",
|
|||
|
"Обработка текстов на естественном языке (Natural Language Processing, NLP) – направление развития искусственного интеллекта и компьютерной лингвистики с целью разработки методов для понимания смысла текста и генерации грамотного текста.\n",
|
|||
|
"\n",
|
|||
|
"Популярные задачи:\n",
|
|||
|
"\n",
|
|||
|
"• Аннотирование и реферирование текстов\n",
|
|||
|
"\n",
|
|||
|
"• Проверка правописания\n",
|
|||
|
"\n",
|
|||
|
"• Машинный перевод\n",
|
|||
|
"\n",
|
|||
|
"• Понимание текста\n",
|
|||
|
"\n",
|
|||
|
"• Генерация текста\n",
|
|||
|
"\n",
|
|||
|
"• Вопросно-ответные системы\n",
|
|||
|
"\n",
|
|||
|
"NLTK (Natural Language Toolkit) — пакет библиотек и программ для символьной и статистической обработки естественного языка, написанных на Python.\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 8,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stderr",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"[nltk_data] Downloading package stopwords to\n",
|
|||
|
"[nltk_data] C:\\Users\\Admin\\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\\Admin\\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\\Admin\\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",
|
|||
|
"import nltk\n",
|
|||
|
"from nltk.corpus import stopwords\n",
|
|||
|
"from nltk.stem import WordNetLemmatizer\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\n",
|
|||
|
"nltk.download('stopwords')\n",
|
|||
|
"nltk.download('punkt')\n",
|
|||
|
"nltk.download('wordnet')\n",
|
|||
|
"\n",
|
|||
|
"# Инициализация стоп-слов и лемматизатора\n",
|
|||
|
"stop_words = set(stopwords.words('russian'))\n",
|
|||
|
"lemmatizer = WordNetLemmatizer()\n",
|
|||
|
"\n",
|
|||
|
"# Загрузка модели spaCy для русского языка\n",
|
|||
|
"nlp = spacy.load(\"ru_core_news_sm\")\n",
|
|||
|
"\n",
|
|||
|
"data_path = os.path.abspath(\".//static//csv//tz_itdocs\")\n",
|
|||
|
"\n",
|
|||
|
"if not os.path.exists(data_path):\n",
|
|||
|
" raise FileNotFoundError(f\"Папка {data_path} не найдена.\")\n",
|
|||
|
"\n",
|
|||
|
"# Инициализация Word\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": [
|
|||
|
"### Применим методы предобработки текста\n",
|
|||
|
"\n",
|
|||
|
"Предобработка текста является важным этапом, на котором решаются следующие задачи:\n",
|
|||
|
"1. Трансформация\n",
|
|||
|
"2. Токенизация\n",
|
|||
|
"3. Выделение частей речи (POS tagging)\n",
|
|||
|
"4. Нормализация\n",
|
|||
|
"5. Фильтрация\n",
|
|||
|
"\n",
|
|||
|
"Наш процесс предобработки будет выгялдеть следующим образом:\n",
|
|||
|
"* Удаление спецсимволов(удаление из текста всех символов, которые не являются буквами или цифрами (например, знаки препинания, символы @, #, $, и т.д.))\n",
|
|||
|
"* Приведение к нижнему регистру \n",
|
|||
|
"* Токенизация(разделение текста на отдельные слова или токены (например, предложение разбивается на список слов))\n",
|
|||
|
"* Удаление стоп-слов(удаление из текста слов, которые не несут смысловой нагрузки (например, предлоги, союзы, местоимения))\n",
|
|||
|
"* Фильтрация по длине токенов(удаление из текста слов, которые слишком короткие (например, меньше 2 символов) или слишком длинные)\n",
|
|||
|
"* Лемматизация по длине токенов(приведение слов к их начальной форме (лемме). Например, \"бежал\" → \"бежать\", \"кошки\" → \"кошка\")\n",
|
|||
|
"* Удаление лишних пробелов\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 9,
|
|||
|
"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": 10,
|
|||
|
"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": 32,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [],
|
|||
|
"source": [
|
|||
|
"from sklearn.feature_extraction.text import TfidfVectorizer\n",
|
|||
|
"\n",
|
|||
|
"vectorizer = TfidfVectorizer(max_df=0.8, min_df=3, max_features=10000)\n",
|
|||
|
"X_filtered = vectorizer.fit_transform(lemmatized_texts)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"### Формируем N-граммы\n",
|
|||
|
"\n",
|
|||
|
"Формирование N-грамм — это процесс разбиения текста на последовательности из N слов или символов. N-граммы широко используются в обработке NLP для анализа текста, построения языковых моделей, классификации текста и других задач.\n",
|
|||
|
"\n",
|
|||
|
"N-грамма — это последовательность из N элементов (слов, символов или других единиц).\n",
|
|||
|
"\n",
|
|||
|
"N — это число, которое определяет длину последовательности:\n",
|
|||
|
"\n",
|
|||
|
"* Униграммы (1-граммы): Отдельные слова или символы\n",
|
|||
|
"\n",
|
|||
|
"* Биграммы (2-граммы): Пары последовательных слов или символов\n",
|
|||
|
"\n",
|
|||
|
"* Триграммы (3-граммы): Тройки последовательных слов или символов\n",
|
|||
|
"\n",
|
|||
|
"И так далее.\n",
|
|||
|
"\n",
|
|||
|
"Зачем нужны N-граммы?\n",
|
|||
|
"* Анализ контекста:\n",
|
|||
|
"\n",
|
|||
|
" N-граммы позволяют учитывать контекст слов. Например, биграммы помогают понять, как слова связаны друг с другом\n",
|
|||
|
"\n",
|
|||
|
"* Построение языковых моделей:\n",
|
|||
|
"\n",
|
|||
|
" N-граммы используются для создания моделей, которые предсказывают следующее слово в последовательности (например, в автодополнении)\n",
|
|||
|
"\n",
|
|||
|
"* Классификация текста:\n",
|
|||
|
"\n",
|
|||
|
" N-граммы могут использоваться как признаки для классификации текста (например, определение тематики или тональности)\n",
|
|||
|
"\n",
|
|||
|
"* Поиск шаблонов:\n",
|
|||
|
"\n",
|
|||
|
" N-граммы помогают находить часто встречающиеся последовательности слов или символов\n",
|
|||
|
"\n",
|
|||
|
"TF-IDF векторизация — это метод преобразования текстовых данных в числовые векторы, который учитывает важность слов в документе относительно всей коллекции документов (корпуса).\n",
|
|||
|
"\n",
|
|||
|
"* TF-IDF расшифровывается как Term Frequency-Inverse Document Frequency (Частота термина – Обратная частота документа). Он состоит из двух компонентов:\n",
|
|||
|
"* TF (Term Frequency):\n",
|
|||
|
"\n",
|
|||
|
" * Частота термина в документе.\n",
|
|||
|
"\n",
|
|||
|
" * Показывает, насколько часто слово встречается в конкретном документе.\n",
|
|||
|
"\n",
|
|||
|
" Формула:\n",
|
|||
|
"\n",
|
|||
|
" TF(t,d) = Количество вхождений термина t в документ d / Общее количество терминов в документе d\n",
|
|||
|
"\n",
|
|||
|
"* IDF (Inverse Document Frequency):\n",
|
|||
|
"\n",
|
|||
|
" * Обратная частота документа.\n",
|
|||
|
"\n",
|
|||
|
" * Показывает, насколько редким является слово во всей коллекции документов.\n",
|
|||
|
"\n",
|
|||
|
" Формула:\n",
|
|||
|
" \n",
|
|||
|
" IDF(t,D) = log(Общее количество документов в корпусе D / Количество документов, содержащих термин t)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 34,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"Количество признаков (N-грамм): 10000\n",
|
|||
|
"Размерность данных N-грамм: (41, 10000)\n"
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"source": [
|
|||
|
"from sklearn.feature_extraction.text import TfidfVectorizer\n",
|
|||
|
"\n",
|
|||
|
"# Формирование N-грамм (одиночные слова до триады) с использованием TF-IDF векторизации\n",
|
|||
|
"vectorizer_ngrams = TfidfVectorizer(ngram_range=(1, 3), max_features=10000)\n",
|
|||
|
"\n",
|
|||
|
"# Подготовка N-грамм из лемматизированных текстов\n",
|
|||
|
"X_ngrams = vectorizer_ngrams.fit_transform(lemmatized_texts)\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": 35,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [],
|
|||
|
"source": [
|
|||
|
"tfidf_vectorizer = TfidfVectorizer(max_features=5000)\n",
|
|||
|
"X_tfidf = tfidf_vectorizer.fit_transform(lemmatized_texts)"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"### Выполним обучение модели с учителем или без учителя для решения задач. Оценим качество решений"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"#### Обучаем модель и оцениеваем её качество с помощью кластеризации"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 38,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"Силуэт-коэффициент: 0.09539462151298214\n"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"data": {
|
|||
|
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAjIAAAGzCAYAAAA1yP25AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABgzUlEQVR4nO3dd3wT9f8H8NdduvduKZQWyigbBMveRaYIIggiG+GHDBUVwa8KuEBBZIkoqKCiMpShIIgMWWWD7N0yCm0ppYPu5j6/P0pjQ5N00CRN+no+HnlA7j539+7dJffOfcZJQggBIiIiIgskmzsAIiIiotJiIkNEREQWi4kMERERWSwmMkRERGSxmMgQERGRxWIiQ0RERBaLiQwRERFZLCYyREREZLGYyBAREZHFYiJDREREZpWTk4OgoCAsWbKkxMtaVSKzYsUKSJKEo0ePFpo3fPhwSJKE+vXrmyEyIiIi0sfW1haTJ0/GRx99hMzMzBIta1WJjD5XrlzBjz/+aO4wiIiISI8RI0YgISEBP/30U4mWqxCJzEcffQRbW1vUrl3b3KEQERGRDh4eHnjqqaewYsWKEi1n9YnM1atX8eOPP2Ls2LEICAjQWebHH39E06ZN4ejoCC8vLwwcOBA3b97UKtOhQwfUr18fx44dQ6tWreDo6Ihq1aph6dKlWuWys7Px3nvvoWnTpnB3d4ezszPatm2LXbt2aZWLjo6GJEmYO3cuPv/8cwQHB8PR0RHt27fHmTNnNOXi4+Ph6+uLDh06oOCDyq9cuQJnZ2c8//zzWjF26NBBaztHjhyBJEmQJEkzbffu3ZAkCbt379YqO3z4cISEhGhNUxQFCxYsQIMGDeDg4ABfX19069atUPVdcffho/F99NFHkGVZKwPfu3cv+vfvj6pVq8Le3h5BQUF47bXXkJGRgUetW7cOzZo1g6urq+bvzN+vhuRXQ0ZHR2umnT17Fp6enujVqxdyc3MLxV5w/fmvgh+4ksR94cIFDBgwAL6+vnB0dETt2rXxv//9DwAwY8YMndsq+Cp47A4dOoRu3brB3d0dTk5OaN++Pfbv36+1vfx15m/Xzc0N3t7eeOWVVwrdxpUkCTNmzNCaNmfOHEiSpHX89u3bhzZt2sDHxwcODg6oXr063nrrLa31JSYm4o033kCDBg3g4uICNzc3dO/eHf/++6/W+vPPyXXr1hXaVy4uLhg+fLjWtJCQkELT1q5dC0mSCp3D8fHxGDVqFKpWrQqVSqXZhy4uLoW2pUv+Z1XXq+D5AwDXrl1D//794eXlBScnJ7Ro0QKbN2/W+bcWPIa3b99GSEgImjVrhgcPHuDBgwdwdnbGK6+8UiieW7duQaVSYdasWQD+O5ft7Oxw9+5drbKRkZGaWB/9zJbkvElISNCafvToUa3zP7/q3tCr4L5asmQJ6tWrB3t7ewQGBmL8+PFISkrS2sajnzkfHx/07NlT6/tRH32fV33HrTjxPMqYn1M/Pz/k5ORozfv555816y14PDZu3IiePXsiMDAQ9vb2CA0NxQcffAC1Wl3s/VHw+lDcz39xzuN8WVlZmD59OmrUqKH5bpwyZQqysrIK7dcuXbpg3759SExMNLj/C7IpdkkL9eGHH8LGxgZvvfUWBg0aVGj+Rx99hHfffRcDBgzA6NGjcffuXSxatAjt2rXDiRMn4OHhoSl7//599OjRAwMGDMCgQYOwZs0ajBs3DnZ2dhg5ciQAICUlBcuXL8egQYPw0ksvITU1Fd988w26du2Kw4cPo3Hjxlrb//7775Gamorx48cjMzMTCxYsQKdOnXD69Gn4+/vDz88PX375Jfr3749FixZh0qRJUBQFw4cPh6ura5ENo956663H2n+jRo3CihUr0L17d4wePRq5ubnYu3cvDh48iGbNmpV4Hxb03Xff4Z133sFnn32GF154QTN97dq1SE9Px7hx4+Dt7Y3Dhw9j0aJFuHXrFtauXaspFxkZiQEDBqBRo0aYPXs23N3dkZCQgNdee63Ef+fNmzfRrVs3hIWFYc2aNbCxKfzRCAsL0yQburZT3LhPnTqFtm3bwtbWFmPGjEFISAiuXr2K33//HR999BGeffZZ1KhRQ1P+tddeQ506dTBmzBjNtDp16gAAdu7cie7du6Np06aYPn06ZFnGd999h06dOmHv3r0IDw/XinHAgAEICQnBrFmzcPDgQSxcuBD379/H999/r3ffJCUlaS6aBaWmpqJOnToYMGAAnJycEBkZiU8//RTp6elYtGgRgLwL+4YNG9C/f39Uq1YNcXFx+Oqrr9C+fXucO3cOgYGBerdbErm5uZpj86hhw4bh77//xsSJE9GoUSOoVCp8/fXXOH78eIm2MWjQIPTo0QMAsGXLFvz8889a8+Pi4tCqVSukp6dj0qRJ8Pb2xsqVK9G7d2+sW7cOffv21bne5ORkdO/eHba2ttiyZYsmwerbty9Wr16NefPmQaVSacr//PPPEEJg8ODBWutRqVT48ccftc7L7777Dg4ODoWS1ZKeN0UZO3YsIiIiNO+HDBmCvn374tlnn9VM8/X1BZB3sZ45cyYiIiIwbtw4XLx4EV9++SWOHDmC/fv3w9bWVrNM/mdOCIGrV69i3rx56NGjB27cuFFkTFWqVCl03uo6biWJpyBjfk5TU1Pxxx9/aJ0z+o7lihUr4OLigsmTJ8PFxQU7d+7Ee++9h5SUFMyZMwcA8L///Q+jR48G8N9315gxY9C2bdsi96O+z/+j9J3HiqKgd+/e2LdvH8aMGYM6derg9OnT+Pzzz3Hp0iVs2LBBaz1NmzaFEAIHDhxAr169itwuAEBYke+++04AEEeOHBFCCHH16lVhY2MjJk2aJIQQon379qJevXqa8tHR0UKlUomPPvpIaz2nT58WNjY2WtPbt28vAIjPPvtMMy0rK0s0btxY+Pn5iezsbCGEELm5uSIrK0trfffv3xf+/v5i5MiRmmlRUVECgHB0dBS3bt3STD906JAAIF577TWtdQwaNEg4OTmJS5cuiTlz5ggAYsOGDVpl2rdvL9q3b695v2XLFgFAdOvWTRQ81P/8848AIHbu3Km1/LBhw0RwcLDm/c6dOwUAzf4rSFGUUu3D/Pg2b94sbGxsxOuvv15o3enp6YWmzZo1S0iSJK5fv66ZNm3aNAFA3LlzRzMtf7/OmTOn0DoKyj9XoqKiRGJioqhbt66oXbu2SEhI0Fm+devWomPHjoW2891335U47nbt2glXV1etaUL8t08fFRwcLIYNG1ZouqIoombNmqJr165ay6anp4tq1aqJLl26aKZNnz5dABC9e/fWWsfLL78sAIh///1XMw2AmD59uub9lClThJ+fn2jatKnW+aVLjx49RP369TXvMzMzhVqt1ioTFRUl7O3txfvvv6+ZtmvXLgFArF27ttA6nZ2dC/39j+6TJUuWCHt7e9GxY0etczgjI0PIsizGjh2rtfywYcOEs7Ozwb8l36VLlwQAMXfuXM20/M9gVFSUZtqrr74qAIi9e/dqpqWmpopq1aqJkJAQzX7I/1t37dolMjMzRYcOHYSfn5+4cuWK1na3bdsmAIg///xTa3rDhg21jkP+uTxo0CDRoEEDzfS0tDTh5uYmXnjhBa3vxdKcN3fv3tWK4ciRI4XO/4IePYfyxcfHCzs7O/HUU09pnReLFy8WAMS3336rmfbo95kQQrz99tsCgIiPj9e53YLLFvyuz/focStJPEUpy8/poEGDRK9evTTTr1+/LmRZFoMGDSp0PHR974wdO1Y4OTmJzMzMQvN0fXcVVNzPf3HP4x9++EHIsqz1uRBCiKVLlwoAYv/+/VrTb9++LQCITz75RGd8ulh11VL+3ZipU6fqnP/bb79BURQMGDAACQkJmldAQABq1qxZqDrIxsYGY8eO1by3s7PD2LFjER8fj2PHjgHI+1VkZ2cHIC8TTUxMRG5uLpo1a6bzF2CfPn1QuXJlzfvw8HA0b94cW7Zs0Sq3ePFiuLu747nnnsO7776LIUOG4JlnntH7twshMG3aNPTr1w/NmzfXmufn5wcg7xa1Ib/++iskScL06dM
|
|||
|
"text/plain": [
|
|||
|
"<Figure size 640x480 with 1 Axes>"
|
|||
|
]
|
|||
|
},
|
|||
|
"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 = 9 \n",
|
|||
|
"hierarchical_clustering = AgglomerativeClustering(n_clusters=n_clusters)\n",
|
|||
|
"hierarchical_clustering.fit(X_tfidf.toarray()) # Преобразуем X_tfidf в массив, если это необходимо\n",
|
|||
|
"\n",
|
|||
|
"# Получение меток кластеров\n",
|
|||
|
"cluster_labels = hierarchical_clustering.labels_\n",
|
|||
|
"\n",
|
|||
|
"# Оценка качества кластеризации\n",
|
|||
|
"silhouette_avg = silhouette_score(X_tfidf.toarray(), cluster_labels) # Преобразуем X_tfidf в массив\n",
|
|||
|
"print(f\"Силуэт-коэффициент: {silhouette_avg}\")\n",
|
|||
|
"\n",
|
|||
|
"# Визуализация кластеров\n",
|
|||
|
"pca = PCA(n_components=2) \n",
|
|||
|
"X_pca = pca.fit_transform(X_tfidf.toarray())\n",
|
|||
|
"\n",
|
|||
|
"plt.scatter(X_pca[:, 0], X_pca[:, 1], c=cluster_labels, cmap='viridis')\n",
|
|||
|
"plt.title(\"Иерархичсекая кластеризация документов по тематике)\")\n",
|
|||
|
"plt.show()"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"\n",
|
|||
|
"Значение силуэт коэффициента: от -1 до 0.25\t\n",
|
|||
|
"\n",
|
|||
|
"Интерпретация: плохая кластеризация. Кластеры плохо разделены или объекты ошибочно отнесены."
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"#### Обучаем модель и оцениеваем её качество с помощью классификации\n",
|
|||
|
"\n",
|
|||
|
"Разделим документы на 2 типа: техническое задание (ТЗ) и научную статью"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "code",
|
|||
|
"execution_count": 57,
|
|||
|
"metadata": {},
|
|||
|
"outputs": [
|
|||
|
{
|
|||
|
"name": "stdout",
|
|||
|
"output_type": "stream",
|
|||
|
"text": [
|
|||
|
"Точность модели: 0.56\n",
|
|||
|
"F1-мера: 0.56\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=51)\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}\")"
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
"cell_type": "markdown",
|
|||
|
"metadata": {},
|
|||
|
"source": [
|
|||
|
"Точность — доля правильно классифицированных объектов от общего числа объектов. Точность 0.56 означает, что модель правильно классифицировала 56% всех объектов. Это довольно низкий показатель, так как идеальная точность равна 1.0 (100% правильных предсказаний).\n",
|
|||
|
"\n",
|
|||
|
"F1-мера — это гармоническое среднее между точностью (Precision) и полнотой (Recall). Она учитывает как ложноположительные, так и ложноотрицательные ошибки.\n",
|
|||
|
"\n",
|
|||
|
"* Precision (Точность) — доля правильно предсказанных положительных классов среди всех предсказанных положительных классов.\n",
|
|||
|
"\n",
|
|||
|
"* Recall (Полнота) — доля правильно предсказанных положительных классов среди всех реальных положительных классов.\n",
|
|||
|
"\n",
|
|||
|
"F1-мера 0.56 указывает на то, что модель имеет среднее качество классификации. Это значение говорит о том, что модель плохо балансирует между точностью и полнотой. Например, она может либо пропускать много положительных примеров (низкий Recall), либо делать много ложноположительных предсказаний (низкий Precision).\n",
|
|||
|
"\n",
|
|||
|
"Точности указывают на то, что модель работает не очень хорошо. Это может быть связано с качеством данных, слабостью модели или дисбалансом классов. Для улучшения результатов необходимо проанализировать данные, попробовать более сложные модели и настроить гиперпараметры."
|
|||
|
]
|
|||
|
}
|
|||
|
],
|
|||
|
"metadata": {
|
|||
|
"kernelspec": {
|
|||
|
"display_name": "aimenv",
|
|||
|
"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
|
|||
|
}
|