{
"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
}