使用 Scikit-Learn 估计器接口

目录

概述

除了原生接口外,XGBoost 还提供了一个符合 sklearn 估计器指南 的 sklearn 估计器接口。它支持回归、分类和学习排序。sklearn 估计器接口的生存训练仍在进行中。

你可以在 使用 sklearn 接口的示例集合 找到一些快速开始的示例。使用 sklearn 接口的主要优势是它与 sklearn 提供的多数实用工具兼容,例如 sklearn.model_selection.cross_validate()。此外,由于其流行性,许多其他库也识别 sklearn 估计器接口。

通过 sklearn 估计器接口,我们只需几行 Python 代码就可以训练一个分类模型。以下是一个训练分类模型的示例:

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split

import xgboost as xgb

X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, random_state=94)

# Use "hist" for constructing the trees, with early stopping enabled.
clf = xgb.XGBClassifier(tree_method="hist", early_stopping_rounds=2)
# Fit the model, test sets are used for early stopping.
clf.fit(X_train, y_train, eval_set=[(X_test, y_test)])
# Save model into JSON format.
clf.save_model("clf.json")

tree_method 参数指定用于构建树的方法,而 early_stopping_rounds 参数启用提前停止。提前停止可以帮助防止过拟合并节省训练时间。

早停

如前例所示,可以通过参数 early_stopping_rounds 启用提前停止。或者,可以使用回调函数 xgboost.callback.EarlyStopping 来指定提前停止行为的更多细节,包括 XGBoost 是否应返回最佳模型而不是完整的树堆栈:

early_stop = xgb.callback.EarlyStopping(
    rounds=2, metric_name='logloss', data_name='validation_0', save_best=True
)
clf = xgb.XGBClassifier(tree_method="hist", callbacks=[early_stop])
clf.fit(X_train, y_train, eval_set=[(X_test, y_test)])

目前,XGBoost 在估计器内部没有实现数据分割逻辑,而是依赖于 xgboost.XGBModel.fit() 方法的 eval_set 参数。如果你想使用早停来防止过拟合,你需要使用 sklearn 库中的 sklearn.model_selection.train_test_split() 函数手动将数据分割为训练集和测试集。其他一些机器学习算法,如 sklearn 中的算法,将早停作为估计器的一部分,并且可能与交叉验证一起工作。然而,在交叉验证期间使用早停可能不是一个完美的方法,因为它会改变每个验证折叠的模型树的数量,导致不同的模型。更好的方法是,在交叉验证后使用最佳超参数和早停重新训练模型。如果你想尝试使用早停进行交叉验证的想法,这里有一个代码片段可以开始:

from sklearn.base import clone
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import StratifiedKFold, cross_validate

import xgboost as xgb

X, y = load_breast_cancer(return_X_y=True)


def fit_and_score(estimator, X_train, X_test, y_train, y_test):
    """Fit the estimator on the train set and score it on both sets"""
    estimator.fit(X_train, y_train, eval_set=[(X_test, y_test)])

    train_score = estimator.score(X_train, y_train)
    test_score = estimator.score(X_test, y_test)

    return estimator, train_score, test_score


cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=94)

clf = xgb.XGBClassifier(tree_method="hist", early_stopping_rounds=3)

results = {}

for train, test in cv.split(X, y):
    X_train = X[train]
    X_test = X[test]
    y_train = y[train]
    y_test = y[test]
    est, train_score, test_score = fit_and_score(
        clone(clf), X_train, X_test, y_train, y_test
    )
    results[est] = (train_score, test_score)

获取原生助推器对象

sklearn 估计器接口主要便于训练,并没有实现 XGBoost 中的所有功能。例如,为了获得缓存的预测,需要使用 xgboost.DMatrixxgboost.Booster.predict()。可以通过 xgboost.XGBModel.get_booster() 从 sklearn 接口获取 booster 对象。

booster = clf.get_booster()
print(booster.num_boosted_rounds())

预测

当启用早停时,包括 xgboost.XGBModel.predict()xgboost.XGBModel.score()xgboost.XGBModel.apply() 方法在内的预测函数将自动使用最佳模型。这意味着 xgboost.XGBModel.best_iteration 用于指定预测中使用的树的范围。

要为增量预测获取缓存结果,请使用 xgboost.Booster.predict() 方法。

并行线程数

在使用 XGBoost 和其他 sklearn 工具时,你可以通过使用 n_jobs 参数来指定要使用的线程数。默认情况下,XGBoost 会使用计算机上所有可用的线程,这在与 sklearn.model_selection.cross_validate() 等其他 sklearn 函数结合使用时,可能会导致一些有趣的后果。如果 XGBoost 和 sklearn 都设置为使用所有线程,你的计算机可能会由于所谓的“线程抖动”而显著变慢。为了避免这种情况,你可以简单地将 XGBoost 的 n_jobs 参数设置为 None`(使用所有线程),并将 sklearn 的 ``n_jobs` 参数设置为 1。这样,两个程序将能够顺利协同工作,而不会造成不必要的计算机负担。