1
0
ответвлено от main/neurocomputers-python

Сравнить коммиты

...

3 Коммитов
main ... main

Автор SHA1 Сообщение Дата
603ec44720 Загрузить файлы в «lab4» 2026-03-03 18:59:41 +00:00
6c5da44cc3 Загрузить файлы в «lab3» 2026-02-28 14:09:46 +00:00
fe6b803876 Загрузить файлы в «lab3» 2026-02-28 14:06:48 +00:00
4 изменённых файлов: 1692 добавлений и 315 удалений

Просмотреть файл

@@ -12,9 +12,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"id": "15BpjnZQzAUG"
},
"source": [ "source": [
"> Цель работы: знакомство с применением многослойного персептрона для решения задач сжатия данных, прогнозирования временных рядов и распознавания образов.\n", "> Цель работы: знакомство с применением многослойного персептрона для решения задач сжатия данных, прогнозирования временных рядов и распознавания образов.\n",
">\n", ">\n",
@@ -23,15 +21,15 @@
"> а) для исходных данных из 5-ти классов; \n", "> а) для исходных данных из 5-ти классов; \n",
"> б) для исходных данных из 4-х классов. \n", "> б) для исходных данных из 4-х классов. \n",
"> Провести визуализацию данных в скрытом слое каждой сети на плоскость и в 3-х мерное пространство. Проанализировать полученные результаты. Выбрать и сохранить автоассоциативные ИНС, обеспечивающие наилучшее сжатие исходных данных. \n", "> Провести визуализацию данных в скрытом слое каждой сети на плоскость и в 3-х мерное пространство. Проанализировать полученные результаты. Выбрать и сохранить автоассоциативные ИНС, обеспечивающие наилучшее сжатие исходных данных. \n",
"> 2. \n", "> 2. Исследовать возможности ИНС по прогнозированию поведения нелинейных динамических систем (построение странного аттрактора) на примере отображения Хенона. Аттрактор Хенона может быть получен из уравнений $x_{n+1} = 1 - \\alpha x_{n}^2 + y_{n}$ и $y_{n+1} = \\beta x_{n}$, где $α = 1.4$, $β = 0.3$.\n",
"> Для прогнозирования предлагается использовать многослойный персептрон и сеть с радиально-базисными функциями.\n",
"> Постройте также прогноз курса доллара на один день вперед. В качестве исходных данных загрузить актуальные данные с сайта центрального банка России (http://www.cbr.ru).\n",
"> 3. Решить задачу распознавания 9-ти изображений самолетов. Исходные данные (файлы avia1.bmp, …, avia9.bmp) необходимо предварительно преобразовать в набор векторов со значениями признаков 0 или 1. Обученная нейронная сеть должна правильно определять модель самолета и его класс (истребитель/бомбардировщик). Принадлежность модели к определенному классу выбирается студентом самостоятельно." "> 3. Решить задачу распознавания 9-ти изображений самолетов. Исходные данные (файлы avia1.bmp, …, avia9.bmp) необходимо предварительно преобразовать в набор векторов со значениями признаков 0 или 1. Обученная нейронная сеть должна правильно определять модель самолета и его класс (истребитель/бомбардировщик). Принадлежность модели к определенному классу выбирается студентом самостоятельно."
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"id": "F1-sSuk2zAUI"
},
"source": [ "source": [
"Импорт библиотек:" "Импорт библиотек:"
] ]
@@ -46,11 +44,11 @@
"source": [ "source": [
"import numpy as np\n", "import numpy as np\n",
"import pandas as pd\n", "import pandas as pd\n",
"import seaborn as sns\n",
"import torch\n", "import torch\n",
"import matplotlib.pyplot as plt\n", "import matplotlib.pyplot as plt\n",
"from IPython.display import clear_output\n", "from IPython.display import clear_output\n",
"from mpl_toolkits.mplot3d import Axes3D\n", "from mpl_toolkits.mplot3d import Axes3D\n",
"from sklearn.model_selection import train_test_split\n",
"\n", "\n",
"from torch import nn\n", "from torch import nn\n",
"\n", "\n",
@@ -59,9 +57,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"id": "GtZJ1mGmzAUL"
},
"source": [ "source": [
"### Содержание: \n", "### Содержание: \n",
"[1. Подготовка данных](#p_1) \n", "[1. Подготовка данных](#p_1) \n",
@@ -71,18 +67,14 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"id": "HZNHPPKUzAUM"
},
"source": [ "source": [
"## 1. Подготовка данных<a id=\"p_1\"></a>" "## 1. Подготовка данных<a id=\"p_1\"></a>"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"id": "h2JqhwwrzAUN"
},
"source": [ "source": [
"Загрузим в датафрейм `data` данные о сорока образцах минеральной воды, хранящиеся в файле `min_water.txt`." "Загрузим в датафрейм `data` данные о сорока образцах минеральной воды, хранящиеся в файле `min_water.txt`."
] ]
@@ -96,7 +88,7 @@
"height": 256 "height": 256
}, },
"id": "PkNWYbQCpsl_", "id": "PkNWYbQCpsl_",
"outputId": "1de6457f-9cc1-42a1-b4f1-2c13c5b66100" "outputId": "ee2dd8c3-2d7d-4962-bc40-a5cc2dded5db"
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
@@ -106,9 +98,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"id": "YjqpAWl9zAUR"
},
"source": [ "source": [
"Вынесем в отдельные переменные:\n", "Вынесем в отдельные переменные:\n",
" - `y_binary` — выходной признак для задачи бинарной классификации (первый столбец датафрейма);\n", " - `y_binary` — выходной признак для задачи бинарной классификации (первый столбец датафрейма);\n",
@@ -132,9 +122,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"id": "rpgOkJkPzAUT"
},
"source": [ "source": [
"Выпишите в список `features` отобранные в прошлой лабораторной работе признаки (формат: `features = ['VAR1', 'VAR2']`):" "Выпишите в список `features` отобранные в прошлой лабораторной работе признаки (формат: `features = ['VAR1', 'VAR2']`):"
] ]
@@ -142,9 +130,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"metadata": { "metadata": {},
"id": "R0bIf4PUzAUT"
},
"outputs": [], "outputs": [],
"source": [ "source": [
"features = # Ваш код здесь" "features = # Ваш код здесь"
@@ -152,9 +138,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"id": "ddwgNPoyzAUV"
},
"source": [ "source": [
"Датафрейм с отобранными входными признаками `X_data_filtered`:" "Датафрейм с отобранными входными признаками `X_data_filtered`:"
] ]
@@ -168,7 +152,7 @@
"height": 206 "height": 206
}, },
"id": "d6eTUCk2Cjdc", "id": "d6eTUCk2Cjdc",
"outputId": "656c9a35-26f6-4425-b35e-ca06930abc82" "outputId": "d89643dd-a410-42b2-9b91-c4534966fd1d"
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
@@ -180,7 +164,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"C помощью функции `train_test_split` разбейте данные (`X_data_filtered`, `y_multiclass`) на обучающую (`X_multiclass_train`, `y_multiclass_train`), валидационную (`X_multiclass_valid`, `y_multiclass_valid`) и тестовую выборки (`X_multiclass_test`, `y_multiclass_test`) с сохранением соотншений классов (сортов минеральной воды):" "Произведите нормализацию или стандартизацию (на выбор) отобранных входных данных `X_data_filtered`. Результат сохраните в переменную `X_data_preprocessed`, которую затем представьте в виде тензора `X_data_tensor`:"
] ]
}, },
{ {
@@ -191,37 +175,19 @@
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"X_multiclass_train, X_multiclass_test, y_multiclass_train, y_multiclass_test = # Ваш код здесь\n", "# Ваш код здесь\n",
"\n", "\n",
"X_multiclass_train, X_multiclass_valid, y_multiclass_train, y_multiclass_valid = # Ваш код здесь" "X_data_preprocessed = # Ваш код здесь\n",
] "\n",
}, "X_data_tensor = # Ваш код здесь"
{
"cell_type": "markdown",
"metadata": {
"id": "LAOh4V56zAUV"
},
"source": [
"Произведите нормализацию или стандартизацию (на выбор) входных данных. Результат сохраните в переменные (`X_multiclass_train`, `X_multiclass_valid`, `X_multiclass_test`), которую затем представьте в виде тензоров:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"X_means = # Ваш код здесь\n",
"X_stds = # Ваш код здесь\n",
"\n",
"X_multiclass_train = # Ваш код здесь\n",
"X_multiclass_valid = # Ваш код здесь\n",
"X_multiclass_test = # Ваш код здесь"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "AtGktiZmJiUV", "id": "AtGktiZmJiUV",
"outputId": "f9edb4f0-c5ab-4a62-af28-6552c981512f" "outputId": "f9edb4f0-c5ab-4a62-af28-6552c981512f"
}, },
@@ -247,9 +213,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"id": "asRgUuyNzAUY"
},
"source": [ "source": [
"Допишите класс `Autoencoder` структурами энкодера и декодера на основе полносвязных слоёв `nn.Linear`. В качестве функций активации используйте `nn.ReLU()`. При этом на выходе энкодера функцию активации можно не применять — это позволит сохранить отрицательные значения в кодированном представлении." "Допишите класс `Autoencoder` структурами энкодера и декодера на основе полносвязных слоёв `nn.Linear`. В качестве функций активации используйте `nn.ReLU()`. При этом на выходе энкодера функцию активации можно не применять — это позволит сохранить отрицательные значения в кодированном представлении."
] ]
@@ -257,9 +221,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"metadata": { "metadata": {},
"id": "F297Z81wzAUY"
},
"outputs": [], "outputs": [],
"source": [ "source": [
"class Autoencoder(nn.Module):\n", "class Autoencoder(nn.Module):\n",
@@ -280,9 +242,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"id": "R5sVUOy7zAUZ"
},
"source": [ "source": [
"Создайте экземпляр модели с двумя нейронами в «узком горле»:" "Создайте экземпляр модели с двумя нейронами в «узком горле»:"
] ]
@@ -290,9 +250,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"metadata": { "metadata": {},
"id": "MlSSzk2yzAUa"
},
"outputs": [], "outputs": [],
"source": [ "source": [
"model_2 = Autoencoder(# Ващ код здесь\n", "model_2 = Autoencoder(# Ващ код здесь\n",
@@ -302,6 +260,9 @@
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "tGS2_TqjK_SI", "id": "tGS2_TqjK_SI",
"outputId": "a1a63c33-5dd5-461e-8d20-97fc34455f21" "outputId": "a1a63c33-5dd5-461e-8d20-97fc34455f21"
}, },
@@ -317,18 +278,16 @@
"base_uri": "https://localhost:8080/" "base_uri": "https://localhost:8080/"
}, },
"id": "Y3GS-3AaKYt7", "id": "Y3GS-3AaKYt7",
"outputId": "81ecb257-7d72-443e-aa9e-256271a17a6e" "outputId": "981a4cd8-3b19-4bf6-ac07-ddd13e3df131"
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"model_2(X_multiclass_train[:3])" "model_2(X_data_tensor[:3])"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"id": "8hJk8GWIzAUb"
},
"source": [ "source": [
"Удостоверимся, что размерность её выхода совпадает с размерностью её входа:" "Удостоверимся, что размерность её выхода совпадает с размерностью её входа:"
] ]
@@ -336,19 +295,15 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"metadata": { "metadata": {},
"id": "pDmdGMRZzAUc"
},
"outputs": [], "outputs": [],
"source": [ "source": [
"assert X_multiclass_train[:3].shape == model_2(X_multiclass_train[:3]).shape" "assert X_data_tensor[:3].shape == model_2(X_data_tensor[:3]).shape"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"id": "IjoYYn-ozAUc"
},
"source": [ "source": [
"Проверим, как модель обучается. Зададим оптимизатор и среднеквадратическую функцию потерь:" "Проверим, как модель обучается. Зададим оптимизатор и среднеквадратическую функцию потерь:"
] ]
@@ -367,9 +322,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"id": "HqcQqxN7zAUd"
},
"source": [ "source": [
"Рассчитаем значение функции потерь:" "Рассчитаем значение функции потерь:"
] ]
@@ -382,21 +335,19 @@
"base_uri": "https://localhost:8080/" "base_uri": "https://localhost:8080/"
}, },
"id": "5kKYW89_KY8j", "id": "5kKYW89_KY8j",
"outputId": "a5ece716-5c89-4553-c78c-1e5c7e20eedf" "outputId": "94e90485-ca86-4204-e61d-75d247a87fc4"
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"decoded = model_2(X_multiclass_train)\n", "decoded = model_2(X_data_tensor)\n",
"\n", "\n",
"loss = criterion(decoded, X_multiclass_train)\n", "loss = criterion(decoded, X_data_tensor)\n",
"loss" "loss"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"id": "JVplv7O8zAUd"
},
"source": [ "source": [
"Выполните несколько раз эту и предыдущую ячейку, чтобы убедиться в уменьшении ошибки:" "Выполните несколько раз эту и предыдущую ячейку, чтобы убедиться в уменьшении ошибки:"
] ]
@@ -416,9 +367,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"id": "iXqI-DurzAUe"
},
"source": [ "source": [
"Задайте параметры для обучения автоассоциативной сети с двумя нейронами в «узком горле»:" "Задайте параметры для обучения автоассоциативной сети с двумя нейронами в «узком горле»:"
] ]
@@ -426,9 +375,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"metadata": { "metadata": {},
"id": "5s4GjW_PzAUe"
},
"outputs": [], "outputs": [],
"source": [ "source": [
"torch.manual_seed(seed=42)\n", "torch.manual_seed(seed=42)\n",
@@ -446,9 +393,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"id": "SN8PZ41vzAUp"
},
"source": [ "source": [
"**Обучение нейронной сети:**" "**Обучение нейронной сети:**"
] ]
@@ -459,21 +404,16 @@
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"loss_train_history, loss_valid_history = [], []\n", "loss_history = []\n",
"\n", "\n",
"for epoch in range(epochs):\n", "for epoch in range(epochs):\n",
" # Ваш код здесь\n", " # Ваш код здесь\n",
"\n", "\n",
" # Отключаем градиенты для этапа валидации\n",
" with torch.no_grad():\n",
" # Ваш код здесь\n",
"\n",
" if (epoch + 1) % 5 == 0:\n", " if (epoch + 1) % 5 == 0:\n",
"\n", "\n",
" clear_output(True)\n", " clear_output(True)\n",
" plt.plot(range(1, epoch+2), loss_train_history, label='Train', color='green')\n", " plt.plot(range(1, epoch+2), loss_history, label='Loss')\n",
" plt.plot(range(1, epoch+2), loss_valid_history, label='Valid', color='red')\n", " plt.title(f'Epoch: {epoch + 1}, Loss: {loss_history[-1]:.6f}')\n",
" plt.title(f'Epoch: {epoch + 1}, Loss Train: {loss_train_history[-1]:.6f}, Loss Valid: {loss_valid_history[-1]:.6f}')\n",
" plt.grid(True, alpha=0.3)\n", " plt.grid(True, alpha=0.3)\n",
" plt.legend(loc='best')\n", " plt.legend(loc='best')\n",
" plt.show()" " plt.show()"
@@ -482,54 +422,6 @@
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [
"Проверим качество обученной сети на тестовой выборке:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "t-Xkwg4h3gyS",
"outputId": "ddfc13ae-f942-4328-9036-92b318c726bc"
},
"outputs": [],
"source": [
"with torch.no_grad():\n",
" decoded_test = model_2(X_multiclass_test)\n",
" loss_test = criterion(decoded_test, X_multiclass_test)\n",
"\n",
"print(f'Loss Test: {loss_test.item():.6f}')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Далее необходимо через обученную сети пропустить все имеющиеся входные данные. Здесь можно сконкатенировать обучающую, валидационную и тестовую выборки, но можно и заново стандартизировать исходные данные `X_data_filtered` с помощью переменных `X_means` и `X_stds`, которые обязательно должны быть ранее рассчитаны на обучающей выборке `X_multiclass_train` (аналогично будет и для нормировки данных). Результат будет прелставлен в виде тензора.\n",
"\n",
"Такой вариант сохранит исходный порядок записей в данных и позволит нам использовать исходный вектор `y_multiclass` для разметки классов ниже."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "0RbKOwMeZUcn"
},
"outputs": [],
"source": [
"X_data_tensor = torch.tensor(((X_data_filtered - X_means) / X_stds).values).float()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "TrWOUf0vzAUq"
},
"source": [ "source": [
"После обучения сети получим двумерные данные с выхода энкодера:" "После обучения сети получим двумерные данные с выхода энкодера:"
] ]
@@ -542,7 +434,7 @@
"base_uri": "https://localhost:8080/" "base_uri": "https://localhost:8080/"
}, },
"id": "HFcSAdGoOaog", "id": "HFcSAdGoOaog",
"outputId": "1233f17c-2188-402e-d1dc-697dc6c0bfb4" "outputId": "36330737-7606-4a6a-e532-6bf372deb34d"
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
@@ -552,9 +444,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"id": "GjtM4NXLzAUr"
},
"source": [ "source": [
"Построим двумерную диаграмму рассеяния и отметим классы с помощью `y_multiclass`:" "Построим двумерную диаграмму рассеяния и отметим классы с помощью `y_multiclass`:"
] ]
@@ -568,7 +458,7 @@
"height": 430 "height": 430
}, },
"id": "KkToPCInQQ1J", "id": "KkToPCInQQ1J",
"outputId": "8469b911-292a-4016-fbd3-38f92997adad" "outputId": "244bae8a-94a9-4817-a564-69c630efea98"
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
@@ -584,9 +474,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"id": "t0EmzLHXzAUs"
},
"source": [ "source": [
"По аналогии обучите автоассоциативную сеть с тремя нейронами в «узком горле»:" "По аналогии обучите автоассоциативную сеть с тремя нейронами в «узком горле»:"
] ]
@@ -594,9 +482,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"metadata": { "metadata": {},
"id": "WasLielLzAUt"
},
"outputs": [], "outputs": [],
"source": [ "source": [
"torch.manual_seed(seed=42)\n", "torch.manual_seed(seed=42)\n",
@@ -609,9 +495,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"metadata": { "metadata": {},
"id": "cFxc9xD-zAUt"
},
"outputs": [], "outputs": [],
"source": [ "source": [
"# Ваш код здесь" "# Ваш код здесь"
@@ -619,19 +503,15 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"id": "18f786y5zAUv"
},
"source": [ "source": [
"После обучения сети получите трёхмерные данные с выхода энкодера (снова по всем данным `X_data_tensor`, которые уже были подготовлены выше):" "После обучения сети получите трёхмерные данные с выхода энкодера:"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"metadata": { "metadata": {},
"id": "PLjKuu-szAUw"
},
"outputs": [], "outputs": [],
"source": [ "source": [
"encoded_3d = # Ваш код здесь" "encoded_3d = # Ваш код здесь"
@@ -639,9 +519,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"id": "BYn45sTnzAUx"
},
"source": [ "source": [
"Построим трёхмерную диаграмму рассеяния:" "Построим трёхмерную диаграмму рассеяния:"
] ]
@@ -655,7 +533,7 @@
"height": 653 "height": 653
}, },
"id": "RpqVg5EeT72I", "id": "RpqVg5EeT72I",
"outputId": "7b9aac3c-68d5-44d7-db56-8f7a53e3aa37" "outputId": "2f5e070d-aa49-4eab-cd8e-277bd3a2c4b5"
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
@@ -685,9 +563,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"id": "NNWL9ZakzAUy"
},
"source": [ "source": [
"Сохраним в бинарные файлы `.npy` выходы энкодеров обеих моделей — для следующей лабораторной работы:" "Сохраним в бинарные файлы `.npy` выходы энкодеров обеих моделей — для следующей лабораторной работы:"
] ]
@@ -695,9 +571,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"metadata": { "metadata": {},
"id": "p2Zx-Jz4zAUz"
},
"outputs": [], "outputs": [],
"source": [ "source": [
"np.save('encoded_2d.npy', encoded_2d)\n", "np.save('encoded_2d.npy', encoded_2d)\n",
@@ -706,18 +580,14 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"id": "K-pYtaxBzAUz"
},
"source": [ "source": [
"## 3. Автоассоциативная нейронная сеть на неполных данных<a id=\"p_3\"></a>" "## 3. Автоассоциативная нейронная сеть на неполных данных<a id=\"p_3\"></a>"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"id": "J3RSV5WDzAU0"
},
"source": [ "source": [
"Выберите класс, который нужно исключить:" "Выберите класс, который нужно исключить:"
] ]
@@ -725,9 +595,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"metadata": { "metadata": {},
"id": "_UuEf5TRzAU0"
},
"outputs": [], "outputs": [],
"source": [ "source": [
"label_to_exclude = # Ваш код здесь" "label_to_exclude = # Ваш код здесь"
@@ -735,9 +603,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"id": "MmlBKShgzAU1"
},
"source": [ "source": [
"Создадим маску для исключения данных этого класса:" "Создадим маску для исключения данных этого класса:"
] ]
@@ -755,9 +621,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"id": "SA3A39ARzAU1"
},
"source": [ "source": [
"Данные исключены:" "Данные исключены:"
] ]
@@ -766,60 +630,22 @@
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"metadata": { "metadata": {
"id": "I7sTKdWgQRWQ" "colab": {
"base_uri": "https://localhost:8080/"
},
"id": "I7sTKdWgQRWQ",
"outputId": "95d2a292-7e2f-401e-e473-7d5f09b0d7fb"
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"X_data_include = X_data_filtered.loc[mask_to_exclude, :]\n", "X_data_tensor[mask_to_exclude].shape"
"y_include = y_multiclass[mask_to_exclude]"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"По аналогии с помощью функции `train_test_split` разбейте данные (`X_data_include`, `y_include`) на обучающую (`X_include_train`, `y_include_train`), валидационную (`X_include_valid`, `y_include_valid`) и тестовую выборки (`X_include_test`, `y_include_test`) с сохранением соотншений классов:" "По аналогии с предыдущим пунктом реализуйте обучение автоассоциативных сетей с двумя и тремя нейронами в «узком горле» на неполных данных (т.е. на каждой эпохе вместо полных данных `X_data_tensor` на модель нужно подавать неполные данные `X_data_tensor[mask_to_exclude]`).\n",
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"X_include_train, X_include_test, y_include_train, y_include_test = # Ваш код здесь\n",
"\n",
"X_include_train, X_include_valid, y_include_train, y_include_valid = # Ваш код здесь"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Обратите внимание, что `X_means` и `X_stds` перерасчитываются уже на другой по составу обучающей выборке."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"X_means = # Ваш код здесь\n",
"X_stds = # Ваш код здесь\n",
"\n",
"X_include_train = # Ваш код здесь\n",
"X_include_valid = # Ваш код здесь\n",
"X_include_test = # Ваш код здесь"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "V2MUFTkczAU2"
},
"source": [
"По аналогии с предыдущим пунктом реализуйте обучение автоассоциативных сетей с двумя и тремя нейронами в «узком горле».\n",
"\n", "\n",
"Результаты выходов энкодеров в обоих случаях также сохраните в отдельные бинарные файлы." "Результаты выходов энкодеров в обоих случаях также сохраните в отдельные бинарные файлы."
] ]
@@ -827,9 +653,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"metadata": { "metadata": {},
"id": "qnSnyqNGzAU2"
},
"outputs": [], "outputs": [],
"source": [ "source": [
"# Ваш код здесь" "# Ваш код здесь"
@@ -838,41 +662,12 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"metadata": { "metadata": {},
"id": "MMW6h5P1zAU3"
},
"outputs": [], "outputs": [],
"source": [ "source": [
"# Ваш код здесь" "# Ваш код здесь"
] ]
}, },
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Обратите внимание, что тензор `X_data_tensor` снова получен из исходных данных `X_data_filtered`, но уже с пересчитанными `X_means` и `X_stds` (без одного класса):"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "1FjpRmrCaOp4"
},
"outputs": [],
"source": [
"X_data_tensor = torch.tensor(((X_data_filtered - X_means) / X_stds).values).float()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"encoded_2d_include = # Ваш код здесь"
]
},
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
@@ -884,39 +679,9 @@
"# Ваш код здесь" "# Ваш код здесь"
] ]
}, },
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Ваш код здесь"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"encoded_3d_include = # Ваш код здесь"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"np.save('encoded_2d_include.npy', encoded_2d_include)\n",
"np.save('encoded_3d_include.npy', encoded_3d_include)"
]
},
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"id": "-BXig37czAU6"
},
"source": [ "source": [
"### Литература:\n", "### Литература:\n",
"1. Бородкин А.А., Елисеев В.Л. Основы и применение искусственных нейронных сетей. Сборник лабораторных работ: методическое пособие. – М.: Издательский дом МЭИ, 2017.\n", "1. Бородкин А.А., Елисеев В.Л. Основы и применение искусственных нейронных сетей. Сборник лабораторных работ: методическое пособие. – М.: Издательский дом МЭИ, 2017.\n",
@@ -926,10 +691,10 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {},
"id": "-KIqZEHczAU6" "source": [
}, " "
"source": [] ]
} }
], ],
"metadata": { "metadata": {

989
lab3/3.2_rbf.ipynb Обычный файл
Просмотреть файл

@@ -0,0 +1,989 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "AoAuVqmYggH6"
},
"source": [
"### ЛАБОРАТОРНАЯ РАБОТА №3\n",
"## Применение многослойного персептрона. Автоассоциативная ИНС"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "32GlCnm4ggH9"
},
"source": [
"> Цель работы: знакомство с применением многослойного персептрона для решения задач сжатия данных, прогнозирования временных рядов и распознавания образов.\n",
">\n",
"> Задание\n",
"> 1. Открыть файл с данными по минеральной воде, который использовался при решении задач классификации в предыдущей лабораторной работе. Построить и обучить автоассоциативные нейронные сети с 2-мя и 3-мя нейронами в скрытом слое: \n",
"> а) для исходных данных из 5-ти классов; \n",
"> б) для исходных данных из 4-х классов. \n",
"> Провести визуализацию данных в скрытом слое каждой сети на плоскость и в 3-х мерное пространство. Проанализировать полученные результаты. Выбрать и сохранить автоассоциативные ИНС, обеспечивающие наилучшее сжатие исходных данных. \n",
"> 2. Исследовать возможности ИНС по прогнозированию поведения нелинейных динамических систем (построение странного аттрактора) на примере отображения Хенона. Аттрактор Хенона может быть получен из уравнений $x_{n+1} = 1 - \\alpha x_{n}^2 + y_{n}$ и $y_{n+1} = \\beta x_{n}$, где $α = 1.4$, $β = 0.3$.\n",
"> Для прогнозирования предлагается использовать многослойный персептрон и сеть с радиально-базисными функциями.\n",
"> Постройте также прогноз курса доллара на один день вперед. В качестве исходных данных загрузить актуальные данные с сайта центрального банка России (http://www.cbr.ru).\n",
"> 3. Решить задачу распознавания 9-ти изображений самолетов. Исходные данные (файлы avia1.bmp, …, avia9.bmp) необходимо предварительно преобразовать в набор векторов со значениями признаков 0 или 1. Обученная нейронная сеть должна правильно определять модель самолета и его класс (истребитель/бомбардировщик). Принадлежность модели к определенному классу выбирается студентом самостоятельно."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "k_B6wp5VggH_"
},
"source": [
"Импорт библиотек:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "tHv-NgtJ30SO"
},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"import torch\n",
"from IPython.display import clear_output\n",
"from torch import nn\n",
"from sklearn.cluster import KMeans\n",
"from sklearn.linear_model import LinearRegression\n",
"\n",
"%matplotlib inline"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "4vwZ6H2DggIB"
},
"source": [
"Среднеквадратическая ошибка:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "OGGq8mjQggIC"
},
"outputs": [],
"source": [
"def mse(y_pred, y_true):\n",
" return np.mean((y_pred - y_true) ** 2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Содержание: \n",
"[1. Подготовка данных](#p_1) \n",
"[2. Сеть с радиально-базисными функциями](#p_2) \n",
"[3. Многослойный персептрон](#p_3) \n",
"[4. Сравнение моделей](#p_4) \n",
"[5. Прогнозирование курса доллара](#p_5)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "iaKX-JW9ggIC"
},
"source": [
"## 1. Подготовка данных<a id=\"p_1\"></a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "C4MQNIvaggIC"
},
"source": [
"Функция с реализацией отображения Хенона — уравнения $x_{n+1} = 1 - \\alpha x_{n}^2 + y_{n}$ и $y_{n+1} = \\beta x_{n}$, где $α = 1.4$, $β = 0.3$:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "3nMMP4Zj1Bwu"
},
"outputs": [],
"source": [
"def xenon_map(x=0, y=0, alpha=1.4, beta=0.3):\n",
" x_next = 1 - alpha * x ** 2 + y\n",
" y_next = beta * x\n",
" return x_next, y_next"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "9HXiFkDoggID"
},
"source": [
"Укажите количество точек во временном ряде, который будет получен из отображения Хенона:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "BUgZtjUyggID"
},
"outputs": [],
"source": [
"n_points = # Ваш код здесь"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "XPr65SPMggIE"
},
"source": [
"Сгенерируем необходимое количество точек — помним, что нужна только переменная $x$:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "iJQi12wm22eR"
},
"outputs": [],
"source": [
"x, y = 0, 0\n",
"xenon_data = []\n",
"for i in range(n_points):\n",
" x, y = xenon_map(x, y)\n",
" xenon_data.append(x)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "vKcPkUDCggIF"
},
"source": [
"Поскольку исходная задача является задачей прогнозирования, то обучающая выборка должна включать в себя первый участок временного ряда, на котором будет обучаться модель. Валидационная выборка, на которой мы оцениваем качество предсказания модели, всегда должна идти после обучающей (аналогично с тестовой).\n",
"\n",
"Выделим, к примеру, первые 70% данных временного ряда `xenon_data` для обучающей выборки, следующие данные по 15% отнесём к вылидационной и тестовой выборкам (вторая и третья части данных соответственно):"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "1ZMHrs0c4Ihy"
},
"outputs": [],
"source": [
"train_size = int(0.7 * n_points)\n",
"valid_size = int(0.15 * n_points)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "JDK1n0N-ggIF"
},
"source": [
"Представим данные для выборок на графике:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 430
},
"id": "fcaFy3iWjeQQ",
"outputId": "64abe542-cee1-4183-b616-6c7e9c41118e"
},
"outputs": [],
"source": [
"plt.plot(xenon_data, color='k', label='Xenon Data')\n",
"plt.axvspan(0, train_size, alpha=0.35, color='blue', label='Train')\n",
"plt.axvspan(train_size, train_size+valid_size, alpha=0.35, color='orange', label='Valid')\n",
"plt.axvspan(train_size+valid_size, n_points, alpha=0.35, color='green', label='Test')\n",
"plt.legend(loc='best')\n",
"plt.grid(True, alpha=0.3)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "pej4dfNRggIG"
},
"source": [
"Пройдём с единичным шагом по всем данным `xenon_data` скользящим окном длиною `seq_length`(например, длиною 10). Таким образом сформируем пары «вход‑выход» для модели:\n",
" - `X_data`: последовательности из `seq_length` элементов (скользящее окно по `xenon_data`),\n",
" - `y_data`: элемент, следующий сразу за каждой последовательностью в `X_data`.\n",
"\n",
"***Примечание***. С помощью `[:-1]` мы убираем в `X_data` последнее окно, для которого нет «следующего значения» в `y_data`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "C2KR8vptSKVH"
},
"outputs": [],
"source": [
"seq_length = 10\n",
"\n",
"X_data = np.lib.stride_tricks.sliding_window_view(xenon_data, window_shape=seq_length)[:-1]\n",
"y_data = xenon_data[seq_length:]"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "wM5lRDRnLWY4"
},
"source": [
"Посмотрим конец полученных данных. Видно, что последнее значение `y_data` не включено в окна из `X_data`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "13yK1ZsbUfWk",
"outputId": "5e86b1ee-c455-4087-f1c9-b1accff382fd"
},
"outputs": [],
"source": [
"X_data[-2:]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "5639fOPUTl2Q",
"outputId": "483d2e6d-36e5-4d4a-cbed-726dc0ed4eec"
},
"outputs": [],
"source": [
"y_data[-4:]"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "04Pd841VggII"
},
"source": [
"Длина наших данных — без учёта последнего значения:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "k62uvZDNONY1"
},
"outputs": [],
"source": [
"assert len(X_data) == len(y_data) == n_points - seq_length"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "v8vK2daVggIJ"
},
"source": [
"Разделим данные на обучающую, валидационную и тестовую выборку по заданному выше соотношению 70%/15%/15%:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "jvRzLs7rS9QF"
},
"outputs": [],
"source": [
"X_train, X_valid, X_test = X_data[:train_size], X_data[train_size:train_size+valid_size], X_data[train_size+valid_size:]\n",
"y_train, y_valid, y_test = y_data[:train_size], y_data[train_size:train_size+valid_size], y_data[train_size+valid_size:]"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "i4VgXIcRV91m"
},
"source": [
"Отнормируйте или отстанлартизируйте входные и выходные данные.\n",
"\n",
"Поскольку нормирующие или стандартизирующие величины (минимум, максимум, среднее, СКО) всегда расчитываются только по значениям обучающей выборки, берём из исходных данных `xenon_data` также значения, которые попадут в последнее окно (и снова исключаем самое последнее значение):"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "fjN96i_1ggIJ"
},
"outputs": [],
"source": [
"X_mean = np.mean(xenon_data[:train_size+seq_length-1])\n",
"X_std = np.std(xenon_data[:train_size+seq_length-1], ddof=1)\n",
"y_mean = np.mean(y_data[:train_size])\n",
"y_std = np.std(y_data[:train_size], ddof=1)\n",
"\n",
"X_train_scaled = # Ваш код здесь\n",
"X_valid_scaled = # Ваш код здесь\n",
"X_test_scaled = # Ваш код здесь\n",
"\n",
"y_train_scaled = # Ваш код здесь\n",
"y_valid_scaled = # Ваш код здесь\n",
"y_test_scaled = # Ваш код здесь"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "gGVJqQGUggIK"
},
"source": [
"## 2. Сеть с радиально-базисными функциями<a id=\"p_2\"></a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "xm61W3LPggIK"
},
"source": [
"РБФ-сеть (Radial Basis Function Network, RBF) — это нейронная сеть, которая использует радиально-базисные функции в качестве функций активации нейронов скрытого слоя. Архитектура такой сети обычно включает три слоя:\n",
" - Входной слой — принимает входные данные (значения временного ряда).\n",
" - Скрытый слой — содержит нейроны с радиальными базисными функциями. Каждый нейрон вычисляет расстояние между входным вектором и заранее определённым центром функции, а затем преобразует это расстояние с помощью радиальной функции.\n",
" - Выходной слой — линейно комбинирует (взвешенно суммирует) выходы скрытых нейронов, чтобы получить итоговый результат.\n",
"\n",
"Таким образом, выходной сигнал РБФ‑сети вычисляется по формуле:\n",
"\n",
"$$\n",
"y(\\mathbf{x}) = \\sum_{j=1}^{H} w_j \\cdot \\phi(\\|\\mathbf{x} - \\mathbf{c}_j\\|_2)\n",
"$$\n",
"где:\n",
"* $y(\\mathbf{x})$ — выходной сигнал сети для входного вектора $\\mathbf{x}$;\n",
"* $H$ — количество нейронов в скрытом слое;\n",
"* $w_j$ — вес связи от $j$-го нейрона скрытого слоя к выходному слою;\n",
"* $\\mathbf{c}_j$ — центр $j$-й радиально-базисной функции;\n",
"* $\\phi$ — радиально-базисная функция;\n",
"* $\\|\\mathbf{x} - \\mathbf{c}_j\\|_2$ — евклидово расстояние между входным вектором $\\mathbf{x}$ и центром $\\mathbf{c}_j$.\n",
"\n",
"Радиально-базисная функция — это функция, которая зависит только от расстояния между входным вектором и центром функции. Чаще всего используется гауссова функция:\n",
"$$\n",
"\\phi(r) = \\exp\\left(-\\frac{r^2}{2\\sigma^2}\\right)\n",
"$$\n",
"где $r = \\|\\mathbf{x} - \\mathbf{c}\\|_2$, $\\sigma$ — параметр ширины окна.\n",
"\n",
"Обучение РБФ‑сетей обычно проходит в два этапа:\n",
"\n",
"1. Определение параметров радиально-базисной функции (центров $\\mathbf{c}_i$ и ширин $\\sigma_i$):\n",
" * кластеризация (например, kmeans) для нахождения центров;\n",
" * эвристические методы или кросс‑валидация для ширин.\n",
"\n",
"2. Обучение выходных весов $w_j$:\n",
" * решение задачи линейной регрессии (с использованием обучения с учителем, например, методом наименьших квадратов или градиентного спуска).\n",
" \n",
"Таким образом, на первом этапе сеть определяет, где в пространстве признаков сосредоточены основные закономерности данных. Для этого, например, используются алгоритмы кластеризации: объекты (значения временного ряда) внутри одного кластера получатся максимально похожи друг на друга, а объекты разных классов — максимально различны (т.о. определим важные зоны или паттерны ряда).\n",
"\n",
"После определения центров сеть анализирует, как каждая точка соотносится с ними. Это показывает гауссова РБФ — для каждой точки вычисляется расстояние до каждого из центров, и чем ближе точка к центру, тем выше значение функции (близко к 1), а также наоборот — чем дальше точка к центру, тем ниже (РБФ стремится к 0). Для каждой точки получается вектор активаций — набор чисел, показывающих, насколько она «похожа» на каждый из центров. Так, точка между двумя центрами даст средние значения для обоих, а точка рядом с одним центром — высокое значение для него и низкие для остальных.\n",
"\n",
"На этих активациях для получения весов между скрытым и выходным слоями обучается линейная регрессия. Она находит оптимальные веса для каждого выхода скрытого слоя: какие локальные паттерны важнее для прогноза, какие — менее значимы."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "2y2jya41ggIL"
},
"source": [
"Реализуем с помощью класса `RBFPredictor` РБФ-сеть с описанной выше архитектурой.\n",
"\n",
"При инициализации (`.__init__()`) задаётся `n_centers` — число центров (нейронов скрытого слоя), устанавливается параметр ширины окна `sigma` для гауссовой функции, создаётся модель линейной регрессии `linear_model` для выходного слоя (взята из библиотеки sklearn).\n",
"\n",
"Выбор `n_centers` центров из входных данных происходит в методе `.fit()`. Для этого используется алгоритм kmeans (взят из библиотеки sklearn).\n",
"\n",
"Далее в скрытом слое (метод `._radial_basis()`) для каждого входного вектора (объекта) вычисляются расстояния до всех центров. Расстояния преобразуются в значения гауссовой РБФ. На выходе получается матрица активаций размером (число объектов, число центров).\n",
"\n",
"На данной матрице активаций скрытого слоя `phi` и целевых значениях `y` обучается модель линейной регрессии `linear_model`. Веса регрессии становятся весами связей от скрытого слоя к выходному.\n",
"\n",
"При прогнозировании (метод `.predict()`) для новых данных вычисляются активации скрытого слоя (через гауссовы РБФ относительно тех же центров), а обученная линейная модель применяет веса к этим активациям и выдаёт финальный прогноз."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "yjn8NBbYXA5p"
},
"outputs": [],
"source": [
"class RBFPredictor:\n",
" def __init__(self, n_centers, sigma=1.0):\n",
" self.n_centers = n_centers\n",
" self.sigma = sigma\n",
" self.centers = None\n",
" self.linear_model = LinearRegression()\n",
"\n",
"\n",
" def _radial_basis(self, X, centers):\n",
" distances = np.zeros((X.shape[0], centers.shape[0]))\n",
" for i, center in enumerate(centers):\n",
" distances[:, i] = np.sqrt(np.sum((X - center) ** 2, axis=1))\n",
" return np.exp(-(distances ** 2) / (2 * self.sigma ** 2))\n",
"\n",
"\n",
" def fit(self, X, y):\n",
" # Выбираем центры с помощью кластеризации\n",
" kmeans = KMeans(n_clusters=self.n_centers, random_state=42)\n",
" self.centers = kmeans.fit(X).cluster_centers_\n",
" # Вычисляем выход скрытого слоя\n",
" phi = self._radial_basis(X, self.centers)\n",
" # Обучаем линейный выходной слой\n",
" self.linear_model.fit(phi, y)\n",
"\n",
"\n",
" def predict(self, X):\n",
" phi = self._radial_basis(X, self.centers)\n",
" return self.linear_model.predict(phi)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "2IAX5UXUggIL"
},
"source": [
"Обучите модель `model_rbf`. Для этого подберите подходящее количество центров `n_centers` и ширину окна `sigma`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "a5RQRqH5ggIM"
},
"outputs": [],
"source": [
"model_rbf = RBFPredictor(\n",
" # Ваш код здесь\n",
")\n",
"\n",
"model_rbf.fit(X_train_scaled, y_train_scaled)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "bOlEYLHGggIN"
},
"source": [
"При подборе добейтесь примерно одинаковой (или хотя бы сопоставимой) ошибки на обучающей и вадилационной выборках:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "T1RLJMCyivU1",
"outputId": "00671844-3026-4302-ecfc-0130c6f840f0"
},
"outputs": [],
"source": [
"pred_rbf_train = model_rbf.predict(X_train_scaled)\n",
"pred_rbf_valid = model_rbf.predict(X_valid_scaled)\n",
"\n",
"print('Loss')\n",
"print(f'Train: {mse(pred_rbf_train, y_train_scaled):.6f}')\n",
"print(f'Valid: {mse(pred_rbf_valid, y_valid_scaled):.6f}')"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "NLZo9mQKggIm"
},
"source": [
"Проверка `model_rbf` на тестовых данных будет ниже."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "G2kFrJUAmWRz"
},
"source": [
"## 3. Многослойный персептрон<a id=\"p_3\"></a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "3kvNrdq3ggIn"
},
"source": [
"Представим входные и выходные данные в виде тензоров PyTorch:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "-GkRe60zptZd"
},
"outputs": [],
"source": [
"X_train_tensor = torch.tensor(X_train_scaled).float()\n",
"y_train_tensor = torch.tensor(y_train_scaled).reshape(-1, 1).float()\n",
"X_valid_tensor = torch.tensor(X_valid_scaled).float()\n",
"y_valid_tensor = torch.tensor(y_valid_scaled).reshape(-1, 1).float()\n",
"X_test_tensor = torch.tensor(X_test_scaled).float()\n",
"y_test_tensor = torch.tensor(y_test_scaled).reshape(-1, 1).float()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "p6INgMk6ggIn"
},
"source": [
"Реализуйте в классе `MLPPredictor` с помощью полносвязных слоёв `nn.Linear` многослойный персептрон. В качестве промежуточных функций активации используйте `nn.ReLU()`, а поскольку решается задача прогнозирования вещественных данных, на выходе сети функцию активации можно не добавлять."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "Cg-m7jZNggIn"
},
"outputs": [],
"source": [
"class MLPPredictor(nn.Module):\n",
" def __init__(self, input_size):\n",
" super().__init__()\n",
" self.seq = nn.Sequential(\n",
" # Ваш код здесь\n",
" )\n",
"\n",
" def forward(self, x):\n",
" return self.seq(x)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "YPF9PyDcycNn"
},
"source": [
"Создайте экземпляр модели:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "T2WBlrBMhA08",
"outputId": "41040db9-10fe-4705-e27a-9f42ebd7ac4f"
},
"outputs": [],
"source": [
"model_mlp = MLPPredictor(input_size=seq_length)\n",
"model_mlp"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "CTVh4iOjggIp"
},
"source": [
"Проверим, как модель обучается. Зададим оптимизатор и среднеквадратическую функцию потерь:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "VGWgT-_UKY5S"
},
"outputs": [],
"source": [
"optimizer = torch.optim.SGD(model_mlp.parameters(), lr=0.01)\n",
"criterion = nn.MSELoss()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "-YGsKE_SggIp"
},
"source": [
"Рассчитаем значение функции потерь:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "8qFQWNrMZyzM",
"outputId": "a7e21b4c-425d-46c5-8406-1a27c6c193ef"
},
"outputs": [],
"source": [
"pred_mlp_train = model_mlp(X_train_tensor)\n",
"\n",
"loss = criterion(pred_mlp_train, y_train_tensor)\n",
"loss"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "drYc365KggIq"
},
"source": [
"Выполните несколько раз эту и предыдущую ячейку, чтобы убедиться в уменьшении ошибки:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "UlggYk-KbfnF"
},
"outputs": [],
"source": [
"loss.backward()\n",
"optimizer.step()\n",
"optimizer.zero_grad()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "F1hRU9Uj07TE"
},
"source": [
"Задайте параметры для обучения нейронной сети:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "nkJ3lGsgggIr"
},
"outputs": [],
"source": [
"# Перебор seed для инициализации параметров\n",
"torch.manual_seed(seed=42)\n",
"\n",
"model_mlp = # Ваш код здесь\n",
"\n",
"epochs = # Ваш код здесь\n",
"\n",
"learning_rate = # Ваш код здесь\n",
"momentum = # Ваш код здесь\n",
"\n",
"optimizer = # Ваш код здесь\n",
"criterion = # Ваш код здесь"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "9rpN21H-ggIs"
},
"source": [
"**Обучение нейронной сети:**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "4tZGNdtWggIs"
},
"outputs": [],
"source": [
"loss_train_history, loss_valid_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_train_history, label='Train', color='green')\n",
" plt.plot(range(1, epoch+2), loss_valid_history, label='Valid', color='red')\n",
" plt.title(f'Epoch: {epoch + 1}, Loss Train: {loss_train_history[-1]:.6f}, Loss Valid: {loss_valid_history[-1]:.6f}')\n",
" plt.grid(True, alpha=0.3)\n",
" plt.legend(loc='best')\n",
" plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "RbvISk2MfSC5"
},
"source": [
"## 4. Сравнение моделей<a id=\"p_4\"></a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "CDKiO9MDggIt"
},
"source": [
"Получим прогнозы на тестовой выборке от РБФ-сети и многослойного персептрона:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "tKZ0sdh0eB91"
},
"outputs": [],
"source": [
"pred_rbf_test = model_rbf.predict(X_test_scaled)\n",
"\n",
"with torch.no_grad():\n",
" pred_mlp_test = model_mlp(X_test_tensor).squeeze().numpy()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "UA_BcjAjggIu"
},
"source": [
"Поскольку обучение шло на нормированных или стандартизированных данных, приведём прогнозы к исходной шкале и рассчитаем среднеквадратическую ошибку:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "tl6X5LGZfjOY",
"outputId": "bef46cea-f16c-41a2-8f12-8f3e967a5ac3"
},
"outputs": [],
"source": [
"pred_rbf_test_descaled = (pred_rbf_test * y_std + y_mean)\n",
"pred_mlp_test_descaled = (pred_mlp_test * y_std + y_mean)\n",
"\n",
"print('Loss')\n",
"print(f'RBF: {mse(pred_rbf_test_descaled, y_test):.6f}')\n",
"print(f'MLP: {mse(pred_mlp_test_descaled, y_test):.6f}')"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "oLOykwtViDsY"
},
"source": [
"Построим графики прогнозов для сравнения с исходными тестовыми данными:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 303
},
"id": "b0IlMe5EjpNl",
"outputId": "6fa95c1b-3756-41fe-f020-358c07dd6b8c"
},
"outputs": [],
"source": [
"plt.figure(figsize=(12, 4))\n",
"\n",
"plt.plot(y_test, label='True Values')\n",
"plt.plot(pred_rbf_test_descaled, label='RBF Pred')\n",
"plt.plot(pred_mlp_test_descaled, label='MLP Pred')\n",
"plt.grid(True, alpha=0.3)\n",
"plt.legend(loc='best')\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Vs0-pqwUnqlL"
},
"source": [
"## 5. Прогнозирование курса доллара<a id=\"p_5\"></a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "4Od-qc-cnqqe"
},
"source": [
"По аналогии с отображением Хенона самостоятельно реализуйте прогнозирование курса доллара.\n",
"\n",
"Для этого скачайте актуальную информацию по курсу с сайта http://www.cbr.ru в формате `.xlsx`.\n",
"\n",
"Введите в виже строки имя скачанного файла с расширением:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "Z0OkaJZ8ggIw"
},
"outputs": [],
"source": [
"dollar_course_filename = # Ваш код здесь"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "cIxIxznLggIx"
},
"source": [
"Загрузим данные в массив NumPy:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "oDN_CihKC4SB",
"outputId": "14391340-b0b6-4017-8771-f54f6306ce71"
},
"outputs": [],
"source": [
"dollar_data = pd.read_excel(dollar_course_filename).curs[::-1]\n",
"\n",
"# По необходимости можно сгладить данные скользящим окном -\n",
"# в данном случае берём среднее за 7 дней\n",
"dollar_data = dollar_data.rolling(window=7).mean().dropna()\n",
"\n",
"dollar_data = dollar_data.values"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "_HnJACO1ggIy"
},
"outputs": [],
"source": [
"# Ваш код здесь"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Ваш код здесь"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Ваш код здесь"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "mwXH9dIBggI4"
},
"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": {
"id": "Je7Xm08vggI5"
},
"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
}

