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": "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SUlJOHbsGJo2bQogL1FRFAXNmzfXuczUqVMxevRorWkNGjTA559/jqeffrokYRLyurCfiL2DqKT7cLWzQ5uqIXy6NhERWR2j9FqqU6cOunXrhpdeeglLly5FTk4OJkyYgIEDB2p6LMXExKBz5874/vvvER4ejoCAAJ13a6pWrYpq1aoZI0yrdfzObUz9exuu3E/UTHOytcXLzZpjXLNwdm0nIiKrYbRxZFatWoWwsDB07twZPXr0QJs2bfD1119r5ufk5ODixYtIT083VggV0tn4OAz+bQ2uJd3Xmp6ek4O5kfvw+cEDZoqMiIio7ElCCGHuIMpSSkoK3N3dkZycXCEb/o7c+Bv23oiGWs9hVUkSDowcC19nZxNHRkREpF9pr9981pIVuZeejn+uR+lNYgBAAPj9Uul6lhEREZU3TGSsSGJGBoq6vaaSJNxNTzNJPERERMbGRMaK+Dg5oahmvGohEODiYpJ4iIiIjI2JjBXxdHRE52qhUBnolSRLEnrVDDNhVERERMbDRMbKvNGqDexVNpD1JDOvNG8JbycnE0dFRERkHExkrEwtbx+s6T8Q9X21n3Xl4eCA6e074uVmugckJCIiskRGGRCPzKuurx82DHwRFxLuIjopCS52dgivXAV2KpW5QyMiIipTTGSsWJiPL8J8in6kBBERkaVi1RIRERFZLCYyREREZLGYyBAREZHFYiJDREREFouJDBEREVksJjJERERksZjIEBERkcViIkNEREQWi4kMERERWSyrG9lXCAEASElJMXMkREREVFz51+3863hxWV0ik5qaCgAICgoycyRERERUUqmpqXB3dy92eUmUNPUp5xRFwe3bt+Hq6gpJkswdTomlpKQgKCgIN2/ehJubm7nDqbB4HMoHHgfz4zEoHyrCcRBCIDU1FYGBgZDl4rd8sbo7MrIso0qVKuYO47G5ublZ7clqSXgcygceB/PjMSgfrP04lOROTD429iUiIiKLxUSGiIiILBYTmXLG3t4e06dPh729vblDqdB4HMoHHgfz4zEoH3gc9LO6xr5ERERUcfCODBEREVksJjJERERksZjIEBERkcViIkNEREQWi4kMERERWSwmMuVAYmIiBg8eDDc3N3h4eGDUqFF48OBBsZYVQqB79+6QJAkbNmwwbqBWrqTHITExERMnTkTt2rXh6OiIqlWrYtKkSUhO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",
|
||
"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
|
||
}
|