{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "2PQW7OXEoWEZ" }, "source": [ "# Введение в анализ данных\n", "## Домашнее задание 3, сложная часть. Линейная и логистическая регрессии.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "aRt8VO2EoWEa" }, "source": [ "**Правила, прочитайте внимательно:**\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", "* Решения необходимо оформить в виде $\\LaTeX$ в markdown-ячейках. Иные способы (в т.ч. фотографии) не принимаются.\n", "* Если вы не знаете $\\LaTeX$, используйте ИИ-инструменты для оформления черновика решения. Примеры были показаны на лекции 2 по ИИ-инструментам.\n", "* **В решениях поясняйте, чем вы пользуетесь**, хотя бы кратко. \n", "* Решение, в котором есть только ответ, и отсутствуют вычисления, оценивается в 0 баллов.\n", "\n", "\n", "Важно!!! Правила заполнения ноутбука:\n", "* Запрещается удалять имеющиеся в ноутбуке ячейки, менять местами положения задач.\n", "* Сохраняйте естественный линейный порядок повествования в ноутбуке сверху-вниз.\n", "* Отвечайте на вопросы, а также добавляйте новые ячейки в предложенных местах, которые обозначены `<...>`.\n", "* В markdown-ячейка, содержащих описание задачи, находятся специальные отметки, которые запрещается модифицировать.\n", "* При нарушении данных правил работа может получить 0 баллов.\n", "\n", "\n", "**Баллы за задание:**\n", "\n", "Легкая часть (достаточно на \"хор\"):\n", "\n", "* Задачи 1-4: скачайте первый ноутбук с условием задания со страницы курса.\n", "\n", "Сложная часть (необходимо на \"отл\"):\n", "\n", "* Задача 5 — 80 баллов;\n", "* Задача 6 — 70 баллов;\n", "* Задача 7 — 50 баллов.\n", "\n", "Баллы учитываются в обязательной части курса и не влияют на оценку по факультативной части." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "TLUn-L0HoWEb" }, "outputs": [], "source": [ "# Bot check\n", "\n", "# HW_ID: fpmi_ad3_part2\n", "# Бот проверит этот ID и предупредит, если случайно сдать что-то не то.\n", "\n", "# Status: not final\n", "# Перед отправкой в финальном решении удали \"not\" в строчке выше.\n", "# Так бот проверит, что ты отправляешь финальную версию, а не промежуточную.\n", "# Никакие значения в этой ячейке не влияют на факт сдачи работы." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "LjG63iFWoWEb" }, "outputs": [], "source": [ "import numpy as np\n", "import pandas as pd\n", "import seaborn as sns\n", "from typing import Literal\n", "\n", "sns.set(style=\"whitegrid\", palette=\"Set2\")" ] }, { "cell_type": "markdown", "metadata": { "id": "4TDjFMbboWEc" }, "source": [ "При решении задания используйте `sklearn`. Пропишите сюда необходимые импорты" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "j19vAJp2oWEc" }, "outputs": [], "source": [ "from sklearn.base import BaseEstimator\n", "from sklearn.preprocessing import StandardScaler\n", "\n", "..." ] }, { "cell_type": "markdown", "metadata": { "id": "N5pKs47noWEc" }, "source": [ "---\n", "### Легкая часть\n", "\n", "Задачи 1-4: скачайте первый ноутбук с условием задания со страницы курса." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "### Сложная часть" ] }, { "cell_type": "markdown", "metadata": { "id": "9T8Ypp5frPWw" }, "source": [ "---\n", "### Задача 5." ] }, { "cell_type": "markdown", "metadata": { "id": "rHtqkeInrWZw" }, "source": [ "\n", "\n", "**1.** Реализуйте логистическую регрессию для двух вариантов поиска оценки параметров:\n", "* простой градиентный спуск;\n", "* стохастический градиентный спуск с `batch_size` элементами на каждой итерации.\n", "\n", "Останавливайте итерации при выполнении хотя бы одного из двух условий:\n", "* количество итераций превзошло число `max_iter`;\n", "* оптимизируемый функционал изменился за итерацию не более чем на `tol`.\n", "\n", "При выполнении каждой итерации с целью дальнейшего анализа сохраняйте текущее значение оптимизируемого функционала, а также затраченное время на итерацию. **При реализации класса запрещено пользоваться ИИ-инструментами.**\n", "\n", "*Замечания.*\n", "\n", "1. Для чистоты эксперимента время шага внутри цикла нужно замерять от конца предыдущего шага до конца текущего, а не от начала текущего шага. Время измеряйте с помощью `from time import time`.\n", "\n", "2. Иногда при подсчете сигмоиды и оптимизируемого функционала могут возникать вычислительные ошибки. Для их избежания существуют специальные трюки.\n", " * [How to Evaluate the Logistic Loss and not NaN trying](http://fa.bianp.net/blog/2019/evaluate_logistic/)\n", " * [Exp-normalize trick](https://timvieira.github.io/blog/post/2014/02/11/exp-normalize-trick/)
\n", "3. Трюки не обязательно реализовывать самостоятельно, можете воспользоваться функциями для них из `numpy` или `scipy`:\n", " * [`numpy.logaddexp`](https://numpy.org/doc/stable/reference/generated/numpy.logaddexp.html);\n", " * [`scipy.special.logsumexp`](https://docs.scipy.org/doc/scipy/reference/generated/scipy.special.logsumexp.html).\n", "4. Обратите внимание, что класс `LogisticRegression` — наследник класса `BaseEstimator`, это с легкостью позволит использовать наш класс в различных пайплайнах библиотеки `sklearn`.\n", "4. Следите за качеством кода, комментируйте логические этапы кода. Несоблюдение этого требования может привести к потере баллов.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# При реализации класса запрещено пользоваться ИИ-инструментами.\n", "\n", "\n", "class LogisticRegression(BaseEstimator):\n", " \"\"\"Модель логистической регрессии.\n", "\n", " Параметры:\n", " method (Literal['gd', 'sgd']): Метод оптимизации ('gd' - градиентный спуск, \n", " 'sgd' - стохастический градиентный спуск).\n", " learning_rate (float): Константа скорости обучения, на которую домножаем градиент при обучении\n", " tol (float): Допустимое изменение функционала между итерациями.\n", " max_iter (int): Максимальное число итераций.\n", " batch_size (int): Размер выборки для оценки градиента (используется только при 'sgd').\n", " fit_intercept (bool): Добавлять ли константу в признаки.\n", " save_history (bool): Сохранять ли историю обучения.\n", " \"\"\"\n", "\n", " def __init__(\n", " self,\n", " method: Literal[\"gd\", \"sgd\"] = \"gd\",\n", " learning_rate: float = 0.5,\n", " tol: float = 1e-3,\n", " max_iter: int = int(1e4),\n", " batch_size: int = 64,\n", " fit_intercept: bool = True,\n", " save_history: bool = True,\n", " ):\n", " \"\"\"Создает модель и инициализирует параметры.\"\"\"\n", " self.method = method\n", " self.learning_rate = learning_rate\n", " self.tol = tol\n", " self.max_iter = max_iter\n", " self.batch_size = batch_size\n", " self.fit_intercept = fit_intercept\n", " self.save_history = save_history\n", " self.history = [] # История обучения\n", "\n", " @staticmethod\n", " def _sigmoid(x: np.ndarray) -> np.ndarray:\n", " \"\"\"Вычисляет сигмоидную функцию.\"\"\"\n", " return 1 / (1 + np.exp(-x))\n", "\n", " def _add_intercept(self, X: np.ndarray) -> np.ndarray:\n", " \"\"\"Добавляет свободный коэффициент к матрице признаков.\n", "\n", " Параметры: X (np.ndarray): Исходная матрица признаков.\n", "\n", " Возвращает: np.ndarray: Матрица X с добавленным свободным\n", " коэффициентом.\n", " \"\"\"\n", " X_copy = np.full((X.shape[0], X.shape[1] + 1), fill_value=1)\n", " X_copy[:, :-1] = X\n", " return X_copy\n", "\n", " def fit(self, X: np.ndarray, Y: np.ndarray) -> \"LogisticRegression\":\n", " \"\"\"Обучает модель логистической регрессии.\n", "\n", " Также, в случае self.save_history=True, добавляет в self.history\n", " текущее значение оптимизируемого функционала и затраченное время.\n", "\n", " Параметры:\n", " X (np.ndarray): Матрица признаков.\n", " Y (np.ndarray): Вектор истинных меток.\n", "\n", " Возвращает:\n", " LogisticRegression: Обученная модель.\n", " \"\"\"\n", " if X.shape[0] != Y.shape[0]:\n", " raise ValueError(\"Количество строк в X и Y должно совпадать\")\n", "\n", " if self.fit_intercept:\n", " X_copy = self._add_intercept(X)\n", " else:\n", " X_copy = X.copy()\n", "\n", " ...\n", "\n", " self.coef_ = ... # Коэффициенты модели\n", " self.intercept_ = ... # Свободный коэффициент\n", " self.n_iter_ = ... # Число итераций\n", "\n", " return self\n", "\n", " def predict(self, X: np.ndarray) -> np.ndarray:\n", " \"\"\"Возвращает предсказанные классы.\n", "\n", " Параметры: X (np.ndarray): Матрица признаков.\n", "\n", " Возвращает: np.ndarray: Предсказанные классы.\n", " \"\"\"\n", " if self.fit_intercept:\n", " X_copy = self._add_intercept(X)\n", " else:\n", " X_copy = X.copy()\n", "\n", " if X_copy.shape[1] != self.coef_.shape[0]:\n", " raise ValueError(\"Число признаков в X не соответствует числу коэффициентов модели\")\n", "\n", " ...\n", " return predictions\n", "\n", " def predict_proba(self, X: np.ndarray) -> np.ndarray:\n", " \"\"\"Возвращает вероятности классов 0 и 1.\n", "\n", " Параметры: X (np.ndarray): Матрица признаков.\n", "\n", " Возвращает: np.ndarray: Матрица вероятностей классов (n_samples,\n", " 2).\n", " \"\"\"\n", " if self.fit_intercept:\n", " X_copy = self._add_intercept(X)\n", " else:\n", " X_copy = X.copy()\n", "\n", " if X_copy.shape[1] != self.coef_.shape[0]:\n", " raise ValueError(\"Число признаков в X не соответствует числу коэффициентов модели\")\n", "\n", " ...\n", " return prob_predictions" ] }, { "cell_type": "markdown", "metadata": { "id": "UdI6YePO7KD4" }, "source": [ "\n", "\n", "Рассмотрим датасет [Diabetes Health Indicators](https://www.kaggle.com/datasets/alexteboul/diabetes-health-indicators-dataset).\n", "\n", "**Для данного задания будем рассматривать версию датасета** `diabetes_binary_5050split_health_indicators_BRFSS2015.csv`\n", "\n", "\n", "Этот датасет содержит статистику здравоохранения и информацию об образе жизни, полученную в результате опросов вместе с меткой наличия/отсутствия диабета у участников. Среди признаков есть демографические данные, результаты лабораторных тестов и ответы на вопросы анкеты. Целевая переменная `Diabetes_binary` определяет статус пациента: есть ли у него диабет или предиабет (`1`), или он здоров (`0`).\n", "\n" ] }, { "cell_type": "markdown", "metadata": { "id": "uaTsecV5Sjkl" }, "source": [ "Рассмотрим некоторые признаки, представленные в датасете.\n", "\n", "**Показатели здоровья**\n", "\n", "- `HighBP`: Высокое кровяное давление (`1` = да, `0` = нет).\n", "\n", "- `HighChol`: Высокий уровень холестерина (`1` = да, `0` = нет).\n", "\n", "- `CholCheck`: Проверка уровня холестерина за последние 5 лет (`1` = да, `0` = нет).\n", "\n", "- `BMI`: Индекс массы тела (рассчитывается как вес (кг) / рост² (м²)).\n", "\n", "- `GenHlth`: Общая оценка здоровья (`1` = отличное, `2` = очень хорошее, ..., `5` = плохое).\n", "\n", "**Образ жизни**\n", "- `Smoker`: Статус курения (`1` = выкурил ≥100 сигарет за жизнь, `0` = нет).\n", "\n", "- `PhysActivity`: Физическая активность вне работы (`1` = да, `0` = нет).\n", "\n", "- `Fruits`: Регулярное употребление фруктов (`1` = не менее 1 раз в день, `0` = реже).\n", "\n", "**Доступ к медицине**\n", "- `AnyHealthcare`: Наличие медицинской страховки (`1` = да, `0` = нет).\n", "\n", "- `NoDocbcCost`: Отказ от визита к врачу из-за стоимости (`1` = да, `0` = нет).\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Скачайте файл и прочитайте его с помощью `pandas`." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "cEgtTimdrasr" }, "outputs": [], "source": [ "dataset = pd.read_csv(\"diabets_health_indicators.csv\")\n", "dataset.head()" ] }, { "cell_type": "markdown", "metadata": { "id": "ZIobQynHrlID" }, "source": [ "\n", "\n", "Разделите выборку на обучающую и тестовую и выполните преобразование категориальных признаков." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "x_dPlSZdrma4" }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": { "id": "mB_9uDuArn8M" }, "source": [ "Для интерпретации коэффициентов необходимо нормализовать данные. Воспользуемся для этого классом `StandardScaler` из библиотеки `sklearn`." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "6K8fHeL1roRf" }, "outputs": [], "source": [ "scaler = StandardScaler()\n", "..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "**2.** Обучите две модели логистической регрессии с помощью методов\n", "* простой градиентный спуск;\n", "* стохастический градиентный спуск." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": { "id": "_CokLOd9rp8_" }, "source": [ "Постройте график, на котором нанесите две кривые обучения, каждая из которых отображает зависимость оптимизируемого функционала от номера итерации метода. **Функционал должен быть одинаковый для всех моделей**. Нарисуйте также график зависимости этого функционала от времени работы метода. \n", "\n", "*Замечания:*\n", "* Все графики должны быть информативны, с подписанными осями и т.д..\n", "* Для чистоты эксперимента желательно не запускать в момент обучения другие задачи и провести обучение несколько раз, усреднив результаты." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Сделайте выводы. Что будет при обучении на датасете, если увеличить количество объектов, а число признаков оставить прежним?" ] }, { "cell_type": "markdown", "metadata": { "id": "eQAaaOUdruoc" }, "source": [ "..." ] }, { "cell_type": "markdown", "metadata": { "id": "CRk5SvBrrzGo" }, "source": [ "\n", "\n", "**3.** Исследуйте влияние размер шага (`learning_rate`) на качество модели для двух режимов обучения (простой и стохастический градиентный спуск). Для каждого размера шага получите качество модели при использовании простого и стохастического градиентного спуска. Сравните качество полученных моделей по метрике `accuracy`." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "pHHtsgd0r53G" }, "outputs": [], "source": [ "learning_rate_list = np.logspace(-5, 3, 8)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "Kgz4aaFRyJHe" }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Сделайте выводы" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "..." ] }, { "cell_type": "markdown", "metadata": { "id": "sHUqzb4cr1zB" }, "source": [ "Постройте кривые обучения для различных `learning_rate`. Не обязательно рассматривать все `learning_rate`, так как их слишком много, и график будет нагроможден. Возьмите около половины из них." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "Jj4MFLcRr5a2" }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Какой `learning_rate` стоит выбирать в зависимости от способа обучения модели? Чем плохи маленькие и большие `learning_rate`?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "..." ] }, { "cell_type": "markdown", "metadata": { "id": "5ns_R7NEr7XA" }, "source": [ "\n", "\n", "**4.** Рассмотрите наилучшую модель с предыдущего шага. Визуализируйте значения полученных коэффициентов." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "NCtU2t2Ur-zX" }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Как можно проинтерпретировать полученные результаты относительно решаемой задачи?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "..." ] }, { "cell_type": "markdown", "metadata": { "id": "10PauxmiV3T5" }, "source": [ "\n", "\n", "**5.** Сравните данную модель с бейзлайном, который в качестве предсказания выдает самый частый класс на обучающей выборке." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "25xDPq1GWTb3" }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Насколько хорошее получилось качество обученной модели?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "..." ] }, { "cell_type": "markdown", "metadata": { "id": "R3nPAObnr_XI" }, "source": [ "\n", "\n", "**6.** В исходной выборке оставьте два вещественных признака, которые имеют наибольшее влияние на предсказание в предыдущем пункте. Обучите на них модель на 10000 итерациях. Визуализируйте предсказание класса $1$ для нескольких промежуточных итераций." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "UGpyX1b-JMxW" }, "outputs": [], "source": [ "iters = [10, 20, 500, 1000, 5000, 10000]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "TNZAgIOGOSzW" }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": { "id": "GgV3-Y65sFQs" }, "source": [ "\n", "\n", "**Вывод:**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "---\n", "### Задача 6.\n", "\n", "В этой задаче вам предлагается реализовать регрессию Хьюбера, а также применить ее к данным с выбросами. Для начала реализуйте класс по шаблону снизу. Обратите внимание, что класс `HuberRegression` — наследник класса `BaseEstimator`, это с легкостью позволит использовать наш класс в различных пайплайнах библиотеки `sklearn`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**1.** Задача оптимизации для регрессии Хьюбера выглядит следующим образом:\n", "$$\\sum_{i=1}^n R\\left(Y_i - x_i^T\\theta\\right) \\rightarrow \\min_\\theta,$$\n", "где $R(x)$ — функция потерь Хьюбера, определяемая как\n", "$$R(x) = \\frac{x^2}{2} I\\left\\{|x| < c\\right\\} + c \\left(|x| - \\frac{c}{2}\\right)I\\left\\{|x| > c\\right\\}.$$\n", "\n", "Выпишите формулы для градиентного и стохастического градиентного спусков. В чем польза такой функции потерь?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "**2.** Реализуем теперь класс. **При реализации класса запрещено пользоваться ИИ-инструментами.**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# При реализации класса запрещено пользоваться ИИ-инструментами.\n", "\n", "\n", "class HuberRegression(BaseEstimator):\n", " \"\"\"Класс, реализующий линейную регрессию с функцией потерь Хьюбера.\"\"\"\n", "\n", " def __init__(self, c: float = 1.0, fit_intercept: bool = True, max_iter: int = 1000) -> None:\n", " \"\"\"Инициализирует модель.\n", "\n", " Параметры: c (float): Константа из функции потерь Хьюбера.\n", " fit_intercept (bool): Добавлять ли константный признак. max_iter\n", " (int): Максимальное число итераций оптимизации.\n", " \"\"\"\n", " self.c = c\n", " self.fit_intercept = fit_intercept\n", " self.max_iter = max_iter\n", "\n", " def fit(self, X: np.ndarray, y: np.ndarray) -> \"HuberRegression\":\n", " \"\"\"Обучает модель.\n", "\n", " Параметры:\n", " X (np.ndarray): Матрица признаков.\n", " y (np.ndarray): Вектор целевой переменной.\n", "\n", " Возвращает:\n", " HuberRegression: Обученная модель.\n", " \"\"\"\n", " if X.shape[0] != y.shape[0]:\n", " raise ValueError(\"Количество строк в X и y должно совпадать\")\n", "\n", " ...\n", "\n", " self.coef_ = ... # Коэффициенты модели\n", " self.intercept_ = ... # Свободный коэффициент\n", " self.n_iter_ = ... # Число итераций\n", "\n", " return self\n", "\n", " def predict(self, X: np.ndarray) -> np.ndarray:\n", " \"\"\"Делает предсказание на новых данных.\n", "\n", " Параметры: X (np.ndarray): Матрица признаков.\n", "\n", " Возвращает: np.ndarray: Вектор предсказанных значений.\n", " \"\"\"\n", "\n", " if X_copy.shape[1] != self.coef_.shape[0]:\n", " raise ValueError(\"Число признаков в X не соответствует числу коэффициентов модели\")\n", "\n", " ...\n", " return pred" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "**3.** Загрузите данные из файлов `train.csv`, `test.csv`. Не забудьте, что всю аналитику, а также процесс обучения и подбор гиперпараметров необходимо выполнять на обучающей выборке." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Посмотрите на зависимость целевой переменной от каждого признака." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Что можно сказать о наличии возможных выбросов? Какое влияние они могут оказать? " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "**4.** Обучите простую линейную регрессию и посчитайте качество на тестовой выборке по метрике [MSE](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.mean_squared_error.html#sklearn.metrics.mean_squared_error)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Что можно сказать о качестве нашей модели?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**5.** Теперь обучите линейную регресcию Хьюбера и посчитайте качество на тестовой части по метрикe MSE." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Что изменилось?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "**6.** Для обучающей выборки постройте два графика (по графику на каждую модель), на которых изобразите зависимость истинного и предсказанного значения таргета от каждого признака." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Что можно заметить на этих графиках?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "**7.** Обучите регрессию Хьюбера на данных из задачи 2 и сравните качество модели с простой линейной регрессией, которую вы построили в задаче 2." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Вывод:**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "---\n", "### Задача 7.\n", "\n", "\n", "Рассмотрим модель одномерной регрессии $y(x) = \\theta x$, где $x \\in \\mathbb{R}$ — одномерный признак, $y \\in \\mathbb{R}$ — целевой признак, $\\theta \\in \\mathbb{R}$ — неизвестный параметр. Имеется выборка размера $n$, полученная по правилу\n", "\t$$Y_i = \\theta x_i + \\varepsilon_i,\\ \\ \\ i=1,...,n,$$\n", "где $\\varepsilon_i$ — случайная ошибка измерений.\n", "\n", "Предложите точный алгоритм поиска оценки параметра $\\theta$ методом наименьших модулей, то есть $$\\sum_{i=1}^n \\left|Y_i - \\theta x_i\\right| \\to \\min_\\theta,$$ работающий за время $O(n \\log n)$. Приведите его описание и теоретическое обоснование. Реализация в коде не требуется." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Решение:**\n", "\n", "..." ] } ], "metadata": { "colab": { "provenance": [], "toc_visible": true }, "hide_input": false, "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.12.3" } }, "nbformat": 4, "nbformat_minor": 1 }