{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "gz18QPRz03Ec" }, "source": [ "### 1) В среде Google Colab создали новый блокнот (notebook). Импортировали необходимые для работы библиотеки и модули." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "mr9IszuQ1ANG" }, "outputs": [], "source": [ "# импорт модулей\n", "import os\n", "\n", "from tensorflow import keras\n", "from tensorflow.keras import layers\n", "from tensorflow.keras.models import Sequential\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n" ] }, { "cell_type": "markdown", "metadata": { "id": "FFRtE0TN1AiA" }, "source": [ "### 2) Загрузили набор данных IMDb, содержащий оцифрованные отзывы на фильмы, размеченные на два класса: позитивные и негативные. При загрузке набора данных параметр seed выбрали равным значению (4k – 1)=3, где k=1 – номер бригады. Вывели размеры полученных обучающих и тестовых массивов данных." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "Ixw5Sp0_1A-w" }, "outputs": [], "source": [ "# загрузка датасета\n", "import ssl\n", "ssl._create_default_https_context = ssl._create_unverified_context\n", "\n", "from keras.datasets import imdb\n", "\n", "vocabulary_size = 5000\n", "index_from = 3\n", "\n", "(X_train, y_train), (X_test, y_test) = imdb.load_data(\n", " path=\"imdb.npz\",\n", " num_words=vocabulary_size,\n", " skip_top=0,\n", " maxlen=None,\n", " seed=3,\n", " start_char=1,\n", " oov_char=2,\n", " index_from=index_from\n", " )\n", "\n", "# вывод размерностей\n", "print('Shape of X train:', X_train.shape)\n", "print('Shape of y train:', y_train.shape)\n", "print('Shape of X test:', X_test.shape)\n", "print('Shape of y test:', y_test.shape)" ] }, { "cell_type": "markdown", "metadata": { "id": "aCo_lUXl1BPV" }, "source": [ "### 3) Вывели один отзыв из обучающего множества в виде списка индексов слов. Преобразовали список индексов в текст и вывели отзыв в виде текста. Вывели длину отзыва. Вывели метку класса данного отзыва и название класса (1 – Positive, 0 – Negative)." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "9W3RklPcZyH0" }, "outputs": [], "source": [ "# создание словаря для перевода индексов в слова\n", "# загрузка словаря \"слово:индекс\"\n", "word_to_id = imdb.get_word_index()\n", "# уточнение словаря\n", "word_to_id = {key:(value + index_from) for key,value in word_to_id.items()}\n", "word_to_id[\"\"] = 0\n", "word_to_id[\"\"] = 1\n", "word_to_id[\"\"] = 2\n", "word_to_id[\"\"] = 3\n", "# создание обратного словаря \"индекс:слово\"\n", "id_to_word = {value:key for key,value in word_to_id.items()}" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "Nu-Bs1jnaYhB" }, "outputs": [], "source": [ "print(X_train[26])\n", "print('len:',len(X_train[26]))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "JhTwTurtZ6Sp" }, "outputs": [], "source": [ "review_as_text = ' '.join(id_to_word[id] for id in X_train[26])\n", "print(review_as_text)\n", "print('len:',len(review_as_text))\n", "\n", "# вывод метки класса и названия класса\n", "print('Label:', y_train[26])\n", "print('Class:', 'Positive' if y_train[26] == 1 else 'Negative')" ] }, { "cell_type": "markdown", "metadata": { "id": "4hclnNaD1BuB" }, "source": [ "### 4) Вывели максимальную и минимальную длину отзыва в обучающем множестве." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "xJH87ISq1B9h" }, "outputs": [], "source": [ "print('MAX Len: ',len(max(X_train, key=len)))\n", "print('MIN Len: ',len(min(X_train, key=len)))" ] }, { "cell_type": "markdown", "metadata": { "id": "7x99O8ig1CLh" }, "source": [ "### 5) Провели предобработку данных. Выбрали единую длину, к которой будут приведены все отзывы. Короткие отзывы дополнили спецсимволами, а длинные обрезали до выбранной длины." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "lrF-B2aScR4t" }, "outputs": [], "source": [ "# предобработка данных\n", "from tensorflow.keras.utils import pad_sequences\n", "max_words = 500\n", "X_train = pad_sequences(X_train, maxlen=max_words, value=0, padding='pre', truncating='post')\n", "X_test = pad_sequences(X_test, maxlen=max_words, value=0, padding='pre', truncating='post')" ] }, { "cell_type": "markdown", "metadata": { "id": "HL2_LVga1C3l" }, "source": [ "### 6) Повторили пункт 4." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "81Cgq8dn9uL6" }, "outputs": [], "source": [ "print('MAX Len: ',len(max(X_train, key=len)))\n", "print('MIN Len: ',len(min(X_train, key=len)))" ] }, { "cell_type": "markdown", "metadata": { "id": "KzrVY1SR1DZh" }, "source": [ "### 7) Повторили пункт 3. Сделали вывод о том, как отзыв преобразовался после предобработки." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "vudlgqoCbjU1" }, "outputs": [], "source": [ "print(X_train[26])\n", "print('len:',len(X_train[26]))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "dbfkWjDI1Dp7" }, "outputs": [], "source": [ "review_as_text = ' '.join(id_to_word[id] for id in X_train[26])\n", "print(review_as_text)\n", "print('len:',len(review_as_text))" ] }, { "cell_type": "markdown", "metadata": { "id": "mJNRXo5TdPAE" }, "source": [ "#### В результате предобработки данных все отзывы были приведены к единой длине 500 токенов. Для отзывов, исходная длина которых была меньше 500, в начало последовательности были добавлены специальные токены заполнения (со значением 0). Это обеспечило единообразие входных данных для нейронной сети и позволило эффективно обрабатывать последовательности различной длины." ] }, { "cell_type": "markdown", "metadata": { "id": "YgiVGr5_1D3u" }, "source": [ "### 8) Вывели предобработанные массивы обучающих и тестовых данных и их размерности." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "7MqcG_wl1EHI" }, "outputs": [], "source": [ "# вывод данных\n", "print('X train: \\n',X_train)\n", "print('X test: \\n',X_test)\n", "\n", "# вывод размерностей\n", "print('Shape of X train:', X_train.shape)\n", "print('Shape of X test:', X_test.shape)" ] }, { "cell_type": "markdown", "metadata": { "id": "amaspXGW1EVy" }, "source": [ "### 9) Реализовали модель рекуррентной нейронной сети, состоящей из слоев Embedding, LSTM, Dropout, Dense, и обучили ее на обучающих данных с выделением части обучающих данных в качестве валидационных. Вывели информацию об архитектуре нейронной сети. Добились качества обучения по метрике accuracy не менее 0.8." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "ktWEeqWd1EyF" }, "outputs": [], "source": [ "embed_dim = 32\n", "lstm_units = 64\n", "\n", "model = Sequential()\n", "model.add(layers.Embedding(input_dim=vocabulary_size, output_dim=embed_dim, input_length=max_words, input_shape=(max_words,)))\n", "model.add(layers.LSTM(lstm_units))\n", "model.add(layers.Dropout(0.5))\n", "model.add(layers.Dense(1, activation='sigmoid'))\n", "\n", "model.summary()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "CuPqKpX0kQfP" }, "outputs": [], "source": [ "# компилируем и обучаем модель\n", "batch_size = 64\n", "epochs = 3\n", "model.compile(loss=\"binary_crossentropy\", optimizer=\"adam\", metrics=[\"accuracy\"])\n", "model.fit(X_train, y_train, batch_size=batch_size, epochs=epochs, validation_split=0.2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "hJIWinxymQjb" }, "outputs": [], "source": [ "test_loss, test_acc = model.evaluate(X_test, y_test)\n", "print(f\"\\nTest accuracy: {test_acc}\")" ] }, { "cell_type": "markdown", "metadata": { "id": "mgrihPd61E8w" }, "source": [ "### 10) Оценили качество обучения на тестовых данных:\n", "### - вывели значение метрики качества классификации на тестовых данных\n", "### - вывели отчет о качестве классификации тестовой выборки \n", "### - построили ROC-кривую по результату обработки тестовой выборки и вычислили площадь под ROC-кривой (AUC ROC)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "Rya5ABT8msha" }, "outputs": [], "source": [ "#значение метрики качества классификации на тестовых данных\n", "print(f\"\\nTest accuracy: {test_acc}\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "2kHjcmnCmv0Y" }, "outputs": [], "source": [ "#отчет о качестве классификации тестовой выборки\n", "y_score = model.predict(X_test)\n", "y_pred = [1 if y_score[i,0]>=0.5 else 0 for i in range(len(y_score))]\n", "\n", "from sklearn.metrics import classification_report\n", "print(classification_report(y_test, y_pred, labels = [0, 1], target_names=['Negative', 'Positive']))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "Kp4AQRbcmwAx" }, "outputs": [], "source": [ "#построение ROC-кривой и AUC ROC\n", "from sklearn.metrics import roc_curve, auc\n", "\n", "fpr, tpr, thresholds = roc_curve(y_test, y_score)\n", "plt.figure(figsize=(8, 6))\n", "plt.plot(fpr, tpr)\n", "plt.grid()\n", "plt.xlabel('False Positive Rate')\n", "plt.ylabel('True Positive Rate')\n", "plt.title('ROC')\n", "plt.savefig('roc_curve.png', dpi=150, bbox_inches='tight')\n", "plt.show()\n", "print('AUC ROC:', auc(fpr, tpr))" ] }, { "cell_type": "markdown", "metadata": { "id": "MsM3ew3d1FYq" }, "source": [ "### 11) Сделали выводы по результатам применения рекуррентной нейронной сети для решения задачи определения тональности текста. " ] }, { "cell_type": "markdown", "metadata": { "id": "xxFO4CXbIG88" }, "source": [ "Таблица1:" ] }, { "cell_type": "markdown", "metadata": { "id": "xvoivjuNFlEf" }, "source": [ "| Модель | Количество настраиваемых параметров | Количество эпох обучения | Качество классификации тестовой выборки |\n", "|----------|-------------------------------------|---------------------------|-----------------------------------------|\n", "| Рекуррентная | 184 897 | 3 | accuracy:0.8659 ; loss:0.3207 ; AUC ROC:0.9386 |\n" ] }, { "cell_type": "markdown", "metadata": { "id": "YctF8h_sIB-P" }, "source": [ "#### Анализируя полученные результаты применения рекуррентной нейронной сети для классификации тональности текстовых отзывов, можно констатировать успешное выполнение поставленной задачи. Достигнутый уровень точности accuracy = 0.8659 существенно превосходит минимально необходимый порог 0.8, что свидетельствует о надежности разработанной модели. Показатель AUC ROC = 0.9386, превышающий значение 0.9, демонстрирует отличную дискриминационную способность модели в различении позитивных и негативных отзывов. Сбалансированные метрики precision и recall (0.87 для обоих классов) указывают на отсутствие значимого смещения в сторону одного из классов, что подтверждает корректность работы алгоритма классификации." ] } ], "metadata": { "accelerator": "GPU", "colab": { "gpuType": "T4", "provenance": [] }, "kernelspec": { "display_name": "Python 3", "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.11.9" } }, "nbformat": 4, "nbformat_minor": 0 }