{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "VhB5tU1IGSIh" }, "source": [ "### ЛАБОРАТОРНАЯ РАБОТА №3\n", "## Применение многослойного персептрона. Автоассоциативная ИНС" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> Цель работы: знакомство с применением многослойного персептрона для решения задач сжатия данных, прогнозирования временных рядов и распознавания образов.\n", ">\n", "> Задание\n", "> 1. Открыть файл с данными по минеральной воде, который использовался при решении задач классификации в предыдущей лабораторной работе. Построить и обучить автоассоциативные нейронные сети с 2-мя и 3-мя нейронами в скрытом слое: \n", "> а) для исходных данных из 5-ти классов; \n", "> б) для исходных данных из 4-х классов. \n", "> Провести визуализацию данных в скрытом слое каждой сети на плоскость и в 3-х мерное пространство. Проанализировать полученные результаты. Выбрать и сохранить автоассоциативные ИНС, обеспечивающие наилучшее сжатие исходных данных. \n", "> 2. … \n", "> 3. Решить задачу распознавания 9-ти изображений самолетов. Исходные данные (файлы avia1.bmp, …, avia9.bmp) необходимо предварительно преобразовать в набор векторов со значениями признаков 0 или 1. Обученная нейронная сеть должна правильно определять модель самолета и его класс (истребитель/бомбардировщик). Принадлежность модели к определенному классу выбирается студентом самостоятельно." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Импорт библиотек:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "FwCw1KfEpbsm" }, "outputs": [], "source": [ "import numpy as np\n", "import pandas as pd\n", "import seaborn as sns\n", "import torch\n", "import matplotlib.pyplot as plt\n", "from IPython.display import clear_output\n", "from mpl_toolkits.mplot3d import Axes3D\n", "\n", "from torch import nn\n", "\n", "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Содержание: \n", "[1. Подготовка данных](#p_1) \n", "[2. Автоассоциативная нейронная сеть на полных данных](#p_2) \n", "[3. Автоассоциативная нейронная сеть на неполных данных](#p_3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1. Подготовка данных" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Загрузим в датафрейм `data` данные о сорока образцах минеральной воды, хранящиеся в файле `min_water.txt`." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 256 }, "id": "PkNWYbQCpsl_", "outputId": "ee2dd8c3-2d7d-4962-bc40-a5cc2dded5db" }, "outputs": [], "source": [ "data = pd.read_csv('min_water.csv')\n", "data.head(n=5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Вынесем в отдельные переменные:\n", " - `y_binary` — выходной признак для задачи бинарной классификации (первый столбец датафрейма);\n", " - `y_multiclass` — выходной признак для задачи многоклассовой классификации (второй столбец датафрейма);\n", " - `X_data` — входные признаки (оставшиеся столбцы)." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "D_QiYrPkpsu0" }, "outputs": [], "source": [ "y_binary = data.iloc[:, 0]\n", "y_multiclass = data.iloc[:, 1]\n", "\n", "X_data = data.iloc[:, 2:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Выпишите в список `features` отобранные в прошлой лабораторной работе признаки (формат: `features = ['VAR1', 'VAR2']`):" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "features = # Ваш код здесь" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Датафрейм с отобранными входными признаками `X_data_filtered`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 206 }, "id": "d6eTUCk2Cjdc", "outputId": "d89643dd-a410-42b2-9b91-c4534966fd1d" }, "outputs": [], "source": [ "X_data_filtered = X_data.loc[:, features]\n", "X_data_filtered.head(n=5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Произведите нормализацию или стандартизацию (на выбор) отобранных входных данных `X_data_filtered`. Результат сохраните в переменную `X_data_preprocessed`, которую затем представьте в виде тензора `X_data_tensor`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "HclxngwAGue-" }, "outputs": [], "source": [ "# Ваш код здесь\n", "\n", "X_data_preprocessed = # Ваш код здесь\n", "\n", "X_data_tensor = # Ваш код здесь" ] }, { "cell_type": "markdown", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "AtGktiZmJiUV", "outputId": "f9edb4f0-c5ab-4a62-af28-6552c981512f" }, "source": [ "## 2. Автоассоциативная нейронная сеть на полных данных" ] }, { "cell_type": "markdown", "metadata": { "id": "jsWiE7Ke1p9S" }, "source": [ "Автоассоциативная сеть (или автоассоциативная память) — тип нейронной сети, способный восстанавливать полный шаблон данных по его частичному или зашумлённому представлению.\n", "\n", "Типичная автоассоциативная сеть содержит как минимум три скрытых слоя:\n", " - первый скрытый слой выполняет нелинейное кодирование входных данных (энкодер);\n", " - средний слой («узкое горло» или «бутылочное горло») формирует сжатое представление данных — в результате обучения выдаёт компактное кодирование;\n", " - последний скрытый слой служит декодером: восстанавливает исходные данные из сжатого представления.\n", "\n", "Цель обучения: в процессе минимизации ошибки воспроизведения сеть стремится сделать выходной сигнал максимально близким к входному. Это эквивалентно оптимальному кодированию в «узком горле» сети." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Допишите класс `Autoencoder` структурами энкодера и декодера на основе полносвязных слоёв `nn.Linear`. В качестве функций активации используйте `nn.ReLU()`. При этом на выходе энкодера функцию активации можно не применять — это позволит сохранить отрицательные значения в кодированном представлении." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "class Autoencoder(nn.Module):\n", " def __init__(self, n_inputs, n_hiddens, bottleneck_size):\n", " super().__init__()\n", " self.encoder = nn.Sequential(\n", " # Ваш код здесь\n", " )\n", " self.decoder = nn.Sequential(\n", " # Ваш код здесь\n", " )\n", "\n", " def forward(self, x):\n", " encoded = self.encoder(x)\n", " decoded = self.decoder(encoded)\n", " return decoded" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Создайте экземпляр модели с двумя нейронами в «узком горле»:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "model_2 = Autoencoder(# Ващ код здесь\n", "print(model_2)" ] }, { "cell_type": "markdown", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "tGS2_TqjK_SI", "outputId": "a1a63c33-5dd5-461e-8d20-97fc34455f21" }, "source": [ "Пропустим данные через эту модель для её проверки:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "Y3GS-3AaKYt7", "outputId": "981a4cd8-3b19-4bf6-ac07-ddd13e3df131" }, "outputs": [], "source": [ "model_2(X_data_tensor[:3])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Удостоверимся, что размерность её выхода совпадает с размерностью её входа:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "assert X_data_tensor[:3].shape == model_2(X_data_tensor[:3]).shape" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Проверим, как модель обучается. Зададим оптимизатор и среднеквадратическую функцию потерь:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "VGWgT-_UKY5S" }, "outputs": [], "source": [ "optimizer = torch.optim.SGD(model_2.parameters(), lr=1.5)\n", "criterion = nn.MSELoss()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Рассчитаем значение функции потерь:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "5kKYW89_KY8j", "outputId": "94e90485-ca86-4204-e61d-75d247a87fc4" }, "outputs": [], "source": [ "decoded = model_2(X_data_tensor)\n", "\n", "loss = criterion(decoded, X_data_tensor)\n", "loss" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Выполните несколько раз эту и предыдущую ячейку, чтобы убедиться в уменьшении ошибки:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "G_JCVLCkKZCa" }, "outputs": [], "source": [ "loss.backward()\n", "optimizer.step()\n", "optimizer.zero_grad()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Задайте параметры для обучения автоассоциативной сети с двумя нейронами в «узком горле»:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "torch.manual_seed(seed=42)\n", "\n", "model_2 = # Ваш код здесь\n", "\n", "epochs = # Ваш код здесь\n", "\n", "learning_rate = # Ваш код здесь\n", "momentum = # Ваш код здесь\n", "\n", "optimizer = # Ваш код здесь\n", "criterion = # Ваш код здесь" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Обучение нейронной сети:**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "loss_history = []\n", "\n", "for epoch in range(epochs):\n", " # Ваш код здесь\n", "\n", " if (epoch + 1) % 5 == 0:\n", "\n", " clear_output(True)\n", " plt.plot(range(1, epoch+2), loss_history, label='Loss')\n", " plt.title(f'Epoch: {epoch + 1}, Loss: {loss_history[-1]:.6f}')\n", " plt.grid(True, alpha=0.3)\n", " plt.legend(loc='best')\n", " plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "После обучения сети получим двумерные данные с выхода энкодера:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "HFcSAdGoOaog", "outputId": "36330737-7606-4a6a-e532-6bf372deb34d" }, "outputs": [], "source": [ "encoded_2d = model_2.encoder(X_data_tensor).detach().numpy()\n", "print(encoded_2d[:3])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Построим двумерную диаграмму рассеяния и отметим классы с помощью `y_multiclass`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 430 }, "id": "KkToPCInQQ1J", "outputId": "244bae8a-94a9-4817-a564-69c630efea98" }, "outputs": [], "source": [ "scatter = plt.scatter(x=encoded_2d[:, 0], y=encoded_2d[:, 1], c=y_multiclass, cmap='viridis')\n", "plt.grid(True, alpha=0.3)\n", "\n", "# Код для легенды\n", "handles, labels = scatter.legend_elements(prop='colors')\n", "plt.legend(handles, labels, loc='best', title='Classes')\n", "\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "По аналогии обучите автоассоциативную сеть с тремя нейронами в «узком горле»:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "torch.manual_seed(seed=42)\n", "\n", "model_3 = # Ваш код здесь\n", "\n", "# Ваш код здесь" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Ваш код здесь" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "После обучения сети получите трёхмерные данные с выхода энкодера:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "encoded_3d = # Ваш код здесь" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Построим трёхмерную диаграмму рассеяния:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 653 }, "id": "RpqVg5EeT72I", "outputId": "2f5e070d-aa49-4eab-cd8e-277bd3a2c4b5" }, "outputs": [], "source": [ "fig = plt.figure(figsize=(10, 8))\n", "ax = fig.add_subplot(111, projection='3d')\n", "\n", "scatter = ax.scatter(\n", " xs=encoded_3d[:, 0],\n", " ys=encoded_3d[:, 1],\n", " zs=encoded_3d[:, 2],\n", " c=y_multiclass,\n", " cmap='viridis',\n", " s=50\n", ")\n", "\n", "ax.grid(True, alpha=0.3)\n", "\n", "handles, labels = scatter.legend_elements(prop='colors', alpha=0.8)\n", "ax.legend(handles, labels, loc='best', title='Classes')\n", "\n", "# Настраиваем угол обзора:\n", "# elev — высота, azim — азимут\n", "ax.view_init(elev=20, azim=45)\n", "\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Сохраним в бинарные файлы `.npy` выходы энкодеров обеих моделей — для следующей лабораторной работы:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "np.save('encoded_2d.npy', encoded_2d)\n", "np.save('encoded_3d.npy', encoded_3d)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3. Автоассоциативная нейронная сеть на неполных данных" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Выберите класс, который нужно исключить:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "label_to_exclude = # Ваш код здесь" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Создадим маску для исключения данных этого класса:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "WwlU6wRqXy3H" }, "outputs": [], "source": [ "mask_to_exclude = y_multiclass != label_to_exclude" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Данные исключены:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "I7sTKdWgQRWQ", "outputId": "95d2a292-7e2f-401e-e473-7d5f09b0d7fb" }, "outputs": [], "source": [ "X_data_tensor[mask_to_exclude].shape" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "По аналогии с предыдущим пунктом реализуйте обучение автоассоциативных сетей с двумя и тремя нейронами в «узком горле» на неполных данных (т.е. на каждой эпохе вместо полных данных `X_data_tensor` на модель нужно подавать неполные данные `X_data_tensor[mask_to_exclude]`).\n", "\n", "Результаты выходов энкодеров в обоих случаях также сохраните в отдельные бинарные файлы." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Ваш код здесь" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Ваш код здесь" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "w3kJHSW3azk0" }, "outputs": [], "source": [ "# Ваш код здесь" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Литература:\n", "1. Бородкин А.А., Елисеев В.Л. Основы и применение искусственных нейронных сетей. Сборник лабораторных работ: методическое пособие. – М.: Издательский дом МЭИ, 2017.\n", "2. MachineLearning.ru — профессиональный информационно-аналитический ресурс, посвященный машинному обучению, распознаванию образов и интеллектуальному анализу данных: http://www.machinelearning.ru\n", "3. Modern State of Artificial Intelligence — Online Masters program at MIPT: https://girafe.ai/" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " " ] } ], "metadata": { "colab": { "provenance": [] }, "kernelspec": { "display_name": "Python 3", "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.7.3" } }, "nbformat": 4, "nbformat_minor": 1 }