{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "Kb_PVxXaW2Qy" }, "source": [ "# Введение в анализ данных\n", "## Домашнее задание 4. Нейронные сети.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "duMi1QifW2Qz" }, "source": [ "**Правила, прочитайте внимательно:**\n", "\n", "* Выполненную работу нужно отправить телеграм-боту `@miptstats_ds24_bot`. Для начала работы с ботом каждый раз отправляйте `/start`. **Работы, присланные иным способом, не принимаются.**\n", "* Дедлайн см. в боте. После дедлайна работы не принимаются кроме случаев наличия уважительной причины.\n", "* Прислать нужно **ноутбук в формате `ipynb`**.\n", "* Следите за размером файлов. **Бот не может принимать файлы весом более 20 Мб.** Если файл получается больше, заранее разделите его на несколько.\n", "* Выполнять задание необходимо полностью самостоятельно. **При обнаружении списывания все участники списывания будут сдавать устный зачет.**\n", "* Решения, размещенные на каких-либо интернет-ресурсах, не принимаются. Кроме того, публикация решения в открытом доступе может быть приравнена к предоставлении возможности списать.\n", "* Для выполнения задания используйте этот ноутбук в качестве основы, ничего не удаляя из него. Можно добавлять необходимое количество ячеек.\n", "* Комментарии к решению пишите в markdown-ячейках.\n", "* Выполнение задания (ход решения, выводы и пр.) должно быть осуществлено на русском языке.\n", "* Если код будет не понятен проверяющему, оценка может быть снижена.\n", "* Никакой код из данного задания при проверке запускаться не будет. *Если код студента не выполнен, недописан и т.д., то он не оценивается.*\n", "\n", "**Правила оформления теоретических задач:**\n", "\n", "* Решения необходимо прислать одним из следующих способов:\n", " * фотографией в правильной ориентации, где все четко видно, а почерк разборчив,\n", " * отправив ее как файл боту вместе с ноутбуком *или*\n", " * вставив ее в ноутбук посредством `Edit -> Insert Image`;\n", " * в виде $LaTeX$ в markdown-ячейках.\n", "* Решения не проверяются, если какое-то требование не выполнено. Особенно внимательно все проверьте в случае выбора второго пункта (вставки фото в ноутбук). Неправильно вставленные фотографии могут не передаться при отправке. Для проверки попробуйте переместить `ipynb` в другую папку и открыть его там.\n", "* В решениях поясняйте, чем вы пользуетесь, хотя бы кратко. Например, если пользуетесь независимостью, то достаточно подписи вида \"*X и Y незав.*\"\n", "* Решение, в котором есть только ответ, и отсутствуют вычисления, оценивается в 0 баллов.\n", "\n", "\n", "\n", "\n", "\n", "**Баллы за задание:**\n", "\n", "Легкая часть (достаточно на \"хор\"):\n", "* Задача 1 — 60 баллов\n", "* Задача 2 — 30 баллов\n", "\n", "Сложная часть (необходимо на \"отл\"):\n", "* Задача 3 — 60 баллов\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "pWZ4wmCvW2Q0" }, "outputs": [], "source": [ "# Bot check\n", "\n", "# HW_ID: fpmi_ad4\n", "# Бот проверит этот ID и предупредит, если случайно сдать что-то не то.\n", "\n", "# Status: not final\n", "# Перед отправкой в финальном решении удали \"not\" в строчке выше.\n", "# Так бот проверит, что ты отправляешь финальную версию, а не промежуточную.\n", "# Никакие значения в этой ячейке не влияют на факт сдачи работы." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "ht9Xm0EucoAr" }, "outputs": [], "source": [ "import numpy as np\n", "import scipy.stats as sps\n", "\n", "import matplotlib.pyplot as plt\n", "import seaborn as sns\n", "\n", "sns.set(font_scale=1.2, palette='Set2')\n", "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": { "id": "2M__0kK2W2Q1" }, "source": [ "Перед выполнением задания обязательно посмотрите презентацию и обучающий ноутбук с занятия по нейронным сетям." ] }, { "cell_type": "markdown", "metadata": { "id": "NtWewpfoLl5S" }, "source": [ "---\n", "### Легкая часть" ] }, { "cell_type": "markdown", "metadata": { "id": "x-9Z1rmVW2Q1" }, "source": [ "---\n", "### Задача 1.\n", "\n", "Рассмотрим двухслойную нейронную сеть, которая принимает на вход $x\\in\\mathbb{R}$ и возвращает $y\\in\\mathbb{R}$. Выход первого слоя возвращает $u \\in\\mathbb{R}^2$. После первого слоя используется функция активации $\\sigma(x) = \\frac{1}{1 + \\exp(-x)}$, после второго слоя функция активации не используется (или используется тождественная). Тем самым нашу нейронную можно представить в виде\n", "\n", "$$\\widehat{y}(x) = \\sum_{h=1}^2 w_{2h}u_h(x) + b_2,$$\n", "\n", "$$u_h(x) = \\sigma(w_{1h}x + b_{1h}),$$\n", "\n", "$$\\text{где} \\; h \\in \\{1, 2\\}.$$\n", "\n" ] }, { "cell_type": "markdown", "metadata": { "id": "4eii8MGZW2Q1" }, "source": [ "**1.** Нарисуйте схематически данную нейронную сеть. Сколько у нее обучаемых параметров?" ] }, { "cell_type": "markdown", "metadata": { "id": "REawtgDJW2Q1" }, "source": [ "..." ] }, { "cell_type": "markdown", "metadata": { "id": "b8DZXIx7W2Q2" }, "source": [ "**2.** Пусть нам дана обучающая выборка $(X_1, Y_1), ..., (X_n, Y_n)$, где $X_i \\in \\mathbb{R}$ и $Y_i \\in \\mathbb{R}$. Нейронная сеть обучается по этой выборке, минимизируя заданную функцию $L$ — функцию ошибки. Положим, что $L$ — это MSE:\n", "$$\\text{MSE} = L(X, Y) = \\frac{1}{n}\\sum_{i=1}^n \\big(Y_i - \\widehat{y}(X_i)\\big)^2.$$\n", "\n", "Наша задача — найти оптимальные параметры нашей модели для минимизации $L(X, Y)$ на заданном наборе данных. Мы будем решать эту задачу с помощью градиентного спуска. Для этого нам понадобится выписать производные по всем параметрам сети. Конечно, в данном случае довольно просто выписать все производные напрямую. Однако мы воспользуемся следующей хитростью: мы будем считать производные поэтапно, причем начнем с конца вычислительной цепочки и, используя формулу производной сложной функции, последовательно посчитаем все необходимые производные. Этот процесс называется методом **обратного распространения ошибки (backpropagation)**." ] }, { "cell_type": "markdown", "metadata": { "id": "sns2ZZArW2Q2" }, "source": [ "**2.1.** Начнем с производной MSE по выходам сети\n", "$$\\frac{\\partial\\:\\text{MSE}}{\\partial \\widehat{y}(X_i)} = \\; ...$$" ] }, { "cell_type": "markdown", "metadata": { "id": "mN2TO-MAW2Q2" }, "source": [ "**2.2** Возьмем производные выходов сети по параметрам последнего слоя\n", "\n", "$$\\frac{\\partial \\widehat{y}(X_i)}{\\partial w_{2h}} = \\; ...$$\n", "\n", "$$\\frac{\\partial \\widehat{y}(X_i)}{\\partial b_2} = \\; ...$$\n", "\n", "Также выпишем производные выходов сети по входам последнего слоя\n", "\n", "$$\\frac{\\partial \\widehat{y}(X_i)}{\\partial u_h(X_i)} = \\; ...$$\n", "\n", "Теперь выпишем производные MSE по параметрам и входам последнего слоя. Для этого вспомните правило производной сложной функции из математического анализа. Обратите внимание на то, что нам не нужно прописывать все производные до конца, достаточно заполнить пропуски в записи ниже:\n", "\n", "$$\\frac{\\partial\\:\\text{MSE}}{\\partial w_{2h}} = \\sum_{i=1}^n \\frac{\\partial\\:\\text{MSE}}{\\partial ...} \\frac{\\partial ...}{\\partial w_{2h}}$$\n", "\n", "$$\\frac{\\partial\\:\\text{MSE}}{\\partial b_2} = \\sum_{i=1}^n \\frac{\\partial\\:\\text{MSE}}{\\partial ...} \\frac{\\partial ...}{\\partial b_2}$$\n", "\n", "$$\\frac{\\partial\\:\\text{MSE}}{\\partial u_h} = \\sum_{i=1}^n \\frac{\\partial\\:\\text{MSE}}{\\partial ...} \\frac{\\partial ...}{\\partial u_h}$$" ] }, { "cell_type": "markdown", "metadata": { "id": "u4_alAF5W2Q2" }, "source": [ "**2.2.** Теперь будем разбираться с производными по параметрам первого слоя.\n", "\n", "Для начала нам пригодится производная функции активации, запишите ее так, чтобы ответе осталась функция от $\\sigma(x)$\n", "\n", "$$\\frac{\\partial\\:\\sigma(x)}{\\partial x} = \\; ...$$\n", "\n", "Теперь возьмем производные выходов первого слоя по его параметрам\n", "\n", "$$\\frac{\\partial u_h(X_i)}{\\partial w_{1h}} = \\; ...$$\n", "\n", "$$\\frac{\\partial u_h(X_i)}{\\partial b_{1h}} = \\; ...$$\n", "\n", "Наконец, выпишем производные MSE по параметрам первого слоя. Так же как и раньше достаточно заполнить пропуски в записи ниже\n", "\n", "$$\\frac{\\partial\\:\\text{MSE}}{\\partial w_{1h}} = \\; \\sum_{i=1}^n \\frac{\\partial\\:\\text{MSE}}{\\partial ...} \\frac{\\partial ...}{\\partial w_{1h}}$$\n", "\n", "$$\\frac{\\partial\\:\\text{MSE}}{\\partial b_{1h}} = \\; \\sum_{i=1}^n \\frac{\\partial\\:\\text{MSE}}{\\partial ...} \\frac{\\partial ...}{\\partial b_{1h}}$$" ] }, { "cell_type": "markdown", "metadata": { "id": "T9TejlitW2Q2" }, "source": [ "**3.** Пусть обучающая выборка очень большая. Что нужно делать в таком случае? Запишите, как нужно поменять правило обновления параметров.\n", "\n", "..." ] }, { "cell_type": "markdown", "metadata": { "id": "a_EvDaB7W2Q2" }, "source": [ "**Вывод:**\n", "..." ] }, { "cell_type": "markdown", "metadata": { "id": "hwaX8xRXW2Q3" }, "source": [ "---\n", "### Задача 2.\n", "\n", "Напишите нейронную сеть из задачи 1 с помощью библиотеки `pytorch`, используя Sequential-стиль. Перед выполнением задачи рекомендуется посмотреть ноутбук с занятия. Функция активации реализована как `torch.nn.Sigmoid`.\n", "\n", "*Внимание.* Для выполнения задачи потребуется установить библиотеку `pytorch`. Альтернативный вариант — выполнение в Google Colab. Учитывайте, что при длительном бездействии Colab может сам завершить работу ядра." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "R03tSHFoW2Q4" }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": { "id": "t1_H2ptPW2Q3" }, "source": [ "Сгенерируем данные. Возьмите какую-либо нелинейную функцию $y(x)$." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "nIB7KwUMW2Q3" }, "outputs": [], "source": [ "sample_size = int(1e6)\n", "X = sps.norm.rvs(size=(sample_size, 1))\n", "y = ...\n", "\n", "assert y.shape == (sample_size,)" ] }, { "cell_type": "markdown", "metadata": { "id": "JLhEEGwOW2Q4" }, "source": [ "Обучите нейросеть на этих данных. Используйте код с занятия." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "TGAZcfvNW2Q4" }, "outputs": [], "source": [] }, { "cell_type": "markdown", "source": [ "Визуализируйте предсказания и посчитайте MSE на тестовой части данных." ], "metadata": { "id": "9MO9FNUDRFSJ" } }, { "cell_type": "code", "source": [], "metadata": { "id": "EfKQSiGVRIxl" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "zPoMmyGgW2Q3" }, "source": [ "**Вывод:**\n", "..." ] }, { "cell_type": "markdown", "metadata": { "id": "RRw1Pk9ZM4Wn" }, "source": [ "---\n", "### Сложная часть" ] }, { "cell_type": "markdown", "metadata": { "id": "EWHsMVWwW2Q2" }, "source": [ "---\n", "### Задача 3.\n", "\n", "Теперь реализуйте класс нейронной сети из задачи 1 в стиле scikit-learn, например, см. шаблон класса задачи 4 из задания 3. Предусмотрите возможность обучения по случайным батчам. При реализации можно использовать только библиотеку `numpy`." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "4tXV_LMcW2Q2" }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": { "id": "iLvOp4K8W2Q3" }, "source": [ "Обучите нейронную сеть на рассмотренных ранее данных, а также простую линейную регрессию. Для линейной регрессии стоит взять реализацию из `sklearn`. Сравните эту нейросеть, линейную регрессию и pytorch-сеть из задачи 2." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "Mitew_VaW2Q3" }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": { "id": "6NmNpWkPW2Q3" }, "source": [ "Визуализируйте предсказания данных моделей и посчитайте MSE на тестовой части данных." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "r2OEQK6JW2Q3" }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": { "id": "j-_6rkdkW2Q3" }, "source": [ "Повторите вычисления для другой нелинейной функции $y(x)$." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "1GJuV0dfW2Q3" }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": { "id": "CtVD-MTtW2Q4" }, "source": [ "**Вывод:**\n", "..." ] } ], "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.8.10" } }, "nbformat": 4, "nbformat_minor": 0 }