Phystech@DataScience¶

Домашнее задание 4¶

Правила, прочитайте внимательно:

  • Выполненную работу нужно отправить телеграм-боту @thetahat_ds25_bot. Для начала работы с ботом каждый раз отправляйте /start. Дождитесь подтверждения от бота, что он принял файл. Если подтверждения нет, то что-то не так. Работы, присланные иным способом, не принимаются.
  • Дедлайн см. в боте. После дедлайна работы не принимаются кроме случаев наличия уважительной причины.
  • Прислать нужно ноутбук в формате ipynb. Если вы строите интерактивные графики, их стоит прислать в формате html.
  • Следите за размером файлов. Бот не может принимать файлы весом более 20 Мб. Если файл получается больше, заранее разделите его на несколько.
  • Выполнять задание необходимо полностью самостоятельно. При обнаружении списывания всем участникам списывания дается штраф -2 балла к итоговой оценке за семестр.
  • Решения, размещенные на каких-либо интернет-ресурсах, не принимаются. Кроме того, публикация решения в открытом доступе может быть приравнена к предоставлении возможности списать.
  • Обратите внимание на правила использования ИИ-инструментов при решении домашнего задания.
  • Код из рассказанных на занятиях ноутбуков можно использовать без ограничений.
  • Для выполнения задания используйте этот ноутбук в качестве основы, ничего не удаляя из него. Можно добавлять необходимое количество ячеек.
  • Комментарии к решению пишите в markdown-ячейках.
  • Выполнение задания (ход решения, выводы и пр.) должно быть осуществлено на русском языке.
  • Решение проверяется системой ИИ-проверки No description has been provided for this image ThetaGrader. Результат проверки валидируется и исправляется человеком, после чего комментарии отправляются студентам.
  • Если код будет не понятен проверяющему, оценка может быть снижена.
  • Никакой код из данного задания при проверке запускаться не будет. Если код студента не выполнен, недописан и т.д., то он не оценивается.

Важно!!! Правила заполнения ноутбука:

  • Запрещается удалять имеющиеся в ноутбуке ячейки, менять местами положения задач.
  • Сохраняйте естественный линейный порядок повествования в ноутбуке сверху-вниз.
  • Отвечайте на вопросы, а также добавляйте новые ячейки в предложенных местах, которые обозначены <...>.
  • В markdown-ячейках, содержащих описание задачи, находятся специальные отметки, которые запрещается модифицировать.
  • При нарушении данных правил работа может получить 0 баллов.

Баллы за задание:

Легкая часть (достаточно на "хор"):

  • Задача 1 — 20 баллов
  • Задача 2 — 40 баллов

Cложная часть (необходимо на "отл"):

  • Задача 3 — 60 баллов

In [ ]:
# Bot check

# HW_ID: phds_hw4
# Бот проверит этот ID и предупредит, если случайно сдать что-то не то.

# Status: not final
# Перед отправкой в финальном решении удали "not" в строчке выше.
# Так бот проверит, что ты отправляешь финальную версию, а не промежуточную.
# Никакие значения в этой ячейке не влияют на факт сдачи работы.
In [ ]:
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)$, для указанных выше типов функций.

In [ ]:
...

Задача 2¶

1. Загрузка и предобработка данных.¶

Профиль физика¶

Скачайте данные по классификации кристаллических решеток. Целевой переменной в этой задаче является Lowest distortion.

CrystalStructure-web.jpg

Каждое наблюдение описывается 13 столбцами признаков и 1 столбцом класса, который идентифицирует его как кубическую, тетрагональную, ромбическую или ромбоэдрическую структуру. Наборы признаков - различные параметры кристаллической решетки, такие как валентность, ионный радиус, среднее значение электроотрицательности, постоянная решетки, а так же энергия, которая численно равна работе, которую необходимо затратить, чтобы разделить и отделить друг от друга на бесконечное расстояние частицы.

In [ ]:
data = pd.read_csv("/content/Crystal_structure.csv")

Сделаем предобработку данных.

In [ ]:
# уберем признаки, которые нам не нужны
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 - наличие у пациента сердечного заболевания.

Информация о наборе данных:

  1. age: Возраст пациента.
  2. sex: Пол пациента (0: женский, 1: мужской).
  3. cp: Тип боли в груди.
  4. trestbps: Артериальное давление в состоянии покоя.
  5. chol: уровень холестерина в сыворотке крови.
  6. fbs: Быстрый сахар крови > 120 мг/дл.
  7. restecg: Результаты электрокардиографии в состоянии покоя.
  8. thalach: Максимальная достигнутая частота сердечных сокращений.
  9. exang: Стенокардия, вызванная физической нагрузкой.
  10. oldpeak: Депрессия ST, вызванная физической нагрузкой по сравнению с покоем.
In [ ]:
heart = pd.read_csv('heart.csv')

2. Обучение модели¶

Создайте массив признаков и вектор таргета.

