Files
neurocomputers-python/lab3/3.2_rbf.ipynb

990 строки
36 KiB
Plaintext
Исходник Ответственный История

Этот файл содержит неоднозначные символы Юникода
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"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
}