Phystech@DataScience¶
Домашнее задание 4¶
Правила, прочитайте внимательно:
- Выполненную работу нужно отправить телеграм-боту
@thetahat_ds25_bot
. Для начала работы с ботом каждый раз отправляйте/start
. Дождитесь подтверждения от бота, что он принял файл. Если подтверждения нет, то что-то не так. Работы, присланные иным способом, не принимаются. - Дедлайн см. в боте. После дедлайна работы не принимаются кроме случаев наличия уважительной причины.
- Прислать нужно ноутбук в формате
ipynb
. Если вы строите интерактивные графики, их стоит прислать в формате html. - Следите за размером файлов. Бот не может принимать файлы весом более 20 Мб. Если файл получается больше, заранее разделите его на несколько.
- Выполнять задание необходимо полностью самостоятельно. При обнаружении списывания всем участникам списывания дается штраф -2 балла к итоговой оценке за семестр.
- Решения, размещенные на каких-либо интернет-ресурсах, не принимаются. Кроме того, публикация решения в открытом доступе может быть приравнена к предоставлении возможности списать.
- Обратите внимание на правила использования ИИ-инструментов при решении домашнего задания.
- Код из рассказанных на занятиях ноутбуков можно использовать без ограничений.
- Для выполнения задания используйте этот ноутбук в качестве основы, ничего не удаляя из него. Можно добавлять необходимое количество ячеек.
- Комментарии к решению пишите в markdown-ячейках.
- Выполнение задания (ход решения, выводы и пр.) должно быть осуществлено на русском языке.
- Решение проверяется системой ИИ-проверки
ThetaGrader. Результат проверки валидируется и исправляется человеком, после чего комментарии отправляются студентам.
- Если код будет не понятен проверяющему, оценка может быть снижена.
- Никакой код из данного задания при проверке запускаться не будет. Если код студента не выполнен, недописан и т.д., то он не оценивается.
Важно!!! Правила заполнения ноутбука:
- Запрещается удалять имеющиеся в ноутбуке ячейки, менять местами положения задач.
- Сохраняйте естественный линейный порядок повествования в ноутбуке сверху-вниз.
- Отвечайте на вопросы, а также добавляйте новые ячейки в предложенных местах, которые обозначены
<...>
. - В markdown-ячейках, содержащих описание задачи, находятся специальные отметки, которые запрещается модифицировать.
- При нарушении данных правил работа может получить 0 баллов.
Баллы за задание:
Легкая часть (достаточно на "хор"):
- Задача 1 — 20 баллов
- Задача 2 — 40 баллов
Cложная часть (необходимо на "отл"):
- Задача 3 — 60 баллов
# Bot check
# HW_ID: phds_hw4
# Бот проверит этот ID и предупредит, если случайно сдать что-то не то.
# Status: not final
# Перед отправкой в финальном решении удали "not" в строчке выше.
# Так бот проверит, что ты отправляешь финальную версию, а не промежуточную.
# Никакие значения в этой ячейке не влияют на факт сдачи работы.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier, RandomForestRegressor
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.preprocessing import LabelEncoder
sns.set_theme(style='whitegrid', font_scale=1.3, palette='Set2')
Легкая часть¶
Задача 1.¶
Перед обучением линейной регрессии вы могли совершать некоторые преобразования над признаками. Какие преобразования стоит совершить перед обучением решающего дерева?
В частности, ответьте и поясните свой ответ на вопрос, имеет ли смысл примененять следующие преобразования:
- монотонные функции от одного признака;
- немонотонные функции от одного признака;
- линейные функции от нескольких признаков;
- нелинейные функции от нескольких признаков;
- стандартизация признаков;
- преобразования категориальных признаков.
Например, вместо/дополнительно с признаком $x_j$ рассматривать признак $f(x_j)$, для указанных выше типов функций.
...
Задача 2¶
Скачайте данные по классификации кристаллических решеток. Целевой переменной в этой задаче является Lowest distortion
.
Каждое наблюдение описывается 13 столбцами признаков и 1 столбцом класса, который идентифицирует его как кубическую, тетрагональную, ромбическую или ромбоэдрическую структуру. Наборы признаков - различные параметры кристаллической решетки, такие как валентность, ионный радиус, среднее значение электроотрицательности, постоянная решетки, а так же энергия, которая численно равна работе, которую необходимо затратить, чтобы разделить и отделить друг от друга на бесконечное расстояние частицы.
data = pd.read_csv("/content/Crystal_structure.csv")
Сделаем предобработку данных.
# уберем признаки, которые нам не нужны
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 = <...>
Обучите модель решающего дерева.
<...>
Сделайте предсказание для тестовой выборки.
<...>
Посчитайте точность предсказания
<...>
Повторите все шаги для случайного леса. Лес — много похожих, но всё же отличающихся деревьев. Такая модель делает предсказание, усредняя ответы отдельных деревьев. Подробнее мы рассмотрим эту модель в осенней части курса, а пока просто воспользуйтесь готовым классом RandomForestClassifier. Сравните полученные результаты.
<...>
Выводы:
Сложная часть¶
Задача 3¶
1. Загрузка данных¶
Профиль физика¶
Рассмотрим набор данных NASA , он включает в себя аэродинамические профили NASA-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)
Обратите внимание: мы разбили выборку на 3 подмножества: обучающая, валидационая и тестовая. Внимательно следите за указаниями, где и какую подвыборку использовать.
2. Обучение модели¶
Обучите решающее дерево глубины 3 и визуализируйте его.
Рекомендуется сделать скриншот визуализации и прислать его в бот вместе с ноутбуком.
<...>
Посчитайте выбранную метрику на валидационной выборке (не на тестовой)
<...>
Подберите оптимальное значение максимальной глубины дерева. Для этого обучите решающие деревья с выставленным значением соответствующего гиперпараметра и посчитайте ошибку предсказаний каждого из них на валидационной выборке. Постройте соответствующий график - зависимость ошибки от максимальной глубины дерева. Подробнее про гиперпараметры смотрите в документации.
<...>
Аналогичным образом подберите минимальное число объектов, необходимое для того, чтобы узел дерева мог бы расщепиться, зафиксировав при этом подобранное значение максимальной глубины. Для минимального числа объектов в листе и максимального числа признаков, по которым ищется лучшее разбиение в дереве, подберите аналогично, фиксируя лучшие значения гиперпараметров, подобранные на предыдущем шаге.
<...>
Обучите вашу лучшую модель и сделайте предсказание для тестовой выборки.
<...>
Теперь вам предлагается проверить результат своей реализации с уже существующей функцией для оптимизации гиперпараметров - GridSearchCV
. Эта функция помогает перебирать предопределенные гиперпараметры и подгонять вашу модель к тренировочному набору. Сравните полученные гиперпараметры и если они различаются, объясните почему. Для этого вам может понадобиться документация.
<...>
Посчитатайте метрику на тестовой выборке и взуализируйте деревья при оптимальных гиперпараметрахдля двух оптимальных моделей - вашей и GridSearchCV.
Ваша модель
<...>
Лучшая модель по мнению GridSearchCV
<...>
Решающее дерево позволяет оценить важность признаков. Это некоторая величина, зависящая от того,
- насколько часто тот или иной признак использовался при разбиении листа,
- и насколько сильно при этом изменился критерий информативности.
У обученной модели значения важности признаков лежат в поле feature_importances_
. Визуализируйте их на одном графике с помощью seaborn.barplot
для обеих моделей.
<...>
Сделайте выводы. Объясните, согласуется ли логически, почему вес того или иного признака так влияет на целевую переменную.
Вывод: <...>
3. Случайный лес¶
Обучите RandomForestRegressor на 500 деревьев. Остальные параметры оставьте по-умолчанию.
<...>
Посчитайте метрику на тестовой выборке.
<...>
Визуализируйте важность признаков, используя поле feature_importances_
.
<...>
Сделайте выводы.
Вывод: <...>