XGBoost, как одно из наиболее широко используемых общедоступных программ для повышения, является важным навыком, которым должны обладать специалисты по обработке и анализу данных.
Ансамбльные модели стали стандартным инструментом прогнозного моделирования. Усиление – это общий метод создания ансамбля моделей [1]. Метод повышения был разработан почти одновременно с бэггингом. Как и бэггинг, бустинг обычно используется с деревом решений. В отличие от бэггинга, который требует небольшой работы, бустинг требует довольно большой осторожности в приложениях. Метафорически бэггинг похож на Toyota Camry, которая надежна и дешева в обслуживании, а наддув похож на Porche, который мощный, но дорогой в обслуживании.
Философия бустинга такая же, как и у других алгоритмов обучения ансамбля: использование множества моделей и использование среднего значения всех выходных данных в качестве окончательного результата прогнозирования для более высокой точности. В моделях линейной регрессии часто проверяются остатки, чтобы увидеть, можно ли улучшить соответствие. Повышение развивает эту концепцию намного дальше и подходит для ряда моделей, в которых каждая последующая модель стремится минимизировать ошибку предыдущей модели. Вот некоторые из вариантов повышения: Adaboost, повышение градиента, стохастическое повышение градиента[1].
XGBoost
Наиболее широко используемым общедоступным программным обеспечением для повышения является XGBoost, реализация стохастического повышения градиента, первоначально разработанная Тианци Ченом и Карлосом Гестерином из Вашингтонского университета [1].
В настройке XGBoost участвуют многие параметры, но наиболее важными из них являются subsample
, которые определяют долю выборок, которые будут использоваться в каждой итерации для обучения модели, и eta
, который определяет коэффициент сжатия, применяемый к весам в алгоритме повышения. Чем меньше eta
, тем меньше вероятность переобучения модели.
Тематическое исследование
Чтобы продемонстрировать применение XGBoost на практике, мы используем python для реализации бинарной классификации с использованием XGBoost. Мы будем использовать библиотеку XGBClassifier
from xgboost
. Мы будем использовать набор данных Титаника, чтобы классифицировать пассажиров как погибших или выживших. Кроме того, были добавлены еще 4 столбца, преобразованные из столбца Имя в Название1 и Название4, обозначающие мужчин и женщин в зависимости от того, были ли они женаты или нет (мистер, миссис, мастер, мисс) . Дополнительный анализ, чтобы увидеть, имеют ли женатые или, другими словами, люди с социальными обязанностями больше инстинктов выживания / или нет, и является ли тенденция одинаковой для обоих полов. Набор данных состоит из 15 предикторов, таких как пол, стоимость проезда, p_class, family_size, …. Целевой ответ сохранился. Обратите внимание, что факторные переменные, которые принимают ограниченный уровень значений, уже были преобразованы с помощью прямого кодирования. Полный код этой статьи можно найти здесь.
В целях визуализации мы будем использовать только два предиктора для прогнозирования статуса пассажиров: Age
и Fare
. В качестве первого шага мы загружаем данные и применяем классификатор. Код ниже написан для этой цели:
train_df = pd.read_csv('train_data.csv') predictors = ['Age', 'Fare'] outcome = 'Survived' X = train_df[predictors] y = train_df[outcome] xgb = XGBClassifier(objective='binary:logistic', subsample=.63, use_label_encoder=False, eval_metric='error') print(xgb.fit(X, y))
Результат будет
Как видно, параметр objective
определяет задачу обучения и соответствующую цель обучения или пользовательскую целевую функцию, которую следует использовать (см. примечание ниже). Здесь, поскольку мы установили целевую функцию на binary:logistic.
XGBoost, мы будем использовать соответствующую функцию для целей оптимизации. Подвыборка установлена на 0,63, что означает, что 63% обучающих данных используются для оптимизации. Установив eval_metric=’error’
, мы заставляем XGBoost оптимизировать целевую функцию на основе частоты ошибок двоичной классификации. Для use_label_encoder=False
используйте кодировщик меток из scikit-learn для кодирования меток. Для нового кода рекомендуется установить для этого параметра значение False.
Чтобы оценить производительность модели прогнозирования, мы собираем обучающие данные и применяем их к модели. Приведенный ниже код предсказывает статус пассажира на основе двух предикторов. Столбец Truth
отражает истинность данных.
xgb_df = X.copy() xgb_df['prediction'] = ['Survived' if p == 1 else 'Dead' for p in xgb.predict(X)] xgb_df['prob_default'] = xgb.predict_proba(X)[:, 0] xgb_df['Truth'] = ['Survived' if p == 1 else 'Dead' for p in y] print(xgb_df.head())
Результат приведен ниже:
Как видно, в первых пяти записях мы имеем один промах. Для лучшей визуализации диапазона Age
и Fare
в статусе пассажира имеем
fig, ax = plt.subplots(figsize=(16, 14)) xgb_df.loc[xgb_df.prediction=='Dead'].plot(x='Age', y='Fare', style='*', markerfacecolor='none', markeredgecolor='C1', ax=ax) xgb_df.loc[xgb_df.prediction=='Survived'].plot( x='Age', y='Fare', style='o', markerfacecolor='none', markeredgecolor='C0', ax=ax) ax.legend(['Dead', 'Survived']); ax.set_ylim(0, 0.6) ax.set_xlabel('Age') ax.set_ylabel('Fare') plt.tight_layout() plt.show()
Результат будет
Прогнозируемые значения представлены синими и оранжевыми цветовыми метками.
Регуляризация: избежание переобучения
Слепое применение xgboost может привести к нестабильности моделей в результате переобучения данных обучения. Чтобы избежать переобучения, можно применить регуляризацию, чтобы учесть сложность.
В xgboost можно изменить функцию стоимости, добавив член, который измеряет сложность модели. В xgboost есть два параметра для регуляризации модели: альфа и лямбда, которые соответствуют манхэттенскому расстоянию (L1-регуляризация) и квадрату евклидова расстояния (L2-регуляризация) соответственно [1]. Мы установим reg_lambda
in xgboost для применения регулирования L2.
test_df = pd.read_csv('test_data.csv') predictors = ['Sex', 'Age', 'Fare', 'Pclass_1','Pclass_2', 'Pclass_3', 'Family_size', 'Title_1', 'Title_2', 'Title_3', 'Title_4', 'Emb_1', 'Emb_2', 'Emb_3'] outcome = 'Survived' train_X = train_df[predictors] train_y = train_df[outcome] valid_X = test_df[predictors] valid_y = test_df[outcome] xgb_default = XGBClassifier(objective='binary:logistic', n_estimators=250, max_depth=6, reg_lambda=0, learning_rate=0.1, subsample=1, use_label_encoder=False, eval_metric='error') xgb_default.fit(train_X, train_y) xgb_penalty = XGBClassifier(objective='binary:logistic', n_estimators=250, max_depth=6, reg_lambda=1000, learning_rate=0.1, subsample=0.63, use_label_encoder=False, eval_metric='error') results = [] for ntree_limit in range(1, 250): train_default = xgb_default.predict_proba(train_X, ntree_limit=ntree_limit)[:, 1] train_penalty = xgb_penalty.predict_proba(train_X, ntree_limit=ntree_limit)[:, 1] pred_default = xgb_default.predict_proba(valid_X, ntree_limit=ntree_limit)[:, 1] pred_penalty = xgb_penalty.predict_proba(valid_X, ntree_limit=ntree_limit)[:, 1] results.append({ 'iterations': ntree_limit, 'default train': np.mean(abs(train_y - train_default) > 0.5), 'penalty train': np.mean(abs(train_y - train_penalty) > 0.5), 'default test': np.mean(abs(valid_y - pred_default) > 0.5), 'penalty test': np.mean(abs(valid_y - pred_penalty) > 0.5), }) results = pd.DataFrame(results) ax = results.plot(x='iterations', y='default test') results.plot(x='iterations', y='penalty test', ax=ax) results.plot(x='iterations', y='default train', ax=ax) results.plot(x='iterations', y='penalty train', ax=ax) plt.show()
Как видно, по мере увеличения итерации ошибка для обученных данных уменьшается, а тест увеличивается. Это может быть связано с неправильной настройкой параметра регуляризации. Мы можем решить эту проблему с помощью перекрестной проверки.
Гиперпараметры и перекрестная проверка
Мы можем перебирать различные значения гиперпараметров и выбирать те, которые имеют наименьшую ошибку проверки. Код ниже будет служить этой цели:
idx = np.random.choice(range(5), size=len(X), replace=True) error = [] for eta, max_depth in product([0.1, 0.5, 0.9], [3, 6, 9]): xgb = XGBClassifier(objective='binary:logistic', n_estimators=250, max_depth=max_depth, learning_rate=eta, use_label_encoder=False, eval_metric='error') cv_error = [] for k in range(5): fold_idx = idx == k train_X = X.loc[~fold_idx]; train_y = y[~fold_idx] valid_X = X.loc[fold_idx]; valid_y = y[fold_idx] xgb.fit(train_X, train_y) pred = xgb.predict_proba(valid_X)[:, 1] cv_error.append(np.mean(abs(valid_y - pred) > 0.5)) error.append({ 'eta': eta, 'max_depth': max_depth, 'avg_error': np.mean(cv_error) }) print(error[-1]) errors = pd.DataFrame(error) print(errors.pivot_table(index='eta', columns='max_depth', values='avg_error') * 100)
Вывод для разных значений гиперпараметров:
Как видно из таблицы выше, минимальная ошибка приходится на eta=0.1
и max_depth=3
.
Ссылка
[1] Брюс, Питер, Эндрю Брюс и Питер Гедек. Практическая статистика для специалистов по данным: более 50 основных концепций использования R и Python. О'Рейли Медиа, 2020.