Просмотреть файл

@@ -19,7 +19,9 @@
"> а) для исходных данных из 5-ти классов; \n", "> а) для исходных данных из 5-ти классов; \n",
"> б) для исходных данных из 4-х классов. \n", "> б) для исходных данных из 4-х классов. \n",
"> Провести визуализацию данных в скрытом слое каждой сети на плоскость и в 3-х мерное пространство. Проанализировать полученные результаты. Выбрать и сохранить автоассоциативные ИНС, обеспечивающие наилучшее сжатие исходных данных. \n", "> Провести визуализацию данных в скрытом слое каждой сети на плоскость и в 3-х мерное пространство. Проанализировать полученные результаты. Выбрать и сохранить автоассоциативные ИНС, обеспечивающие наилучшее сжатие исходных данных. \n",
"> 2. \n", "> 2. Исследовать возможности ИНС по прогнозированию поведения нелинейных динамических систем (построение странного аттрактора) на примере отображения Хенона. Аттрактор Хенона может быть получен из уравнений $x_{n+1} = 1 - \\alpha x_{n}^2 + y_{n}$ и $y_{n+1} = \\beta x_{n}$, где $α = 1.4$, $β = 0.3$.\n",
"> Для прогнозирования предлагается использовать многослойный персептрон и сеть с радиально-базисными функциями.\n",
"> Постройте также прогноз курса доллара на один день вперед. В качестве исходных данных загрузить актуальные данные с сайта центрального банка России (http://www.cbr.ru).\n",
"> 3. Решить задачу распознавания 9-ти изображений самолетов. Исходные данные (файлы avia1.bmp, …, avia9.bmp) необходимо предварительно преобразовать в набор векторов со значениями признаков 0 или 1. Обученная нейронная сеть должна правильно определять модель самолета и его класс (истребитель/бомбардировщик). Принадлежность модели к определенному классу выбирается студентом самостоятельно." "> 3. Решить задачу распознавания 9-ти изображений самолетов. Исходные данные (файлы avia1.bmp, …, avia9.bmp) необходимо предварительно преобразовать в набор векторов со значениями признаков 0 или 1. Обученная нейронная сеть должна правильно определять модель самолета и его класс (истребитель/бомбардировщик). Принадлежность модели к определенному классу выбирается студентом самостоятельно."
] ]
}, },