In [ ]:
X = <...>
y = <...>
In [ ]:
X_train, X_test, y_train, y_test = <...>

Обучите модель решающего дерева.

In [ ]:
<...>

Сделайте предсказание для тестовой выборки.

In [ ]:
<...>

Посчитайте точность предсказания

In [ ]:
<...>

Повторите все шаги для случайного леса. Лес — много похожих, но всё же отличающихся деревьев. Такая модель делает предсказание, усредняя ответы отдельных деревьев. Подробнее мы рассмотрим эту модель в осенней части курса, а пока просто воспользуйтесь готовым классом RandomForestClassifier. Сравните полученные результаты.

In [ ]:
<...>

Выводы:

Сложная часть¶


Задача 3¶

1. Загрузка данных¶

Профиль физика¶

Рассмотрим набор данных NASA , он включает в себя аэродинамические профили NASA-0012 разных размеров при различных параметрах в аэродинамической трубе и углах атаки. Скачайте данные и разделите их на три части — обучающую, валидационную и тестовую в соотношении 3:1:1. Целевой переменной будет scaled-sound-pressure: это звуковое давление в определенной части лопасти, распределение этой величины показано на втором рисунке. Данная задача, конечно, имеет почти аналитическое решение, однако оно занимает довольно много времени и ресурсов. Мы хотим продемострировать возможность использования методов машинного обучения для быстрых и довольно точных численных оценок.

photo_2024-04-13_14-52-24.jpg

In [ ]:
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)
In [ ]:
df = df.rename(columns={'scaled-sound-pressure': 'target'})
df = df.sample(frac=1).reset_index(drop=True)
In [ ]:
X = df.drop('target',axis=1)
y = df[['target']]
In [ ]:
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)

Профиль биология¶

Данные. Будем предсказывать возраст моллюсков.

молюсок.jpg

In [ ]:
data = pd.read_csv('abalone.data', names=['Sex', 'Length', 'Diameter', 'Height', 'Whole weight',
                                          'Shucked weight', 'Viscera weight', 'Shell weight',
                                          'Rings'])
In [ ]:
data = data.drop('Sex', axis=1)
X = data.drop('Rings', axis=1)
y = data['Rings'] + 1.5
In [ ]:
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 и визуализируйте его.

Рекомендуется сделать скриншот визуализации и прислать его в бот вместе с ноутбуком.

In [ ]:
<...>

Посчитайте выбранную метрику на валидационной выборке (не на тестовой)

In [ ]:
<...>

Подберите оптимальное значение максимальной глубины дерева. Для этого обучите решающие деревья с выставленным значением соответствующего гиперпараметра и посчитайте ошибку предсказаний каждого из них на валидационной выборке. Постройте соответствующий график - зависимость ошибки от максимальной глубины дерева. Подробнее про гиперпараметры смотрите в документации.

In [ ]:
<...>

Аналогичным образом подберите минимальное число объектов, необходимое для того, чтобы узел дерева мог бы расщепиться, зафиксировав при этом подобранное значение максимальной глубины. Для минимального числа объектов в листе и максимального числа признаков, по которым ищется лучшее разбиение в дереве, подберите аналогично, фиксируя лучшие значения гиперпараметров, подобранные на предыдущем шаге.

In [ ]:
<...>

Обучите вашу лучшую модель и сделайте предсказание для тестовой выборки.

In [ ]:
<...>

Теперь вам предлагается проверить результат своей реализации с уже существующей функцией для оптимизации гиперпараметров - GridSearchCV. Эта функция помогает перебирать предопределенные гиперпараметры и подгонять вашу модель к тренировочному набору. Сравните полученные гиперпараметры и если они различаются, объясните почему. Для этого вам может понадобиться документация.

In [ ]:
<...>

Посчитатайте метрику на тестовой выборке и взуализируйте деревья при оптимальных гиперпараметрахдля двух оптимальных моделей - вашей и GridSearchCV.

Ваша модель

In [ ]:
<...>

Лучшая модель по мнению GridSearchCV

In [ ]:
<...>

Решающее дерево позволяет оценить важность признаков. Это некоторая величина, зависящая от того,

  • насколько часто тот или иной признак использовался при разбиении листа,
  • и насколько сильно при этом изменился критерий информативности.

У обученной модели значения важности признаков лежат в поле feature_importances_. Визуализируйте их на одном графике с помощью seaborn.barplot для обеих моделей.

In [ ]:
<...>

Сделайте выводы. Объясните, согласуется ли логически, почему вес того или иного признака так влияет на целевую переменную.

Вывод: <...>

3. Случайный лес¶

Обучите RandomForestRegressor на 500 деревьев. Остальные параметры оставьте по-умолчанию.

In [ ]:
<...>

Посчитайте метрику на тестовой выборке.

In [ ]:
<...>

Визуализируйте важность признаков, используя поле feature_importances_.

In [ ]:
<...>

Сделайте выводы.

Вывод: <...>