{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "i4MGAGZSqtd5"
},
"source": [
"# Phystech@DataScience\n",
"## Домашнее задание 2\n",
"\n",
"**Правила, прочитайте внимательно:**\n",
"\n",
"* Выполненную работу нужно отправить телеграм-боту `@thetahat_ds25_bot`. Для начала работы с ботом каждый раз отправляйте `/start`. Дождитесь подтверждения от бота, что он принял файл. Если подтверждения нет, то что-то не так. **Работы, присланные иным способом, не принимаются.**\n",
"* Дедлайн см. в боте. После дедлайна работы не принимаются кроме случаев наличия уважительной причины.\n",
"* Прислать нужно **ноутбук в формате `ipynb`**. Если вы строите интерактивные графики, их стоит прислать в формате html.\n",
"* Следите за размером файлов. **Бот не может принимать файлы весом более 20 Мб.** Если файл получается больше, заранее разделите его на несколько.\n",
"* Выполнять задание необходимо полностью самостоятельно. **При обнаружении списывания всем участникам списывания дается штраф -2 балла к итоговой оценке за семестр.**\n",
"* Решения, размещенные на каких-либо интернет-ресурсах, не принимаются. Кроме того, публикация решения в открытом доступе может быть приравнена к предоставлении возможности списать.\n",
"* Обратите внимание на правила использования ИИ-инструментов при решении домашнего задания.\n",
"* **Код из рассказанных на занятиях ноутбуков** можно использовать без ограничений.\n",
"* Для выполнения задания используйте этот ноутбук в качестве основы, ничего не удаляя из него. Можно добавлять необходимое количество ячеек.\n",
"* Комментарии к решению пишите в markdown-ячейках.\n",
"* Выполнение задания (ход решения, выводы и пр.) должно быть осуществлено на русском языке.\n",
"* Решение проверяется системой ИИ-проверки
**ThetaGrader**. Результат проверки валидируется и исправляется человеком, после чего комментарии отправляются студентам.\n",
"* Если код будет не понятен проверяющему, оценка может быть снижена.\n",
"* Никакой код из данного задания при проверке запускаться не будет. *Если код студента не выполнен, недописан и т.д., то он не оценивается.*\n",
"\n",
"Важно!!! Правила заполнения ноутбука:\n",
"* Запрещается удалять имеющиеся в ноутбуке ячейки, менять местами положения задач.\n",
"* Сохраняйте естественный линейный порядок повествования в ноутбуке сверху-вниз.\n",
"* Отвечайте на вопросы, а также добавляйте новые ячейки в предложенных местах, которые обозначены `<...>`.\n",
"* В markdown-ячейка, содержащих описание задачи, находятся специальные отметки, которые запрещается модифицировать.\n",
"* При нарушении данных правил работа может получить 0 баллов.\n",
"\n",
"\n",
"**Перед выполнением задания посмотрите презентацию по выполнению и оформлению домашних заданий с занятия 2.**\n",
"\n",
"\n",
"**Баллы за задание:**\n",
"\n",
"\n",
"* Задача 1 — 50 баллов\n",
"* Задача 2 — 50 баллов\n",
"* Задача 3 — 30 баллов\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"-----"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "WmDDSxlDeHco"
},
"outputs": [],
"source": [
"# Bot check\n",
"\n",
"# HW_ID: phds_hw2\n",
"# Бот проверит этот ID и предупредит, если случайно сдать что-то не то\n",
"\n",
"# Status: not final\n",
"# Перед отправкой в финальном решении удали \"not\" в строчке выше\n",
"# Так бот проверит, что ты отправляешь финальную версию, а не промежуточную"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "nab2ZrRjqtd7"
},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"import seaborn as sns\n",
"\n",
"from sklearn.model_selection import train_test_split\n",
"from sklearn.metrics import accuracy_score, mean_squared_error, mean_absolute_error, mean_absolute_percentage_error, r2_score\n",
"from sklearn.linear_model import LinearRegression\n",
"from sklearn.linear_model import LogisticRegression\n",
"from sklearn.preprocessing import OneHotEncoder\n",
"from sklearn.preprocessing import StandardScaler\n",
"\n",
"\n",
"import warnings\n",
"warnings.filterwarnings(\"ignore\")\n",
"import seaborn as sns\n",
"sns.set_theme(palette='Set2')"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "LWEjjNYqqtd8"
},
"source": [
"### Легкая часть\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "GP6ZcRKLY3x7"
},
"source": [
"---\n",
"### Задача 1\n",
"\n",
"\n",
"#### 1. Загрузка данных и предобработка"
]
},
{
"cell_type": "markdown",
"metadata": {
"ai_eval_tool": {
"snippet_hash": "9c620b5e71dfb8e728703d73d13c9bc3",
"snippet_label": "start"
},
"id": "092qpasSqtd8"
},
"source": [
"\n",
"\n",
"\n",
"#### **Профиль биология**\n",
"\n",
"Загрузите [данные](https://www.kaggle.com/datasets/marshuu/breast-cancer) по предсказанию рака груди.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "kM9ctbRHqtd8"
},
"outputs": [],
"source": [
"data = pd.read_csv('breast_cancer_disbalances.csv')\n",
"data.head()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "5WUpYx_dqtd9"
},
"source": [
"Проверьте, имеются ли в ваших данных пропуски. Если да, то удалите их.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "-3kv7xUiPprV"
},
"outputs": [],
"source": [
"..."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "EjG4E_KCqtd-"
},
"source": [
"Библиотека `pandas` позволяет строить графики `matplotlib` для своих объектов `DataFrame` ([подробнее](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.plot.html)). Посмотрим, как распределены значения признака `Bare Nuclei` для разных классов:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "0s0RAiLsqtd-"
},
"outputs": [],
"source": [
"fig, axs = plt.subplots(1, 2, figsize=(10, 5))\n",
"data.groupby(\"Class\")['Bare Nuclei'].hist(ax=axs[0], alpha=0.5)\n",
"data.groupby(\"Class\")['Bare Nuclei'].plot(kind='kde', ax=axs[1])\n",
"axs[0].set_title('Гистограмма для Bare Nuclei', fontsize=20)\n",
"axs[1].set_title('KDE для Bare Nuclei', fontsize=20);"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "d3e4EfWJqtd-"
},
"source": [
"Чем отличаются способы построения ЯОП и гистограммы? Какую информацию о наших данных можно извлечь из каждого графика?"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "61OjcvsXqtd-"
},
"source": [
"**Ответ:**\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "A6onkGOGqtd_"
},
"source": [
"Постройте гистограммы и ядерные оценки плотности для всех признаков из датасета отдельно для каждого класса. `Class` — целевая переменная. Можно это сделать, опираясь на код выше, а можно воспользоваться параметром `hue` у функции [`sns.histplot`](https://seaborn.pydata.org/generated/seaborn.histplot.html) или другим методом, который вам нравится. Не забывайте подписывать, к чему относится каждый график."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "_CLHMYqvU9Si"
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "3u2Ircukqtd_"
},
"source": [
"Какие выводы вы можете сделать из полученных графиков?"
]
},
{
"cell_type": "markdown",
"metadata": {
"ai_eval_tool": {
"snippet_hash": "9c620b5e71dfb8e728703d73d13c9bc3",
"snippet_label": "end"
},
"id": "DUjghYGeqtd_"
},
"source": [
"**Вывод:** ..."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "PbB9APbKP8Ps"
},
"source": [
"\n",
"\n",
"**Это не конец задачи! Переходите к пункту 2!**"
]
},
{
"cell_type": "markdown",
"metadata": {
"ai_eval_tool": {
"snippet_hash": "ca9029c0d916da0e69572b206fa25145",
"snippet_label": "start"
},
"id": "VEtE7q4Dqtd_"
},
"source": [
"\n",
"\n",
"#### **Профиль физика**\n",
"\n",
"Загрузите данные по бинарной классификации астероидов в зависимости от различных параметров с сайта.\n",
"\n",
"Вашей целевой переменной будет являться столбец `pha`. Более подробно ознакомить с датасетом вы можете также [здесь](https://www.kaggle.com/datasets/sakhawat18/asteroid-dataset/data). Можно заметить, что наш датасет сильно меньше по размерам, чем оригинал. Это сделано намеренно."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "iT1Wl3F3qtd_"
},
"outputs": [],
"source": [
"data = pd.read_csv('asteroid_cut.csv')\n",
"data.info()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Ohh2MuiHqtd_"
},
"source": [
"Библиотека `pandas` позволяет строить графики `matplotlib` для своих объектов `DataFrame` ([подробнее](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.plot.html)). Посмотрим, как распределены значения признака `rms` для разных классов:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "mJPdRYQwqteA"
},
"outputs": [],
"source": [
"fig, axs = plt.subplots(1, 2, figsize=(10, 5))\n",
"data.groupby(\"pha\")['rms'].hist(ax=axs[0], density=True)\n",
"data.groupby(\"pha\")['rms'].plot(kind='kde', ax=axs[1])\n",
"axs[0].set_title('Гистограмма для H', fontsize=20)\n",
"axs[1].set_title('KDE для H', fontsize=20);"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "QXwE_hurqteA"
},
"source": [
"Чем отличаются способы построения ЯОП и гистограммы? Какую информацию о наших данных можно извлечь из каждого графика?"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "hZlzLtTSqteA"
},
"source": [
"**Ответ:** ...\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "0B27vJKoqteA"
},
"source": [
"Постройте гистограммы и ядерные оценки плотности для указанных ниже признаков отдельно для каждого класса. `pha` — целевая переменная. Можно это сделать, опираясь на код выше, а можно воспользоваться параметром `hue` у функции [`sns.histplot`](https://seaborn.pydata.org/generated/seaborn.histplot.html) или другим методом, который вам нравится. Не забывайте подписывать, к чему относится каждый график.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "_wZcvPyWqteA"
},
"outputs": [],
"source": [
"features = ['epoch', 'ma', 'tp', 'rms']\n",
"\n",
"..."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "3zcMmW36qteA"
},
"source": [
"Какие выводы вы можете сделать из полученный графиков?"
]
},
{
"cell_type": "markdown",
"metadata": {
"ai_eval_tool": {
"snippet_hash": "ca9029c0d916da0e69572b206fa25145",
"snippet_label": "end"
},
"id": "WZ4kcZIiqteA"
},
"source": [
"**Вывод:** ..."
]
},
{
"cell_type": "markdown",
"metadata": {
"ai_eval_tool": {
"snippet_hash": "30a722e795d939966c91ff0a92cf86eb",
"snippet_label": "start"
},
"id": "w_ovzRYAqteA"
},
"source": [
"\n",
"\n",
"#### 2. Обучение модели\n",
"\n",
"Продолжайте использовать выбранные вами данные."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "GxLTI2LQqteB"
},
"source": [
"Создайте массив признаков и массив таргета. Разбейте ваши данные на обучающую и тестовую выборки в отношении 7:3."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "7ST_FJgVqteB"
},
"outputs": [],
"source": [
"X = ...\n",
"y = ...\n",
"X_train, X_test, y_train, y_test = ..."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "itjGzFWCqteB"
},
"source": [
"Примените стандартизацию к обучающей и тестовой выборкам, используя класс `StandardScaler`, натренированный на обучающей выборке."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "Rpi7SEbpqteB"
},
"outputs": [],
"source": [
"..."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "vFG3h0zUqteB"
},
"source": [
"Объясните, что делает `StanderdScaler` и почему нельзя его нельзя обучать на тестовой выборке?"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "naP590nQqteB"
},
"source": [
"**Ответ:**\n",
"\n",
"..."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "CakSs7aEqteB"
},
"source": [
"Обучите модель логистической регрессии."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "TO6JT22zqteB"
},
"outputs": [],
"source": [
"..."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "vaJl9Yr8qteC"
},
"source": [
"Сделайте предсказание для тестовой выборки и оцените качества полученного предсказания, используя метрику `accuracy_score`\n",
"\n",
"Если названия ваших классов отличаются от 0 и 1, то надо использовать `pos_label`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ai_eval_tool": {
"snippet_hash": "30a722e795d939966c91ff0a92cf86eb",
"snippet_label": "end"
},
"id": "lU4rByMxqteC"
},
"outputs": [],
"source": [
"..."
]
},
{
"cell_type": "markdown",
"metadata": {
"ai_eval_tool": {
"snippet_hash": "720b0d3dae956d90fb3ea500b9479d13",
"snippet_label": "start"
},
"id": "fpzWgAZMqteC"
},
"source": [
"\n",
"\n",
"Можем ли порадоваться таким результатам? Вернемся к гистограммам и сделаем вывод, почему метрика оказалась такой большой.\n",
"\n",
"Давайте посмотрим на распределение наших данных по целевой переменной по всему датасету, тренировочной и тестовой выборках."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "51rxojIKqteC"
},
"outputs": [],
"source": [
"original = <...>.value_counts() # Колонка таргета из изначального датасета\n",
"train = <...>.value_counts() # Колонка таргета из тренировочного датасета\n",
"test = <...>.value_counts() # Колонка таргета из тестового датасета\n",
"\n",
"fig, axes = plt.subplots(1, 3, figsize=(15, 5))\n",
"sns.barplot(x=original.index, y=original, ax=axes[0], palette=['blue'])\n",
"axes[0].set_title('Распределение классов в data')\n",
"axes[0].set_ylabel('Количество')\n",
"\n",
"sns.barplot(x=train.index, y=train, ax=axes[1], palette=['green'])\n",
"axes[1].set_title('Распределение классов в train')\n",
"\n",
"sns.barplot(x=test.index, y=test, ax=axes[2], palette=['orange'])\n",
"axes[2].set_title('Распределение классов в test')\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "OadSCTKRqteD"
},
"source": [
"Видно, что в данных есть сильный перекос — классы представлены неравномерно. Как и почему это может повлиять на наши результаты?"
]
},
{
"cell_type": "markdown",
"metadata": {
"ai_eval_tool": {
"snippet_hash": "720b0d3dae956d90fb3ea500b9479d13",
"snippet_label": "end"
},
"id": "1ERKEkM_qteD"
},
"source": [
"**Ответ:** ..."
]
},
{
"cell_type": "markdown",
"metadata": {
"ai_eval_tool": {
"snippet_hash": "27d23fce3fb2cb6960814deb0a13d80b",
"snippet_label": "start"
},
"id": "zE_mWlc6qteD"
},
"source": [
"\n",
"\n",
"Есть много способов борьбы с этим. Можно искусственно сгенерировать данные нужного класса или урезать другой класс. Однако сегодня мы воспользуемся ***взвешенной*** логистической регрессией. Суть метода в том, что мы вручную поставим веса для классов, исходя из их предполагаемой природы: важность разных классов, цена ошибки в реальной жизни(например, что лучше, предсказать наличие рака, если он есть или нет?) и представленность данных.\n",
"\n",
"Кросс-энтропия для взвешенной логистической регресси будет записана как:\n",
"\n",
"$$\n",
"F(\\theta) = \\sum_{i=1}^{n} H(y_i, \\widehat{y}_i) = -\\sum_{i=1}^{n} w_{y_i} \\left[ y_i \\log(\\widehat{y}_i) + (1-y_i) \\log(1-\\widehat{y}_i) \\right]\n",
"$$\n",
"\n",
"где:\n",
"\n",
"- $ y_i $ - истинный класс для образца $i$\n",
"- $ \\widehat{y}_i = \\sigma(\\theta^Tx_i)$ - предсказанный класс для образца $i$\n",
"- $ w_{y_i} $ - вес класса\n",
"\n",
"\n",
"\n",
"Давайте применим этот подход на практике. Воспользуемся параметром `class_weight`. Для начала определим количество примеров каждого класса в обучающей выборке и вычислим их соотношение."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "TkXw6-AZo7kI"
},
"outputs": [],
"source": [
"..."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "_Fwpza1YpmE9"
},
"source": [
"Применим рассчитанное соотношение классов в качестве весов:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "witXjZQnqteD"
},
"outputs": [],
"source": [
"threshold = ...\n",
"class_weights = {<класс_1>: threshold, <класс_2>: 1 - threshold}\n",
"# если использовать class_weights = 'balanced' модель сама подсчитает веса\n",
"\n",
"weighted_model = LogisticRegression(class_weight=class_weights, random_state=0)\n",
"..."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "z7jLyCj7SFUy"
},
"source": [
"Посчитаем метрику `accuracy_score`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "K07hvv4wR7ii"
},
"outputs": [],
"source": [
"accuracy = ...\n",
"print(f\"accuracy = {accuracy}\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "QUa7wWjOqteE"
},
"source": [
"Как изменилось качество нашей модели?\n",
"\n",
"Сделайте общий вывод по задаче."
]
},
{
"cell_type": "markdown",
"metadata": {
"ai_eval_tool": {
"snippet_hash": "27d23fce3fb2cb6960814deb0a13d80b",
"snippet_label": "end"
},
"id": "KxPjxdMgqteE"
},
"source": [
"**Вывод:**"
]
},
{
"cell_type": "markdown",
"metadata": {
"ai_eval_tool": {
"snippet_hash": "d47d648e3e531cd82a72ebefc5133104",
"snippet_label": "start"
},
"id": "UPcUqqJHYgGu"
},
"source": [
"\n",
"\n",
"---\n",
"### Задача 2\n",
"\n",
"\n",
"#### Датасет penguins\n",
"В первой части задания мы познакомимся с новым для нас датасетом"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "KzwbvpTaYGDE"
},
"outputs": [],
"source": [
"penguins = pd.read_csv('penguins.csv')\n",
"penguins.head()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Tc1kVcbdZbPp"
},
"source": [
"> ⚠️ **Warning:** Лучше не нажимать на пингвинов\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "gdyoXgYKZbM8"
},
"source": [
"Здесь содержатся данные о морфололгии пингвинов трех различных видов: Adelie, Chinstrap, и Gentoo."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "-_NVK0gdb5Bl"
},
"source": [
"
"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "VqCf9EZgb4_I"
},
"source": [
"Оставшеися колонки: `bill_length_mm`, `bill_depth_mm`, `flipper_length_mm`, `body_mass_g` описывают морфологию каждого пингвина."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "tq3DaCSRb48o"
},
"source": [
"
"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "z9c3uyNRb46T"
},
"source": [
"Как мы видим, в данном датасете присутствуют категориальные переменные: `species`, `island` и `sex`, которые не могут быть оценены моделью линейной регресии. Закодируйте их: к переменным, где присутствует более трёх категорий, примените преобразование `OneHotEncoder`. Обратите внимание на аргумент [`drop`](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "vg-v3uqvcMi1"
},
"outputs": [],
"source": [
"cat_features = [...]\n",
"\n",
"onehotencoder = ...\n",
"encoded = pd.DataFrame(onehotencoder.fit_transform(...), dtype=int)\n",
"\n",
"penguins_encoded = penguins.drop(cat_features, axis=1).join(...)\n",
"penguins_encoded = penguins_encoded.rename(str, axis=\"columns\")\n",
"\n",
"penguins_encoded.head()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "vS5U7q37cPlB"
},
"source": [
"Выберем в качестве таргета вес пингвинов (`body_mass_g`), и разделим нашу выборку на тренировочную и тестовую:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ai_eval_tool": {
"snippet_hash": "d47d648e3e531cd82a72ebefc5133104",
"snippet_label": "end"
},
"id": "wT-CUn10cPaT"
},
"outputs": [],
"source": [
"X = penguins_encoded.drop('body_mass_g', axis=1)\n",
"y = penguins_encoded['body_mass_g']\n",
"X_train, X_test, y_train, y_test = ..."
]
},
{
"cell_type": "markdown",
"metadata": {
"ai_eval_tool": {
"snippet_hash": "609f7e6bc983c66d5814592a5352a7e0",
"snippet_label": "start"
},
"id": "a1wOR3nVcS-c"
},
"source": [
"\n",
"\n",
"Реализуйте линейную регрессию самостоятельно, используя формулы с лекции.\n",
"Вам нужно только заполнить прочерки в методах `fit` и `predict`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "qBeb_uF9cMfm"
},
"outputs": [],
"source": [
"class MyLinearRegression:\n",
" \"\"\"\n",
" Класс, реализующий линейную регрессию c помощью МНК.\n",
" \"\"\"\n",
"\n",
" def __init__(self):\n",
" pass\n",
"\n",
" def fit(self, X, Y):\n",
" \"\"\"\n",
" Функция обучения модели.\n",
"\n",
" Предполагается модель Y = X * theta + epsilon.\n",
" где X --- регрессор (матрица размера n x d),\n",
" Y --- отклик (матрица размера n x 1),\n",
" epsilon-ы имеют нормальное распределение\n",
"\n",
" Обратите внимание, здесь нет intercept_\n",
" \"\"\"\n",
"\n",
" self.n, self.d = X.shape[0], X.shape[1]\n",
"\n",
" self.theta = МНК-оценка\n",
"\n",
" return ...\n",
"\n",
"\n",
" def predict(self, X):\n",
" \"\"\"\n",
" Возвращает предсказание отклика на новых объектах X.\n",
"\n",
" X --- матрица объектов размера n x d\n",
" \"\"\"\n",
"\n",
" y_pred = ...\n",
" return ..."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "sEYv4FQBcYDY"
},
"source": [
"Обучите вашу модель на датасете о пингвинах **без** добавления свободного члена.\n",
"Распечатайте коэффициенты и сравните их с коэффициентами модели из `sklearn`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "tvgV1eIYcMYq"
},
"outputs": [],
"source": [
"MyModel = ...\n",
"\n",
"..."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "kYBcoSaP1HX-"
},
"source": [
"Как соотносятся коэффициенты вашей модели и реализации из `sklearn`?\n",
"\n",
"**Ответ:** ..."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "DfdsFy-Xb44H"
},
"source": [
"Теперь обучите собственную модель **c** добавлением свободного члена."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ai_eval_tool": {
"snippet_hash": "609f7e6bc983c66d5814592a5352a7e0",
"snippet_label": "end"
},
"id": "ne1RsKoQYEoq"
},
"outputs": [],
"source": [
"..."
]
},
{
"cell_type": "markdown",
"metadata": {
"ai_eval_tool": {
"snippet_hash": "cf209df06ad3ab80411542037954e29d",
"snippet_label": "start"
},
"id": "VYp3PROLchG3"
},
"source": [
"\n",
"\n",
"Помимо рассмотренных на семенаре метрик, довольно часто рассматривают [коэфициент детерминации](https://en.wikipedia.org/wiki/Coefficient_of_determination) $R^2$, который может быть более интуитивным."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "GeFRusKLchz3"
},
"source": [
"Определяется он так:\n",
"$$\n",
" R^2 = 1 - \\frac{SS_{reg}}{SS_{tot}},\n",
"$$\n",
"где $SS_{res} = \\sum\\limits_{i=1}^n (y_i - f_i)^2$ отражает точность нашей модели, \n",
"a $SS_{tot} = \\sum\\limits_{i=1}^n (y_i - \\overline{y})^2$ отражает дисперсию исходных данных. \n",
"Соответсвенно чем результат ближе к еденице тем более точная у нас модель и тем лучше она предсказывает. Отрицательный же результат можем получить в случае, если наша модель предсказывает хуже, чем предсказание средним."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "GZWOkqincnJl"
},
"source": [
"В `sklearn` есть готовая [реализация](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.r2_score.html) под названием `r2_score`"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "hnP7xCRVcp81"
},
"source": [
"Сравните качество моделей со свободным членом и без него на тестовой выборке, используя метрики RMSE, MAE, MAPE и $R^2$."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "qiJYLO8Tcpch"
},
"outputs": [],
"source": [
"..."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "MEHQ-Br3dL3a"
},
"source": [
"**Сделайте выводы**"
]
},
{
"cell_type": "markdown",
"metadata": {
"ai_eval_tool": {
"snippet_hash": "cf209df06ad3ab80411542037954e29d",
"snippet_label": "end"
},
"id": "Se26zaCadLvR"
},
"source": [
"**Вывод:** ..."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "8mdmZ1EWoKSt"
},
"source": [
"\n",
"\n",
"---\n",
"### Задача 3\n",
"\n",
"Во взвешенном методе наименьших квадратов каждому наблюдению задается некоторый известный вес $w_i$. Задача имеет вид: $$\\sum\\limits_{i=1}^n w_i\\left(Y_i - x_i^T \\theta\\right)^2 \\to \\min\\limits_\\theta$$ Найдите решение задачи в матричном виде.\n"
]
}
],
"metadata": {
"colab": {
"provenance": [],
"toc_visible": true
},
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.9.19"
}
},
"nbformat": 4,
"nbformat_minor": 0
}