Задание выполнил(а): Подчезерцев Алексей
Дата выдачи: 27.04.2019
Дедлайн: 23:59 12.05.2019
За сдачу задания позже срока на итоговую оценку за задание накладывается штраф в размере 1 балл в день, но получить отрицательную оценку нельзя.
Внимание! Домашнее задание выполняется самостоятельно. «Похожие» решения считаются плагиатом и все задействованные студенты (в том числе те, у кого списали) не могут получить за него больше 0 баллов.
Стирать условия нельзя!
Загрузка файлов с решениями происходит в системе Anytask.
Формат названия файла: homework_04_Подчезерцев_Алексей.ipynb
Задание 1. (0.5 балла)
Мы будем использовать данные соревнования Home Credit Default Risk.
Так как в данных значительный дисбаланс классов, в качестве метрики качества везде будем использовать площадь под precision-recall кривой.
import numpy as np
import pandas as pd
import seaborn as sns
%matplotlib inline
%%time
X_orig = pd.read_csv('application_train.csv', index_col=0)
%%time
X = X_orig.copy()
Приведем в числовой вид бинарные признаки
%%time
X["CODE_GENDER"] = X.apply(lambda x: 1 if x["CODE_GENDER"] == 'M' else 0, axis=1)
X["FLAG_OWN_CAR"] = X.apply(lambda x: 1 if x["FLAG_OWN_CAR"] == 'Y' else 0, axis=1)
X["FLAG_OWN_REALTY"] = X.apply(lambda x: 1 if x["FLAG_OWN_REALTY"] == 'Y' else 0, axis=1)
X["NAME_CONTRACT_TYPE"] = X.apply(lambda x: 1 if x["NAME_CONTRACT_TYPE"] == 'Revolving loans' else 0, axis=1)
#X = X.drop("NAME_TYPE_SUITE", axis=1)
def plot_corr(D, size):
corr = D.corr()
corr = np.abs(corr)
f, ax = plt.subplots(figsize=(size, size))
cmap = plt.cm.Oranges
sns.heatmap(corr, cmap=cmap,
xticklabels=corr.columns,
yticklabels=corr.columns)
%%time
plot_corr(X, 60)
Метрики дома сильно коррелируют друг с другом, избавимся от них
%%time
#
X.drop("APARTMENTS_AVG", axis=1, inplace=True)
X.drop("BASEMENTAREA_AVG", axis=1, inplace=True)
# X.drop("YEARS_BEGINEXPLUATATION_AVG", axis=1, inplace=True)
X.drop("YEARS_BUILD_AVG", axis=1, inplace=True)
X.drop("COMMONAREA_AVG", axis=1, inplace=True)
X.drop("ELEVATORS_AVG", axis=1, inplace=True)
X.drop("ENTRANCES_AVG", axis=1, inplace=True)
X.drop("FLOORSMAX_AVG", axis=1, inplace=True)
X.drop("FLOORSMIN_AVG", axis=1, inplace=True)
X.drop("LANDAREA_AVG", axis=1, inplace=True)
X.drop("LIVINGAPARTMENTS_AVG", axis=1, inplace=True)
# X.drop("LIVINGAREA_AVG", axis=1, inplace=True)
X.drop("NONLIVINGAPARTMENTS_AVG", axis=1, inplace=True)
X.drop("NONLIVINGAREA_AVG", axis=1, inplace=True)
X.drop("APARTMENTS_MODE", axis=1, inplace=True)
X.drop("BASEMENTAREA_MODE", axis=1, inplace=True)
X.drop("YEARS_BEGINEXPLUATATION_MODE", axis=1, inplace=True)
X.drop("YEARS_BUILD_MODE", axis=1, inplace=True)
X.drop("COMMONAREA_MODE", axis=1, inplace=True)
X.drop("ELEVATORS_MODE", axis=1, inplace=True)
X.drop("ENTRANCES_MODE", axis=1, inplace=True)
X.drop("FLOORSMAX_MODE", axis=1, inplace=True)
X.drop("FLOORSMIN_MODE", axis=1, inplace=True)
X.drop("LANDAREA_MODE", axis=1, inplace=True)
X.drop("LIVINGAPARTMENTS_MODE", axis=1, inplace=True)
X.drop("LIVINGAREA_MODE", axis=1, inplace=True)
X.drop("NONLIVINGAPARTMENTS_MODE", axis=1, inplace=True)
X.drop("NONLIVINGAREA_MODE", axis=1, inplace=True)
X.drop("APARTMENTS_MEDI", axis=1, inplace=True)
X.drop("BASEMENTAREA_MEDI", axis=1, inplace=True)
X.drop("YEARS_BEGINEXPLUATATION_MEDI", axis=1, inplace=True)
X.drop("YEARS_BUILD_MEDI", axis=1, inplace=True)
X.drop("COMMONAREA_MEDI", axis=1, inplace=True)
X.drop("ELEVATORS_MEDI", axis=1, inplace=True)
X.drop("ENTRANCES_MEDI", axis=1, inplace=True)
X.drop("FLOORSMAX_MEDI", axis=1, inplace=True)
X.drop("FLOORSMIN_MEDI", axis=1, inplace=True)
X.drop("LANDAREA_MEDI", axis=1, inplace=True)
X.drop("LIVINGAPARTMENTS_MEDI", axis=1, inplace=True)
X.drop("LIVINGAREA_MEDI", axis=1, inplace=True)
X.drop("NONLIVINGAPARTMENTS_MEDI", axis=1, inplace=True)
X.drop("NONLIVINGAREA_MEDI", axis=1, inplace=True)
X.drop("FONDKAPREMONT_MODE", axis=1, inplace=True)
X.drop("HOUSETYPE_MODE", axis=1, inplace=True)
X.drop("TOTALAREA_MODE", axis=1, inplace=True)
X.drop("WALLSMATERIAL_MODE", axis=1, inplace=True)
X.drop("EMERGENCYSTATE_MODE", axis=1, inplace=True)
Дропнем некоторые хорошо взаимокоррелируемые значения
X.drop("AMT_ANNUITY", axis=1, inplace=True)
X.drop("AMT_GOODS_PRICE", axis=1, inplace=True)
X.drop("DAYS_EMPLOYED", axis=1, inplace=True)
X.drop("REGION_RATING_CLIENT_W_CITY", axis=1, inplace=True)
X.drop("LIVE_CITY_NOT_WORK_CITY", axis=1, inplace=True)
X.drop("LIVE_REGION_NOT_WORK_REGION", axis=1, inplace=True)
X.drop("OBS_60_CNT_SOCIAL_CIRCLE", axis=1, inplace=True)
X.drop("DEF_60_CNT_SOCIAL_CIRCLE", axis=1, inplace=True)
%%time
plot_corr(X, 40)
X.head()
_x_null=X.isnull().sum(axis=0)
_x_null = _x_null[_x_null != 0]
_x_null.shape
_x_null[_x_null != 0]
X["OWN_CAR_AGE"].fillna(0, inplace=True)
X["OCCUPATION_TYPE"].fillna('', inplace=True)
X["EXT_SOURCE_1"].fillna(0.5, inplace=True)
X["EXT_SOURCE_2"].fillna(0.5, inplace=True)
X["EXT_SOURCE_3"].fillna(0.5, inplace=True)
X["YEARS_BEGINEXPLUATATION_AVG"].fillna(0.5, inplace=True)
X["LIVINGAREA_AVG"].fillna(0.5, inplace=True)
X["AMT_REQ_CREDIT_BUREAU_HOUR"].fillna(0, inplace=True)
X["AMT_REQ_CREDIT_BUREAU_DAY"].fillna(0, inplace=True)
X["AMT_REQ_CREDIT_BUREAU_WEEK"].fillna(0, inplace=True)
X["AMT_REQ_CREDIT_BUREAU_MON"].fillna(0, inplace=True)
X["AMT_REQ_CREDIT_BUREAU_QRT"].fillna(0, inplace=True)
X["AMT_REQ_CREDIT_BUREAU_YEAR"].fillna(0, inplace=True)
X.head()
_x_null=X.isnull().sum(axis=0)
_x_null = _x_null[_x_null != 0]
_x_null.shape
_x_null[_x_null != 0]
X.dropna(axis = 0, inplace=True)
X.shape
X.info()
X = X.reset_index(drop=True)
y = X["TARGET"]
X = X.drop("TARGET", axis=1)
X.head()
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)
Задание 2. (1.5 балла)
Обучите реализации градиентного бустинга LightGBM и Catboost на вещественных признаках без подбора параметров. Почему получилась заметная разница в качестве?
В этом и последующих экспериментах необходимо измерять время обучения моделей.
from catboost import CatBoostClassifier
import lightgbm as lgb
from sklearn.metrics import precision_recall_curve, auc
def pr_auc(y_true, y_scores):
precision, recall, thresholds = precision_recall_curve(y_true, y_scores)
return auc(recall, precision)
X_train_2 = X_train.select_dtypes(include=["int64", "float64"])
X_test_2 = X_test.select_dtypes(include=["int64", "float64"])
%%time
yandex_clf = CatBoostClassifier(logging_level='Silent')
yandex_clf.fit(X_train_2, y_train)
y_predict_2 = yandex_clf.predict_proba(X_test_2)[:,1]
print("PR-AUC for default yandex boost", pr_auc(y_test, y_predict_2))
%%time
l_clf = lgb.LGBMClassifier()
l_clf.fit(X_train_2, y_train)
y_predict_2 = l_clf.predict_proba(X_test_2)[:,1]
print("PR-AUC for default lgb", pr_auc(y_test, y_predict_2))
Алгоритмы catboost и lightgbm имеют разные дефолтные параметры, поэтому отличаются метрики качества и время работы.
Задание 3. (2 балла)
Подберите с CV=3 оптимальные параметры алгоритмов, изменяя:
Проанализируйте соотношения глубины и количества деревьев в зависимости от алгоритма.
from sklearn.model_selection import KFold
from time import time
CV = 3
kf = KFold(n_splits=CV,shuffle=True, random_state=0)
X_3 = X.select_dtypes(include=["int64", "float64"])
def calc_CV_classifier(kf, x, y, classifier):
_auc = []
_times = []
for train_index, test_index in kf.split(x):
begin = time()
classifier.fit(x.values[train_index], y[train_index])
_times.append(time() - begin)
y_predict = classifier.predict_proba(x.values[test_index])[:,1]
_auc.append(pr_auc(y[test_index], y_predict))
d = {}
d["auc_mean"] = [sum(_auc)/len(_auc)]
d["time_mean"] = [sum(_times)/len(_times)]
for i in range(len(_auc)):
d["auc_" + str(i + 1)] = [_auc[i]]
for i in range(len(_times)):
d["time_" + str(i + 1)] = [_times[i] ]
return pd.DataFrame(data=d)
%%time
max_trees = 100
learning_rate = 0.1
result_depth = pd.DataFrame()
for depth in range(1, 10, 2):
ya_clf = CatBoostClassifier(logging_level='Silent', depth=depth, iterations=max_trees, learning_rate=learning_rate)
ya_result = calc_CV_classifier(kf, X_3, y, ya_clf)
ya_result.insert(0, "name", ["ya_depth_" + str(depth)])
result_depth = result_depth.append(ya_result, ignore_index=True)
l_clf = lgb.LGBMClassifier(max_depth=depth, n_estimators=max_trees, learning_rate=learning_rate)
l_result = calc_CV_classifier(kf, X_3, y, l_clf)
l_result.insert(0, "name", ["lgbm_depth_" + str(depth)])
result_depth = result_depth.append(l_result, ignore_index=True)
result_depth.set_index('name')
result_depth.sort_values("auc_mean")[::-1]
def log_int_iterator(start, end, step):
i = start
while i <= end:
yield int(i)
i *= step
%%time
depth = 7
learning_rate = 0.1
result_trees = pd.DataFrame()
for max_trees in log_int_iterator(80, 160, 1.3):
ya_clf = CatBoostClassifier(logging_level='Silent', depth=depth, iterations=max_trees, learning_rate=learning_rate)
ya_result = calc_CV_classifier(kf, X_3, y, ya_clf)
ya_result.insert(0, "name", ["ya_trees_" + str(max_trees)])
result_trees = result_trees.append(ya_result, ignore_index=True)
for max_trees in log_int_iterator(160, 320, 1.3):
l_clf = lgb.LGBMClassifier(max_depth=depth, n_estimators=max_trees, learning_rate=learning_rate)
l_result = calc_CV_classifier(kf, X_3, y, l_clf)
l_result.insert(0, "name", ["lgbm_trees_" + str(max_trees)])
result_trees = result_trees.append(l_result, ignore_index=True)
result_trees.set_index('name')
result_trees.sort_values("auc_mean")[::-1]
def log_iterator(start, end, step):
i = start
while i <= end:
yield i
i *= step
%%time
depth = 7
max_trees = 100
result_rate = pd.DataFrame()
for learning_rate in log_iterator(0.1, 0.2, 1.1):
ya_clf = CatBoostClassifier(logging_level='Silent', depth=depth, iterations=max_trees, learning_rate=learning_rate)
ya_result = calc_CV_classifier(kf, X_3, y, ya_clf)
ya_result.insert(0, "name", ["ya_rate_" + str(learning_rate)])
result_rate = result_rate.append(ya_result, ignore_index=True)
for learning_rate in log_iterator(0.01, 0.1, 1.2):
l_clf = lgb.LGBMClassifier(max_depth=depth, n_estimators=max_trees, learning_rate=learning_rate)
l_result = calc_CV_classifier(kf, X_3, y, l_clf)
l_result.insert(0, "name", ["lgbm_rate_" + str(learning_rate)])
result_rate = result_rate.append(l_result, ignore_index=True)
result_rate.set_index('name')
result_rate.sort_values("auc_mean")[::-1]
%%time
depth = 7
max_trees = 100
learning_rate=0.1
result_obj = pd.DataFrame()
for loss_function in ["CrossEntropy", "Logloss", None]:
ya_clf = CatBoostClassifier(logging_level='Silent', depth=depth, iterations=max_trees, learning_rate=learning_rate, loss_function=loss_function)
ya_result = calc_CV_classifier(kf, X_3, y, ya_clf)
ya_result.insert(0, "name", ["ya_loss_function_" + str(loss_function)])
result_obj = result_obj.append(ya_result, ignore_index=True)
%%time
result_obj_2 = result_obj.copy()
l_clf = lgb.LGBMClassifier(max_depth=depth, n_estimators=max_trees, learning_rate=learning_rate)
l_result = calc_CV_classifier(kf, X_3, y, l_clf)
l_result.insert(0, "name", ["lgbm_objective_None"])
result_obj_2 = result_obj_2.append(l_result, ignore_index=True)
l_clf = lgb.LGBMClassifier(max_depth=depth, n_estimators=max_trees, learning_rate=learning_rate, is_unbalance=True)
l_result = calc_CV_classifier(kf, X_3, y, l_clf)
l_result.insert(0, "name", ["lgbm_objective_is_unbalance=True"])
result_obj_2 = result_obj_2.append(l_result, ignore_index=True)
result_obj_2.set_index('name')
%%time
result_obj_3 = result_obj_2.copy()
for metric in ["binary_logloss", "binary_error", "cross_entropy"]:
l_clf = lgb.LGBMClassifier(max_depth=depth, n_estimators=max_trees, learning_rate=learning_rate, is_unbalance=True, metric=metric)
l_result = calc_CV_classifier(kf, X_3, y, l_clf)
l_result.insert(0, "name", ["lgbm_objective_" + str(metric) + "_is_unbalance=True"])
result_obj_3 = result_obj_3.append(l_result, ignore_index=True)
result_obj_3.sort_values("auc_mean")[::-1]
Чем больше количество деревьев и глубина построения, тем дольше работает алгоритм. До некоторого числа растет качество моделей, затем оно начинает падать
Задание 4. (3.5 балла)
Добавьте категориальные признаки к вещественным следующими способами:
При подсчете счетчиков запрещается использование циклов.
На получившихся датасетах подберите параметры у каждого из алгоритмов. Как меняется время, необходимое для обучения модели в зависимости от способа кодирования? Сравните полученные результаты с встроенными методами обработки категориальных признаков.
def calc_classifier(x_train, y_train, x_test, y_test, classifier):
begin = time()
classifier.fit(x_train, y_train)
_times = time() - begin
y_predict = classifier.predict_proba(x_test)[:,1]
_auc = pr_auc(y_test, y_predict)
d = {}
d["auc"] = [_auc]
d["time"] = [_times]
return pd.DataFrame(data=d)
X_train_OHE = X_train.copy()
X_test_OHE = X_test.copy()
y_train_OHE = y_train.copy()
y_test_OHE = y_test.copy()
%%time
for i in X_train_OHE:
if X_train_OHE[i].dtype == 'object':
X_train_OHE = pd.concat([X_train_OHE, pd.get_dummies(X_train_OHE[i], prefix = i)], axis=1)
X_test_OHE = pd.concat([X_test_OHE, pd.get_dummies(X_test_OHE[i], prefix = i)], axis=1)
X_train_OHE.head()
X_train_OHE = X_train_OHE.select_dtypes(include=["int64", "float64", "uint8"])
X_test_OHE = X_test_OHE.select_dtypes(include=["int64", "float64", "uint8"])
%%time
max_trees = 100
learning_rate = 0.1
result_depth_OHE = pd.DataFrame()
for depth in range(5, 10, 2):
ya_result = calc_classifier(X_train_OHE, y_train_OHE, X_test_OHE, y_test_OHE, CatBoostClassifier(logging_level='Silent', depth=depth, iterations=max_trees, learning_rate=learning_rate))
ya_result.insert(0, "name", ["ya_depth_" + str(depth)])
result_depth_OHE = result_depth_OHE.append(ya_result, ignore_index=True)
for depth in range(11, 20, 2):
l_result = calc_classifier(X_train_OHE, y_train_OHE, X_test_OHE, y_test_OHE, lgb.LGBMClassifier(max_depth=depth, n_estimators=max_trees, learning_rate=learning_rate))
l_result.insert(0, "name", ["lgbm_depth_" + str(depth)])
result_depth_OHE = result_depth_OHE.append(l_result, ignore_index=True)
result_depth_OHE.set_index('name')
result_depth_OHE.sort_values("auc")[::-1]
%%time
learning_rate = 0.1
result_trees_OHE = pd.DataFrame()
for max_trees in log_int_iterator(80, 160, 1.3):
ya_result = calc_classifier(X_train_OHE, y_train_OHE, X_test_OHE, y_test_OHE,
CatBoostClassifier(logging_level='Silent', depth=7, iterations=max_trees, learning_rate=learning_rate))
ya_result.insert(0, "name", ["ya_trees_" + str(max_trees)])
result_trees_OHE = result_trees_OHE.append(ya_result, ignore_index=True)
for max_trees in log_int_iterator(160, 320, 1.3):
l_result = calc_classifier(X_train_OHE, y_train_OHE, X_test_OHE, y_test_OHE,
lgb.LGBMClassifier(max_depth=17, n_estimators=max_trees, learning_rate=learning_rate))
l_result.insert(0, "name", ["lgbm_trees_" + str(max_trees)])
result_trees_OHE = result_trees_OHE.append(l_result, ignore_index=True)
result_trees_OHE.set_index('name')
result_trees_OHE.sort_values("auc")[::-1]
%%time
result_rate_OHE = pd.DataFrame()
for learning_rate in log_iterator(0.1, 0.2, 1.1):
ya_result =calc_classifier(X_train_OHE, y_train_OHE, X_test_OHE, y_test_OHE,
CatBoostClassifier(logging_level='Silent', depth=7, iterations=150, learning_rate=learning_rate))
ya_result.insert(0, "name", ["ya_rate_" + str(learning_rate)])
result_rate_OHE = result_rate_OHE.append(ya_result, ignore_index=True)
for learning_rate in log_iterator(0.01, 0.1, 1.2):
l_result = calc_classifier(X_train_OHE, y_train_OHE, X_test_OHE, y_test_OHE,
lgb.LGBMClassifier(max_depth=17, n_estimators=150, learning_rate=learning_rate))
l_result.insert(0, "name", ["lgbm_rate_" + str(learning_rate)])
result_rate_OHE = result_rate_OHE.append(l_result, ignore_index=True)
result_rate_OHE.set_index('name')
result_rate_OHE.sort_values("auc")[::-1]
X_train_SC = X_train.copy()
X_test_SC = X_test.copy()
y_train_SC = y_train.copy()
y_test_SC = y_test.copy()
%%time
y_mean = y_train_SC.mean()
for i in X_train_SC:
if X_train_SC[i].dtype == 'object':
# Fit
uniq = pd.DataFrame(data=X_train_SC[i].unique(), columns=["unique"])
val = uniq.apply(lambda x: 1 if y_train_SC[X_train_SC[X_train_SC[i] == x["unique"]].index].mean() > y_mean else 0, axis=1)
uniq.insert(loc=1, column='value', value=val)
uniq = uniq.set_index("unique")
# Transform
X_train_SC[i] = X_train_SC.apply(lambda x: uniq.loc[x[i],"value"], axis=1)
X_test_SC[i] = X_test_SC.apply(lambda x: uniq.loc[x[i],"value"], axis=1)
X_train_SC = X_train_SC.select_dtypes(include=["int64", "float64", "uint8"])
X_test_SC = X_test_SC.select_dtypes(include=["int64", "float64", "uint8"])
%%time
max_trees = 100
learning_rate = 0.1
result_depth_SC = pd.DataFrame()
for depth in range(8, 16, 2):
ya_result =calc_classifier(X_train_SC, y_train_SC, X_test_SC, y_test_SC,
CatBoostClassifier(logging_level='Silent', depth=depth, iterations=max_trees, learning_rate=learning_rate))
ya_result.insert(0, "name", ["ya_depth_" + str(depth)])
result_depth_SC = result_depth_SC.append(ya_result, ignore_index=True)
for depth in range(5, 10, 2):
l_result = calc_classifier(X_train_SC, y_train_SC, X_test_SC, y_test_SC,
lgb.LGBMClassifier(max_depth=depth, n_estimators=max_trees, learning_rate=learning_rate))
l_result.insert(0, "name", ["lgbm_depth_" + str(depth)])
result_depth_SC = result_depth_SC.append(l_result, ignore_index=True)
result_depth_SC.set_index('name')
result_depth_SC.sort_values("auc")[::-1]
%%time
learning_rate = 0.1
result_trees_SC = pd.DataFrame()
for max_trees in log_int_iterator(80, 300, 1.3):
ya_result = calc_classifier(X_train_SC, y_train_SC, X_test_SC, y_test_SC,
CatBoostClassifier(logging_level='Silent', depth=8, iterations=max_trees, learning_rate=learning_rate))
ya_result.insert(0, "name", ["ya_trees_" + str(max_trees)])
result_trees_SC = result_trees_SC.append(ya_result, ignore_index=True)
for max_trees in log_int_iterator(160, 320, 1.3):
l_result = calc_classifier(X_train_SC, y_train_SC, X_test_SC, y_test_SC,
lgb.LGBMClassifier(max_depth=7, n_estimators=max_trees, learning_rate=learning_rate))
l_result.insert(0, "name", ["lgbm_trees_" + str(max_trees)])
result_trees_SC = result_trees_SC.append(l_result, ignore_index=True)
result_trees_SC.set_index('name')
result_trees_SC.sort_values("auc")[::-1]
%%time
result_rate_SC = pd.DataFrame()
for learning_rate in log_iterator(0.1, 0.2, 1.1):
ya_result = calc_classifier(X_train_SC, y_train_SC, X_test_SC, y_test_SC,
CatBoostClassifier(logging_level='Silent', depth=8, iterations=300, learning_rate=learning_rate))
ya_result.insert(0, "name", ["ya_rate_" + str(learning_rate)])
result_rate_SC = result_rate_SC.append(ya_result, ignore_index=True)
for learning_rate in log_iterator(0.01, 0.1, 1.2):
l_result = calc_classifier(X_train_SC, y_train_SC, X_test_SC, y_test_SC,
lgb.LGBMClassifier(max_depth=7, n_estimators=160, learning_rate=learning_rate))
l_result.insert(0, "name", ["lgbm_rate_" + str(learning_rate)])
result_rate_SC = result_rate_SC.append(l_result, ignore_index=True)
result_rate_SC.set_index('name')
result_rate_SC.sort_values("auc")[::-1]
CatBoost categorical
from catboost import Pool, CatBoostClassifier
categorical = np.array(X_train.select_dtypes(include=["object"]).columns)
categorical
train_dataset = Pool(data=X_train,
label=y_train,
cat_features=categorical)
eval_dataset = Pool(data=X_test,
label=y_test,
cat_features=categorical)
model = CatBoostClassifier(iterations=135,
learning_rate=0.146,
depth=7)
model.fit(train_dataset)
preds_proba = model.predict_proba(eval_dataset)[:,1]
print("Catboost pr auc", pr_auc(y_test, preds_proba))
AUC 0.223777 time 59.692731 для SC
AUC 0.225587 time 31.980033 для OHE
Стандартный метод обработки примерно похож по времени и качеству на SC
X_train_lgbm = X_train.copy()
X_test_lgbm = X_test.copy()
l_cat = "name:" + ','.join(categorical)
for i in categorical:
X_train_lgbm[i] = X_train_lgbm[i].astype('category')
X_test_lgbm[i] = X_test_lgbm[i].astype('category')
lgb_train = lgb.Dataset(X_train_lgbm, y_train)
%%time
lgb_params = {
'objective': 'binary',
'learning_rate' : 0.074,
'max_depth' : 5,
'n_estimators' : 160}
gbm = lgb.train(lgb_params,
lgb_train,
num_boost_round=100)
print("Lgbm pr auc", pr_auc(y_test, gbm.predict(X_test_lgbm)))
AUC 0.228050 time 9.101934 для SC
AUC 0.228120 time 11.166834 для OHE
Ручная обработка дала немного лучшие результаты, однако затрачивала больше времени. Возможная причина - различные гиперпараметры, подобранные для выборок без категориальных признаках и с их обработкой.
Smoth counter счетчики обрабатываются несколько быстрее чем OHE метод. Возможно это обусловлено разным количеством признаков в выборках после обработки. В то же время, оптимальные гиперпараметры подбираются разные, что говорит о разной природе данных
LightGBM и CatBoost позволяют работать с категориальными признаками, для lgbm необходимо конвертировать тип столбцов и просто передать, далее он сам разберется. Catboost принимает список категориальных столбцов и с ними работает.
Задание 5. (1 балл)
Реализуйте блендинг (получение ответов нескольких моделей и взятие их с весами (их нужно подбирать на обучающей выборке)) подобранных в предыдущем задании моделей и сравните качество.
models = {
"cat_OHE" : {"model":CatBoostClassifier(logging_level='Silent', depth=7, iterations=150, learning_rate=0.12)},
"lgbm_OHE" : {"model":lgb.LGBMClassifier(max_depth=17, n_estimators=200, learning_rate=0.074)},
"cat_SC" : {"model":CatBoostClassifier(logging_level='Silent', depth=8, iterations=300, learning_rate=0.1)},
"lgbm_SC" : {"model":lgb.LGBMClassifier(max_depth=7, n_estimators=160, learning_rate=0.062)},
}
kf = KFold(n_splits=2,shuffle=True, random_state=0)
_y_train = y_train_OHE
_y_train = _y_train.reset_index(drop=True)
for k,v in models.items():
_x_train = None
if k.endswith("_OHE"):
_x_train = X_train_OHE
else:
_x_train = X_train_SC
_x_train = _x_train.reset_index(drop=True)
for train_index, test_index in kf.split(_x_train):
begin = time()
v["model"].fit(_x_train.values[train_index], _y_train[train_index])
print(k, "fit time: ", time() - begin)
v["proba"] = v["model"].predict_proba(_x_train.values[test_index])[:,1]
v["auc"] = pr_auc(_y_train[test_index], v["proba"])
break
from sklearn.linear_model import LinearRegression
d_blend = pd.DataFrame()
for k,v in models.items():
d_blend[k] = pd.Series(v['proba'])
d_blend.head()
lr_blend = LinearRegression()
lr_blend.fit(d_blend, _y_train[test_index])
lr_blend.coef_
out = pd.DataFrame()
for k,v in models.items():
_x_test = None
if k.endswith("_OHE"):
_x_test = X_test_OHE
else:
_x_test = X_test_SC
out[k] = v["model"].predict_proba(_x_test)[:,1]
out.head()
result_predict = np.sum(out.values * 0.5, axis=1)
result_predict
_auc = pr_auc(y_test_OHE,result_predict)
_auc
result_blend = pd.DataFrame()
for k,v in models.items():
result_blend = result_blend.append(pd.DataFrame(data={"name":[k], "auc":v["auc"]}), ignore_index=True)
result_blend = result_blend.append(pd.DataFrame(data={"name":["blend"], "auc":[_auc]}), ignore_index=True)
result_blend.sort_values("auc")[::-1]
Блендинг не повысил качество
Задание 6. (1.5 балла)
В задании 3 вы подобрали гиперпараметры для LightGBM и CatBoost на вещественных признаках. Визуализируйте важности признаков, посчитанные этими алгоритмами, в виде горизонтального bar-plot (отсортируйте признаки по убыванию важности, подпишите названия признаков по оси y).
Для каждого из двух алгоритмов удалите неважные признаки (обычно по bar-plot хорошо видно порог на важность, с которого начинается хвост неважных признаков) и обучите ту же модель на получившихся данных. Сильно ли упало качество при удалении признаков, которые модель считает неважными?
import matplotlib.pyplot as plt
%matplotlib inline
_x_train = X_train.select_dtypes(include=["int64", "float64"])
_x_test = X_test.select_dtypes(include=["int64", "float64"])
%%time
clf = lgb.LGBMClassifier(max_depth=5, n_estimators=160, learning_rate=0.074)
clf.fit(_x_train, y_train)
feature_imp = pd.DataFrame(sorted(zip(clf.feature_importances_,_x_train.columns)), columns=['Value','Feature'])
print("pr-auc", pr_auc(y_test, clf.predict_proba(_x_test)[:,1]))
objects = feature_imp['Feature']
y_pos = np.arange(len(objects))
performance = feature_imp['Value']
plt.figure(figsize=(20,20))
plt.grid(True)
plt.title('Важность признаков для LGBM')
plt.barh(y_pos, performance, align='center', alpha=0.5)
plt.yticks(y_pos, objects)
plt.show()
select = feature_imp.sort_values("Value")[::-1]["Feature"][:41].values
_x_train_lgb = _x_train[select]
_x_test_lgb = _x_test[select]
%%time
clf = lgb.LGBMClassifier(max_depth=5, n_estimators=160, learning_rate=0.074)
clf.fit(_x_train_lgb, y_train)
feature_imp = pd.DataFrame(sorted(zip(clf.feature_importances_,_x_train_lgb.columns)), columns=['Value','Feature'])
print("pr-auc", pr_auc(y_test, clf.predict_proba(_x_test_lgb)[:,1]))
%%time
clf = CatBoostClassifier(max_depth=7, n_estimators=135, learning_rate=0.146)
clf.fit(_x_train, y_train)
feature_imp = pd.DataFrame(sorted(zip(clf.feature_importances_,_x_train.columns)), columns=['Value','Feature'])
print("pr-auc", pr_auc(y_test, clf.predict_proba(_x_test)[:,1]))
objects = feature_imp['Feature']
y_pos = np.arange(len(objects))
performance = feature_imp['Value']
plt.figure(figsize=(20,20))
plt.grid(True)
plt.title('Важность признаков для CatBoost')
plt.barh(y_pos, performance, align='center', alpha=0.5)
plt.yticks(y_pos, objects)
plt.show()
select = feature_imp.sort_values("Value")[::-1]["Feature"][:30].values
_x_train_lgb = _x_train[select]
_x_test_lgb = _x_test[select]
%%time
clf = lgb.LGBMClassifier(max_depth=5, n_estimators=160, learning_rate=0.074)
clf.fit(_x_train_lgb, y_train)
feature_imp = pd.DataFrame(sorted(zip(clf.feature_importances_,_x_train_lgb.columns)), columns=['Value','Feature'])
print("pr-auc", pr_auc(y_test, clf.predict_proba(_x_test_lgb)[:,1]))
После селеции качество lgbm практически не изменилось, качество же catboost'a даже несколько повысилось