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.