{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Пример запуска Нейросетевых Дифференциальных уравнений на синтетических данных" ] }, { "cell_type": "code", "execution_count": 71, "metadata": {}, "outputs": [], "source": [ "import os\n", "import argparse\n", "import logging\n", "import tqdm\n", "import numpy as np\n", "import torch\n", "import torch.nn as nn\n", "import torch.nn.functional as F" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Устанавливаем библиотеку с сайта авторов: https://github.com/rtqichen/torchdiffeq" ] }, { "cell_type": "code", "execution_count": 72, "metadata": {}, "outputs": [], "source": [ "from torchdiffeq import odeint" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Создаём классы ODEfunc, реализующий обучаемый модуль $f(\\cdot)$, из уравнения $\\frac{dz}{dt} = f(z(t), t, \\theta)$.\n", "В нашем случае, это будет простая трёхслойная полносвязанная нейросеть. Первый слой увеличивает размерность пространства,\n", "второй -- содержит основное число параметров, третий -- проецирует скрытое представление обратно в пространство малой размерности.\n", "\n", "При этом, в слои добавлена зависимость от $t$, как это требуется в исходной функции." ] }, { "cell_type": "code", "execution_count": 73, "metadata": {}, "outputs": [], "source": [ "class ODEfunc(nn.Module):\n", "\n", " def __init__(self, dim, hidden_dim):\n", " super(ODEfunc, self).__init__()\n", " self.first = nn.Linear(dim, hidden_dim)\n", " self.second = nn.Linear(hidden_dim + 1, hidden_dim)\n", " self.third = nn.Linear(hidden_dim + 1, dim)\n", "\n", " def forward(self, t, x):\n", " out = self.first(x)\n", " times = torch.ones_like(x) * t\n", " cat_inp = torch.cat((out, times), dim=1)\n", " out = self.second(cat_inp)\n", " out = F.relu(out)\n", " times = torch.ones_like(x) * t\n", " out = F.relu(out)\n", " cat_inp = torch.cat((out, times), dim=1)\n", " out = self.third(cat_inp)\n", " return out" ] }, { "cell_type": "code", "execution_count": 74, "metadata": {}, "outputs": [], "source": [ "def count_parameters(model):\n", " return sum(p.numel() for p in model.parameters() if p.requires_grad)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Создаём сеть и считаем количество параметров:" ] }, { "cell_type": "code", "execution_count": 75, "metadata": {}, "outputs": [], "source": [ "network = ODEBlock(ODEfunc(dim=1, hidden_dim=500))" ] }, { "cell_type": "code", "execution_count": 76, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "252502" ] }, "execution_count": 76, "metadata": {}, "output_type": "execute_result" } ], "source": [ "count_parameters(network)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Обучаем архитектуру.\n", "Возьмём синтетические данные - случайные числа от 0 до 2, будем предсказывать их квадрат.\n", "Заметим, что " ] }, { "cell_type": "code", "execution_count": 77, "metadata": {}, "outputs": [], "source": [ "optimizer = torch.optim.Adam(params=network.parameters(), lr=0.000001)" ] }, { "cell_type": "code", "execution_count": 79, "metadata": {}, "outputs": [], "source": [ "for i in range(20000):\n", " # генерируем данные\n", " batch = np.random.sample(size=(400, 1)) * 2\n", " values = batch ** 2\n", " batch = torch.tensor(batch, dtype=torch.float32)\n", " values = torch.tensor(values, dtype=torch.float32)\n", " \n", " # считаем значения и функцию потерь\n", " predictions = network(batch, tol=1e-3)\n", " loss = F.mse_loss(input=predictions, target=values)\n", " \n", " # считаем градиент ошибок по папарметрам и делаем шаг в направлении антиградиента\n", " loss.backward()\n", " optimizer.step()\n", "\n", " if i % 100 == 0:\n", " print(\"MSE Loss (iter {}): {:.3f}\".format(i, float(loss)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Визуализация" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "x = np.linspace(0, 2, 40)\n", "out = network(torch.tensor(x.reshape(-1, 1), dtype=torch.float32))" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "%matplotlib inline\n", "\n", "plt.style.use('ggplot')" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plt.figure(figsize=(6, 6))\n", "plt.plot(x, out.detach().numpy(), label='NeuralODE')\n", "plt.plot(x, x**2, label='golden')\n", "plt.legend()\n", "plt.show()" ] } ], "metadata": { "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.5.2" } }, "nbformat": 4, "nbformat_minor": 2 }