Физтех.Статистика
Скачать ipynb
Phystech@DataScience¶
Домашнее задание 11¶
Правила, прочитайте внимательно:
- Выполненную работу нужно отправить телеграм-боту
@miptstats_pds_bot
. Для начала работы с ботом каждый раз отправляйте/start
. Работы, присланные иным способом, не принимаются. - Дедлайн см. в боте. После дедлайна работы не принимаются кроме случаев наличия уважительной причины.
- Прислать нужно ноутбук в формате
ipynb
. - Выполнять задание необходимо полностью самостоятельно. При обнаружении списывания все участники списывания будут сдавать устный зачет.
- Решения, размещенные на каких-либо интернет-ресурсах, не принимаются. Кроме того, публикация решения в открытом доступе может быть приравнена к предоставлении возможности списать.
- Для выполнения задания используйте этот ноутбук в качестве основы, ничего не удаляя из него. Можно добавлять необходимое количество ячеек.
- Комментарии к решению пишите в markdown-ячейках.
- Выполнение задания (ход решения, выводы и пр.) должно быть осуществлено на русском языке.
- Если код будет не понятен проверяющему, оценка может быть снижена.
- Никакой код из данного задания при проверке запускаться не будет. Если код студента не выполнен, недописан и т.д., то он не оценивается.
- Код из рассказанных на занятиях ноутбуков можно использовать без ограничений.
Правила оформления теоретических задач:
- Решения необходимо прислать одним из следующих способов:
- фотографией в правильной ориентации, где все четко видно, а почерк разборчив,
- отправив ее как файл боту вместе с ноутбуком или
- вставив ее в ноутбук посредством
Edit -> Insert Image
(фото, вставленные ссылкой, не принимаются);
- в виде $\LaTeX$ в markdown-ячейках.
- фотографией в правильной ориентации, где все четко видно, а почерк разборчив,
- Решения не проверяются, если какое-то требование не выполнено. Особенно внимательно все проверьте в случае выбора второго пункта (вставки фото в ноутбук). Неправильно вставленные фотографии могут не передаться при отправке. Для проверки попробуйте переместить
ipynb
в другую папку и открыть его там. - В решениях поясняйте, чем вы пользуетесь, хотя бы кратко. Например, если пользуетесь независимостью, то достаточно подписи вида "X и Y незав."
- Решение, в котором есть только ответ, и отсутствуют вычисления, оценивается в 0 баллов.
Баллы за задание:
Легкая часть (достаточно на "хор"):
- Задача 1 — 20 баллов
- Задача 2 — 40 баллов
Cложная часть (необходимо на "отл"):
- Задача 3 — 60 баллов
- Задача 4 — 30 баллов
# Bot check
# HW_ID: phds_hw11
# Бот проверит этот ID и предупредит, если случайно сдать что-то не то.
# Status: not final
# Перед отправкой в финальном решении удали "not" в строчке выше.
# Так бот проверит, что ты отправляешь финальную версию, а не промежуточную.
# Никакие значения в этой ячейке не влияют на факт сдачи работы.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(style='whitegrid', font_scale=1.3, palette='Set2')
При решении задания используйте sklearn
. Пропишите сюда необходимые импорты
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import os
from sklearn.ensemble import RandomForestClassifier, RandomForestRegressor
from sklearn.tree import DecisionTreeClassifier, DecisionTreeRegressor
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split, GridSearchCV
# возможно придется что-то добавить)
Легкая часть¶
Задача 1¶
Перед обучением линейной регрессии вы могли совершать некоторые преобразования над признаками. Какие преобразования стоит совершить перед обучением решающего дерева?
В частности, ответьте и поясните свой ответ на вопрос, имеет ли смысл примененять следующие преобразования:
- монотонные функции от одного признака;
- немонотонные функции от одного признака;
- линейные функции от нескольких признаков;
- нелинейные функции от нескольких признаков;
- стандартизация признаков;
- преобразования категориальных признаков.
Например, вместо/дополнительно с признаком $x_j$ рассматривать признак $f(x_j)$, для указанных выше типов функций.
Задача 2¶
Скачайте данные по классификации кристаллических решеток. Целевой переменной в этой задаче является Lowest distortion
.
Каждое наблюдение описывается 13 столбцами признаков и 1 столбцом класса, который идентифицирует его как кубическую, тетрагональную, ромбическую или ромбоэдрическую структуру. Наборы признаков - различные параметры кристаллической решетки, такие как валентность, ионный радиус, среднее значение электроотрицательности, постоянная решетки, а так же энергия, которая численно равна работе, которую необходимо затратить, чтобы разделить и отделить друг от друга на бесконечное расстояние частицы.
data = pd.read_csv("/content/Crystal_structure.csv")
Сделаем предобработку данных.
# уберем признаки, которые нам не нужны (подробнее можете почиать во вкладке 'Code' на странице датасета)
data = data.drop(["In literature", "Compound", "τ"], axis=1)
# убираем объекты, для которых неизвестен таргет
data = data.drop(data[data["Lowest distortion"] == "-"].index).reset_index(drop=True)
# закодируем целевую переменную числами
data['Lowest distortion'] = LabelEncoder().fit_transform(data['Lowest distortion'])
# закодируем категориальные признаки числами
data['A'] = LabelEncoder().fit_transform(data['A'])
data['B'] = LabelEncoder().fit_transform(data['B'])
# обработаем пропуски
for i in data.columns:
column = data[i]
for k in range(len(column)):
if column[k] == '-':
column[k] = 0
data[i] = column
Профиль биология¶
В этом наборе данных содержится различная информация о пациентах, включая возраст, пол, артериальное давление, уровень холестерина, электрокардиографические характеристики (ЭКГ) и многое другое. Целевой характеристикой является target
- наличие у пациента сердечного заболевания.
Информация о наборе данных:
- age: Возраст пациента.
- sex: Пол пациента (0: женский, 1: мужской).
- cp: Тип боли в груди.
- trestbps: Артериальное давление в состоянии покоя.
- chol: уровень холестерина в сыворотке крови.
- fbs: Быстрый сахар крови > 120 мг/дл.
- restecg: Результаты электрокардиографии в состоянии покоя.
- thalach: Максимальная достигнутая частота сердечных сокращений.
- exang: Стенокардия, вызванная физической нагрузкой.
- oldpeak: Депрессия ST, вызванная физической нагрузкой по сравнению с покоем.
heart = pd.read_csv('heart.csv')
2. Обучение модели¶
Создайте массив признаков и массив таргета.
X = <...>
y = <...>
X_train, X_test, y_train, y_test = <...>
Обучите модель решающего дерева.
<...>
Сделайте предсказание для тестовой выборки.
<...>
Создайте массив, показывающий успех или не успех модели (1 если модель угадала класс, 0 если не угадала).
<...>
Вы получили выборку из распределения $Bern(\theta)$. Постройте доверительный интервал для $\theta$.
<...>
Повторите все шаги для случайного леса. Сравните полученные интервалы.
<...>
Выводы:
Сложная часть¶
Задача 3¶
1. Загрузка данных¶
Профиль физика¶
Рассмотрим набор данных НАСА, он включает в себя аэродинамические профили NACA-0012 разных размеров при различных параметрах в аэродинамической трубе и углах атаки. Скачайте данные и разделите их на три части — обучающую, валидационную и тестовую в соотношении 3:1:1. Целевой переменной будет scaled-sound-pressure: это звуковое давление в определенной части лопасти, распределение этой величины показано на втором рисунке. Данная задача конечно имеет почти аналитическое решение, однако оно занимает довольно много времени и ресурсов. Мы хотим продемострировать возможность использования лесов для быстрых и довольно точных численных оценок.
column_names = ['frequency', 'attack-angle', 'chord-length', 'free-stream-velocity', "suction-side-displacement-thickness", "scaled-sound-pressure"]
df = pd.read_csv("/content/airfoil_self_noise.dat", sep='\t', names=column_names)
df = df.rename(columns={'scaled-sound-pressure': 'target'})
df = df.sample(frac=1).reset_index(drop=True)
X = df.drop('target',axis=1)
y = df[['target']]
X_1, X_test, y_1, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
X_train, X_valid, y_train, y_valid = train_test_split(X_1, y_1, test_size=0.2, random_state=42)
data = pd.read_csv('abalone.data', names=['Sex', 'Length', 'Diameter', 'Height', 'Whole weight',
'Shucked weight', 'Viscera weight', 'Shell weight',
'Rings'])
data = data.drop('Sex', axis=1)
X = data.drop('Rings', axis=1)
y = data['Rings'] + 1.5
X_1, X_test, y_1, y_test = train_test_split(X, y, test_size = 0.2, random_state=42)
X_train, X_valid, y_train, y_valid = train_test_split(X_1, y_1, test_size = 0.2, random_state=42)
2. Обучение модели¶
Обучите решающее дерево глубины 3 и визуализируйте его.
Рекомендуется сделать скриншот визуализации и прислать его в бот вместе с ноутбуком.
<...>
Посчитайте выбранную метрику на валидационной выборке.
<...>
Подберите оптимальное значение максимальной глубины дерева. Для этого обучите решающие деревья с выставленным значением соответствующего гиперпараметра и посчитайте ошибку предсказаний каждого из них на валидационной выборке. Постройте соответствующий график - зависиость ошибки от максимальной глубины дерева. Подробнее про гиперпараметры смотрите в документации.
<...>
Аналогичным образом подберите минимальное число объектов, необходимое для того, чтобы узел дерева мог бы расщепиться, зафиксировав при этом подобранное значение максимальной глубины. Для минимального числа объектов в листе и максимального число признаков, по которым ищется лучшее разбиение в дереве, подберите аналогично, фиксируя лучшие значения гиперпараметров, подобранные на предыдущем шаге.
<...>
Обучите вашу лучшую модель и сделайте предсказание для тестовой выборки.
<...>
Теперь вам предлагается проверить результат своей реализации с уже существующей функцией для оптимизации гиперпараметров - GridSearchCV
. Эта функция помогает перебирать предопределенные гиперпараметры и подгонять вашу модель к тренировочному набору. Сравните полученные гиперпараметры и если они различаются, объясните почему. Для этого вам может понадобится документация.
<...>
Посчитатайте метрику на тестовой выборке и взуализируйте деревья при оптимальных гиперпараметрахдля двух оптимальных моделей - вашей и GridSearchCV.
Ваша модель
<...>
Лучшая модель по мнению GridSearchCV
<...>
Решающее дерево позволяет оценить важность признаков — некоторая величина, зависящая от того
- насколько часто тот или иной признак использовался при разбиении листа,
- и насколько сильно при этом изменился критерий информативности.
У обученной модели значения важности признаков лежат в поле feature_importances_
. Визуализируйте их на одном графике с помощью seaborn.barplot
для обеих моделей.
<...>
Сделайте выводы. Объясните, согласуется ли логически, почему вес того или иного параметра так влияет на целевую переменную.
Вывод: <...>
Задача 4¶
Для данных из задачи 3 обучите случайный лес на 500 деревьев.
<...>
Постройте график зависимости ошибки модели в зависимости от количества деревьев для обучающей и валидационной выборок.
Замечание. Не нужно заново обучать лес каждый раз. Используйте у обученной модели поле estimators_
, это список из объектов класса DecisionTreeRegressor
. Обратите внимание, что это приватное поле объекта, и менять его очень плохо, за такое баллы будут снижаться.
Посчитайте метрику на тестовой выборке.
<...>
Для леса с максимальным количеством деревьев визуализируйте
важность признаков, используя поле feature_importances_
.
<...>
Сделайте выводы.
Вывод: <...>