使用 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)

获取原生 booster 对象

sklearn 估计器接口主要用于训练,并未实现 XGBoost 中的所有功能。例如,为了获得缓存预测结果,需要结合 xgboost.DMatrix 使用 xgboost.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。这样,两个程序就能顺利协同工作,而不会对计算机造成不必要的压力。