621
lab4/4_kohonen.ipynb Обычный файл
Просмотреть файл

@@ -0,0 +1,621 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### ЛАБОРАТОРНАЯ РАБОТА №4\n",
"## Сеть Кохонена"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> Цель работы: знакомство с применением многослойного персептрона для решения задач сжатия данных, прогнозирования временных рядов и распознавания образов.\n",
">\n",
"> Задание\n",
"> 1. Изучить разделы справки связанные с обучением сети Кохонена. Загрузить набор данных, содержащий измерения длины и ширины чашелистика и лепестка 150 экземпляров ириса (ирисы Фишера). Создать сеть Кохонена и выполнить с помощью неё кластеризацию сортов ириса. Проанализировать полученные результаты. Выполнить визуализацию исходных данных.\n",
"> 2. Построить и обучить сеть Кохонена для кластеризации данных скрытого слоя автоассоциативной сети из п.1. лабораторной работы №3. Проанализировать результаты и сравнить их с результатами классификации многослойным персептроном, полученными в лабораторной работе №2.."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Импорт библиотек:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "5pnjRdYLSLXZ"
},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"from IPython.display import clear_output\n",
"from mpl_toolkits.mplot3d import Axes3D\n",
"from sklearn.datasets import load_iris\n",
"\n",
"%matplotlib inline"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Содержание: \n",
"[1. Ирисы Фишера](#p_1) \n",
"[2. Данные скрытого слоя](#p_2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. Ирисы Фишера<a id=\"p_1\"></a>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Сеть Кохонена (или самоорганизующаяся карта) — это тип нейронных сетей без учителя (unsupervised learning), разработанный финским учёным Теуво Кохоненом. \n",
"\n",
"Основная цель таких сетей — визуализация и кластеризация многомерных данных путём их проецирования на пространство меньшей размерности (чаще всего двумерное).\n",
"\n",
"Ключевые особенности:\n",
" - Без учителя: не требует размеченных данных для обучения.\n",
" - Топологическое упорядочивание: сохраняет пространственные отношения между точками данных — близкие входные векторы активируют соседние нейроны на карте.\n",
" - Конкурентное обучение: в каждый момент времени «побеждает» только один нейрон (ближайший к входному вектору).\n",
"\n",
"Обучение сети Кохонена происходит итеративно, по одному примеру за раз.\n",
" - Шаг 1. Инициализация. \n",
"Веса всех нейронов инициализируются случайными значениями (обычно из того же распределения, что и входные данные).\n",
" - Шаг 2. Выбор входного вектора. \n",
"Из набора данных случайным образом выбирается один образец $x$ (пусть количество признаков равно $m$).\n",
" - Шаг 3. Определение «нейрона‑победителя». \n",
"Находится нейрон, вектор весов которого наиболее близок к входному вектору. Мера близости — обычно евклидово расстояние:\n",
"\n",
"$$\n",
"d(x, w_i) = \\sqrt{\\sum_{j=1}^{m} (x_j - w_{ij})^2}\n",
"$$\n",
"\n",
" - Шаг 4. Обновление весов. \n",
"Вектор весов нейрона‑победителя (и, опционально, его соседей) подтягивается ближе к входному вектору:\n",
"\n",
"$$\n",
"w_i(t+1) = w_i(t) + \\eta(t) \\cdot (x(t) - w_i(t))\n",
"$$\n",
"\n",
"где $w_i$ — вектор весов $i$-го нейрона (кластера); $\\eta(t)$ — скорость обучения (learning rate) в момент времени $t$, которая определяет, насколько сильно будут скорректированы веса; $x(t)$ — текущий входной вектор.\n",
"\n",
" - Шаг 5. Уменьшение скорости обучения. \n",
"На этом этапе скорость обучения $\\eta$ постепенно уменьшается с каждой эпохой. Это необходимо для стабилизации карты в конце обучения: на ранних этапах допускаются большие корректировки весов (чтобы быстро приблизиться к оптимальной конфигурации), а на поздних — только мелкие уточнения. Обновление скорости обучения происходит по следующему правилу:\n",
"\n",
"$$\n",
"\\eta(t+1) = \\eta(t) \\times \\text{decay}\n",
"$$\n",
"\n",
"где $\\text{decay}$ — коэффициент затухания (гиперпараметр, обычно близкий к $1$, например $0{,}99$ или $0{,}95$).\n",
"\n",
" - Шаг 6. Повторение. \n",
"Шаги 2–5 повторяются заданное число эпох или до сходимости (т.е. пока значения весов нейронов в карте практически не перестанут меняться от эпохи к эпохе — структура карты, таким образом, уже сформирована и отражает топологию входных данных).\n",
"\n",
"Преимущества сетей Кохонена:\n",
" - простота реализации и интерпретации;\n",
" - наглядная визуализация сложных данных;\n",
" - устойчивость к шуму в данных;\n",
" - сохранение топологических свойств исходного пространства.\n",
"\n",
"Недостатки:\n",
" - чувствительность к инициализации весов;\n",
" - необходимость ручного подбора числа кластеров;\n",
" - относительно медленное обучение на больших наборах данных.\n",
" - результат может зависеть от порядка предъявления данных (поэтому их необходимо перемешивать).\n",
"\n",
"Описанная выше сеть Кохонена реализована в классе `KohonenClustering`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "JJtHNld8SOWL"
},
"outputs": [],
"source": [
"class KohonenClustering:\n",
" def __init__(self, n_clusters, lr=0.1, decay=0.99):\n",
" self.n_clusters = n_clusters\n",
" self.lr = lr\n",
" self.decay = decay\n",
" self.cluster_weights = None\n",
"\n",
" def winner(self, x):\n",
" \n",
" # Вычисляем евклидово расстояние от входного вектора до каждого кластера\n",
" distances = np.zeros((x.shape[0], self.n_clusters))\n",
" for i, cluster_weight in enumerate(self.cluster_weights):\n",
" distances[:, i] = np.sqrt(np.sum((x - cluster_weight) ** 2, axis=1))\n",
" \n",
" # Находим индексы нейронов с минимальным расстоянием (победителей)\n",
" winner_idx = np.argmin(distances, axis=1)\n",
" return winner_idx\n",
"\n",
" def fit(self, data, epochs=100):\n",
"\n",
" self.cluster_weights = np.random.randn(self.n_clusters, data.shape[1]).astype(np.float32)\n",
" \n",
" lr_history = []\n",
" for epoch in range(epochs):\n",
"\n",
" # Перемешиваем индексы данных для случайного выбора векторов\n",
" indices = np.random.permutation(data.shape[0])\n",
" \n",
" # Проходим по всем векторам в случайном порядке\n",
" for i in indices:\n",
" # Извлекаем один вектор\n",
" x = data[i:i+1]\n",
" \n",
" # Определяем нейрон‑победитель для текущего входного вектора\n",
" winner_idx = self.winner(x)\n",
" \n",
" # Обновляем веса победившего нейрона: подтягиваем их ближе к входному вектору\n",
" for i, idx in enumerate(winner_idx):\n",
" self.cluster_weights[idx] += self.lr * (x[i] - self.cluster_weights[idx])\n",
"\n",
" lr_history.append(self.lr)\n",
"\n",
" # Постепенно уменьшаем скорость обучения для стабилизации карты\n",
" self.lr *= self.decay\n",
"\n",
" if (epoch + 1) % 5 == 0:\n",
"\n",
" clear_output(True)\n",
" plt.plot(range(1, epoch+2), lr_history, label='Learning Rate')\n",
" plt.title(f'Epoch: {epoch + 1}, Learning Rate: {lr_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": {
"id": "N7kdsjBEWy3P"
},
"outputs": [],
"source": [
"iris_data = load_iris()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Значения четырёх входных признаков:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "1qmf6ZAxWy8A",
"outputId": "b7eaeee4-39ea-4204-e6e7-f9b47a10f73f",
"scrolled": false
},
"outputs": [],
"source": [
"X_iris_data = iris_data['data']\n",
"print(X_iris_data[:5])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Названия признаков — длина и ширина чашелистика, длина и ширина лепестка:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "UDNslebrcXfK",
"outputId": "9ece4206-94c9-436d-c6a2-d6bbf2495fa0"
},
"outputs": [],
"source": [
"iris_data['feature_names']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Значения выходного признака — метки классов (три сорта ирисов):"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "IF6_sIBtXjNI",
"outputId": "c59b99c6-3c1d-4576-d88c-6b7c870a9428"
},
"outputs": [],
"source": [
"y_iris_data = iris_data['target']\n",
"print(y_iris_data)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Названия сортов ирисов:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "IWZwrWKaX2R8",
"outputId": "59e3f58e-71a1-40e2-9410-8871c5b0b695"
},
"outputs": [],
"source": [
"iris_names = iris_data['target_names']\n",
"print(iris_names)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Поскольку при обучении сети Кохонена вычисляются евклидовы расстояния между входными данными и весами нейронов, входные данные рекомендуются отнормировать или отстандартизировать:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"X_means = X_iris_data.mean(axis=0)\n",
"X_stds = X_iris_data.std(axis=0, ddof=1)\n",
"\n",
"X_iris_data_scaled = # Ваш код здесь"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Обучите модель `kohonen_iris` на нормированных (или стандартизированных) данных.\n",
"\n",
"Для этого подберите количество кластеров `n_clusters`, скорость обучения `lr`, шаг снижения скорости обучения `decay`. При неоходимости измените количество эпох `epochs`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"kohonen_iris = KohonenClustering(\n",
" n_clusters= # Ваш код здесь\n",
" lr= # Ваш код здесь\n",
" decay= # Ваш код здесь\n",
")\n",
"\n",
"kohonen_iris.fit(X_iris_data_scaled, epochs=100)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Получим метки кластеров — сопоставьте их с исходными метками классов:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "4gVxatZFYVCm",
"outputId": "bfa24efd-eb30-4036-c01d-5e09aa8b931e"
},
"outputs": [],
"source": [
"clusters_iris = kohonen_iris.winner(X_iris_data_scaled)\n",
"print(clusters_iris)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Построим диаграмму рассеяния, например, для пары признаков — длины и ширины лепестка. Точки разметим по трём сортам ирисов:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 450
},
"id": "B8vgAwpQd4Zh",
"outputId": "ebf196cd-ea4e-4367-a88b-cbc22bb9a7c5"
},
"outputs": [],
"source": [
"scatter = plt.scatter(X_iris_data[:, 2], X_iris_data[:, 3], c=y_iris_data)\n",
"plt.xlabel('petal length (cm)')\n",
"plt.ylabel('petal width (cm)')\n",
"plt.grid(True, alpha=0.3)\n",
"\n",
"# Код для легенды\n",
"handles, _ = scatter.legend_elements(prop='colors')\n",
"plt.legend(handles, iris_names, loc='best', title='Classes')\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Построим такую же диаграмму, олнако точки в ней будут размечены по меткам кластеров: "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 450
},
"id": "hWedmXtmeKXH",
"outputId": "0c8b239e-b140-4cdc-d80f-238bc3038304"
},
"outputs": [],
"source": [
"scatter = plt.scatter(X_iris_data[:, 2], X_iris_data[:, 3], c=clusters_iris)\n",
"plt.xlabel('petal length (cm)')\n",
"plt.ylabel('petal width (cm)')\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='Clusters')\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "6Wlm1xrBYzuf"
},
"source": [
"Поэкспериментируйте с количеством кластеров `n_clusters`. Проанализируйте варианты, когда:\n",
" - количество кластеров совпадает с количеством сортов ирисов;\n",
" - кластеров меньше сортов ирисов;\n",
" - кластеров больше сортов ирисов."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. Данные скрытого слоя<a id=\"p_2\"></a>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Загрузим из файла `encoded_2d.npy` двумерные данные с выхода энкодера автоассоциативной сети из третьей лабораторной работы:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "B0OS99x8Dz9v",
"outputId": "9b21ab60-5422-421f-e83b-64e378763bd7"
},
"outputs": [],
"source": [
"encoded_2d = np.load('encoded_2d.npy')\n",
"print(encoded_2d[:5])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Обучите модель `kohonen_2d` на этих данных. Количество кластеров пусть совпадает с количеством сортов минеральной воды (т.е. 5)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "3TXtr9d6SZ9a"
},
"outputs": [],
"source": [
"kohonen_2d = KohonenClustering(\n",
" # Ваш код здесь\n",
")\n",
"\n",
"kohonen_2d.fit(encoded_2d, epochs=100)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "LOv1vQ1kWKKf"
},
"source": [
"Получим метки кластеров:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "zm3DoRAEStuR"
},
"outputs": [],
"source": [
"clusters_2d = kohonen_2d.winner(encoded_2d)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "arnxu4zcSzyk"
},
"source": [
"Построим двухмерную диаграмму рассеяния:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 430
},
"id": "KkToPCInQQ1J",
"outputId": "418558e8-8c2a-4521-9ef1-6b25b971cff0"
},
"outputs": [],
"source": [
"scatter = plt.scatter(x=encoded_2d[:, 0], y=encoded_2d[:, 1], c=clusters_2d, 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='Clusters')\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Сравните диаграмму с соответствующим результатом из третьей лабораторной работы. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Загрузите данные из остальных файлов (`encoded_3d.npy`, `encoded_2d_include.npy`, `encoded_3d_include.npy`) и также обучите на них по отдельному экземпляру сети Кохонена. Получите метки кластеров и постройте для каждого набора диаграммы рассеяния. Сравните их с соответствующими диаграммами из третьей лабораторной работы."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "QwJagpWTWMIb"
},
"outputs": [],
"source": [
"# Ваш код здесь"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"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": {
"id": "w2UD2JKOWyrb"
},
"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
}