开发预测模型的目标是开发一个在未知数据上准确的模型。
这可以通过使用统计技术来实现,其中训练数据集被仔细用于估计模型在新和未知数据上的性能。
在本教程中,您将学习如何在 Python 中使用 XGBoost 评估您的梯度提升模型的性能。
完成本教程后,您将了解。
- 如何使用训练集和测试集评估 XGBoost 模型的性能。
- 如何使用 k 折交叉验证评估 XGBoost 模型的性能。
通过我的新书《XGBoost With Python》启动您的项目,其中包括所有示例的分步教程和 Python 源代码文件。
让我们开始吧。
- 2017 年 1 月更新:已更新以反映 scikit-learn API 0.18.1 版本中的更改。
- **2018 年 3 月更新**:添加了下载数据集的备用链接,因为原始链接似乎已被删除。

如何在 Python 中使用 XGBoost 评估梯度提升模型
图片由 Timitrius 提供,保留部分权利。
在 Python 中使用 XGBoost 需要帮助吗?
参加我的免费 7 天电子邮件课程,探索 xgboost(含示例代码)。
立即点击注册,还将免费获得本课程的 PDF 电子书版本。
使用训练集和测试集评估 XGBoost 模型
我们可以用来评估机器学习算法性能的最简单方法是使用不同的训练集和测试数据集。
我们可以将原始数据集分成两部分。在第一部分上训练算法,然后在第二部分上进行预测,并根据预期结果评估预测。
划分的大小可能取决于数据集的大小和具体情况,尽管通常使用 67% 的数据进行训练,其余 33% 用于测试。
这种算法评估技术速度很快。它非常适合大型数据集(数百万条记录),并且有充分证据表明数据的两个划分都代表了潜在问题。由于速度快,当您正在研究的算法训练缓慢时,使用此方法很有用。
这种技术的一个缺点是它可能具有高方差。这意味着训练集和测试数据集中的差异可能导致模型准确性估计的显著差异。
我们可以使用 scikit-learn 库中的 train_test_split() 函数将数据集分成训练集和测试集。例如,我们可以将数据集分成 67% 用于训练和 33% 用于测试,如下所示
1 2 |
# 将数据拆分为训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.33, random_state=7) |
完整的代码列表如下所示,使用了 Pima Indians 糖尿病发病数据集,假设其位于当前工作目录中。
下载数据集并将其放置在您的当前工作目录中。
一个默认配置的 XGBoost 模型在训练数据集上拟合,并在测试数据集上评估。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# train-test split evaluation of xgboost model 从 numpy 导入 loadtxt from xgboost import XGBClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score # 加载数据 dataset = loadtxt('pima-indians-diabetes.csv', delimiter=",") # 将数据拆分为 X 和 y X = dataset[:,0:8] Y = dataset[:,8] # 将数据拆分为训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.33, random_state=7) # 拟合模型,无训练数据 model = XGBClassifier() model.fit(X_train, y_train) # 对测试数据进行预测 y_pred = model.predict(X_test) predictions = [round(value) for value in y_pred] # 评估预测 accuracy = accuracy_score(y_test, predictions) print("Accuracy: %.2f%%" % (accuracy * 100.0)) |
注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能会有所不同。考虑多次运行示例并比较平均结果。
运行此示例总结了模型在测试集上的性能。
1 |
准确率:77.95% |
使用 k 折交叉验证评估 XGBoost 模型
交叉验证是一种可以用来估计机器学习算法性能的方法,其方差比单个训练集-测试集划分要小。
它的工作原理是将数据集分成 k 个部分(例如 k=5 或 k=10)。数据的每个部分称为一个折叠。算法在 k-1 个折叠上训练,一个折叠保留下来并在保留的折叠上测试。重复此过程,以便数据集的每个折叠都有机会成为保留的测试集。
运行交叉验证后,您将得到 k 个不同的性能分数,您可以使用平均值和标准差来总结这些分数。
结果是对算法在给定测试数据上的新数据性能的更可靠估计。它更准确,因为算法在不同的数据上多次训练和评估。
k 的选择必须允许每个测试分区的大小足够大,以便成为问题的合理样本,同时允许足够多的算法训练-测试评估重复,以提供对算法在未见数据上性能的公平估计。对于数千或数万个观测值的适中大小数据集,k 值为 3、5 和 10 是常见的。
我们可以使用 scikit-learn 中提供的 k 折交叉验证支持。首先,我们必须创建 KFold 对象,指定折叠数和数据集大小。然后,我们可以将此方案与特定数据集一起使用。scikit-learn 中的 cross_val_score() 函数允许我们使用交叉验证方案评估模型,并返回在每个折叠上训练的每个模型的得分列表。
1 2 |
kfold = KFold(n_splits=10, random_state=7) results = cross_val_score(model, X, Y, cv=kfold) |
以下是使用 k 折交叉验证评估 XGBoost 模型的完整代码列表,以供参考。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# k-fold cross validation evaluation of xgboost model 从 numpy 导入 loadtxt import xgboost from sklearn.model_selection import KFold from sklearn.model_selection import cross_val_score # 加载数据 dataset = loadtxt('pima-indians-diabetes.csv', delimiter=",") # 将数据拆分为 X 和 y X = dataset[:,0:8] Y = dataset[:,8] # CV model model = xgboost.XGBClassifier() kfold = KFold(n_splits=10, random_state=7) results = cross_val_score(model, X, Y, cv=kfold) print("Accuracy: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100)) |
注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能会有所不同。考虑多次运行示例并比较平均结果。
运行此示例总结了默认模型配置在数据集上的性能,包括平均值和标准差分类准确率。
1 |
准确率:76.69% (7.11%) |
如果您的分类预测建模问题有许多类别,或者类别不平衡(一个类别的实例远多于另一个类别),那么在执行交叉验证时创建分层折叠是一个好主意。
这在执行交叉验证评估时,会强制每个折叠中的类别分布与整个训练数据集中的分布相同。scikit-learn 库在 StratifiedKFold 类中提供了此功能。
下面是修改后的相同示例,使用分层交叉验证来评估 XGBoost 模型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# 分层 k 折交叉验证评估 XGBoost 模型 从 numpy 导入 loadtxt import xgboost from sklearn.model_selection import StratifiedKFold from sklearn.model_selection import cross_val_score # 加载数据 dataset = loadtxt('pima-indians-diabetes.csv', delimiter=",") # 将数据拆分为 X 和 y X = dataset[:,0:8] Y = dataset[:,8] # CV model model = xgboost.XGBClassifier() kfold = StratifiedKFold(n_splits=10, random_state=7) results = cross_val_score(model, X, Y, cv=kfold) print("Accuracy: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100)) |
注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能会有所不同。考虑多次运行示例并比较平均结果。
运行此示例将产生以下输出。
1 |
准确率:76.95% (5.88%) |
何时使用何种技术
- 通常,k 折交叉验证是评估机器学习算法在未知数据上性能的黄金标准,其中 k 设置为 3、5 或 10。
- 当类别数量众多或每个类别的实例不平衡时,使用分层交叉验证来强制执行类别分布。
- 当使用慢速算法时,使用训练/测试划分有助于提高速度,并且在使用大型数据集时会产生偏差较低的性能估计。
最好的建议是进行实验,为您的问题找到一种快速且能产生合理性能估计的技术,以便您可以做出决策。
如有疑问,回归问题使用 10 折交叉验证,分类问题使用分层 10 折交叉验证。
总结
在本教程中,您学习了如何通过估计 XGBoost 模型在未见数据上的预期表现来评估它们。
具体来说,你学到了:
- 如何将数据集分成训练集和测试子集,用于训练和评估模型的性能。
- 如何在一个数据集的不同子集上创建 k 个 XGBoost 模型,并对分数求平均以获得更稳健的模型性能估计。
- 帮助您为问题选择训练-测试划分和 k 折交叉验证的启发式方法。
您对如何评估 XGBoost 模型的性能或本帖有什么疑问吗?请在下面的评论中提出您的问题,我将尽力回答。
嗨,Jason,
感谢这篇文章。您没有提及留一交叉验证方法。
它的逻辑是否与 k 折交叉验证相同(除了测试集的大小为 1)?
对于小型数据集(大约 2000 行),您会推荐使用留一交叉验证还是 k 折交叉验证?
此致,
艾格尼丝
你好,艾格尼丝,
是的,它类似于 1 折交叉验证,针对数据集中的每个模式重复进行。
根据我的阅读,您最好使用 k 折交叉验证。
你好 Jason,如何找到 XGBRegressor 模型的准确性?
您无法计算回归算法的准确性。没有类别。您必须计算均方误差等误差。
请问能否展示一下具体的代码行?
谢谢你
你好 Nader,
你可以使用 XGBRegressor 而不是 XGBClassifier 来解决回归问题
https://docs.xgboost.com.cn/en/latest/python/python_api.html#xgboost.XGBRegressor
嗨,Jason,
使用 cross_val_score 是否已经拟合了模型,使其可以提供预测?
谢谢,
瓦希姆
我建议在所有数据上拟合最终模型,并使用它进行预测。请参阅此帖子了解一般思路
https://machinelearning.org.cn/train-final-machine-learning-model/
感谢您的教程。我还在研究中,但可以说它比其他教程更容易理解。
谢谢,听到这个我很高兴。
嗨,Jason,
感谢这篇教程,它简单明了。
我正在处理不平衡数据集 (1:9) 分类问题。它与 XGBClassifier() 配合得很好,并使用 k 折验证进行了很好的评估。
非常感谢!
干得好!
嗨,Jason,
在您的示例中——您会在哪里实施早期停止?
这篇文章可能会有帮助
https://machinelearning.org.cn/avoid-overfitting-by-early-stopping-with-xgboost-in-python/
感谢 Jason 对整个过程的详尽解释。
我很高兴它能帮到你。
你好 Jason Brownlee,
你最近怎么样?
完成交叉验证后,如何获得最佳模型来对我的测试数据进行分类?
选择给出最佳结果的配置,然后在所有可用数据上拟合最终模型。
谢谢,Jason,教程很有帮助。
但是,我在处理不平衡数据集(1:15)分类问题时遇到了困难。模型最初使用 XGBClassifier() 效果很好,训练集的 AUC 为 0.911,测试集的 AUC 为 0.949。然后,在我使用 GridSearchCV 调整超参数(max_depth、min_child_weight、gamma)后,训练集和测试集的 AUC 明显下降(0.892 和 0.917)。我感到非常困惑。有没有什么线索可以解释为什么会发生这种情况?
也许调整参数降低了模型的容量。也许可以继续调整项目?
我使用了大卖场数据集并将数据分成训练集、测试集,然后我执行了 model.fit(x_train, y_train);其中我的模型是 XGBClassifier(),它成功执行。
但是当我执行 y_pred = model.predict(X_test) 时,它会给出一个特征名称不匹配的错误,如下所示:
ValueError 回溯 (最近一次调用)
in ()
1 # 对测试数据进行预测
—-> 2 y_pred = model.predict(X_test)
3 predictions = [round(value) for value in y_pred]
4 # 评估预测
5 accuracy = accuracy_score(y_test, predictions)
/home/gopal/.local/lib/python2.7/site-packages/xgboost/sklearn.pyc in predict(self, data, output_margin, ntree_limit, validate_features)
770 output_margin=output_margin,
771 ntree_limit=ntree_limit,
–> 772 validate_features=validate_features)
773 if output_margin
774 # 如果 output_margin 为活动状态,则直接返回分数
/home/gopal/.local/lib/python2.7/site-packages/xgboost/core.pyc in predict(self, data, output_margin, ntree_limit, pred_leaf, pred_contribs, approx_contribs, pred_interactions, validate_features)
1283
1284 if validate_features
-> 1285 self._validate_features(data)
1286
1287 length = c_bst_ulong()
/home/gopal/.local/lib/python2.7/site-packages/xgboost/core.pyc in _validate_features(self, data)
1690
1691 raise ValueError(msg.format(self.feature_names,
-> 1692 data.feature_names))
1693
1694 def get_split_value_histogram(self, feature, fmap=”, bins=None, as_pandas=True)
ValueError: feature_names mismatch: [‘f0’, ‘f1’, ‘f2’, ‘f3’, ‘f4’, ‘f5’, ‘f6’, ‘f7’, ‘f8’, ‘f9’, ‘f10’, ‘f11′] [u’Item_Fat_Content’, u’Item_Visibility’, u’Item_Type’, u’Item_MRP’, u’Outlet_Size’, u’Outlet_Location_Type’, u’Outlet_Type’, u’Outlet_Years’, u’Item_Visibility_MeanRatio’, u’Outlet’, u’Identifier’, u’Item_Weight’]
输入数据中预期存在 f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11
训练数据不包含以下字段:Outlet_Years, Outlet_Size, Item_Visibility, Item_MRP, Item_Visibility_MeanRatio, Outlet_Location_Type, Item_Weight, Item_Type, Outlet, Identifier, Outlet_Type, Item_Fat_Content
或许可以确认这两个数据集具有相同的列?
我的训练集和测试集包含浮点值,但是当我使用分类器进行预测时,它说不支持连续值。
这很奇怪。也许仔细检查您的数据是否正确加载?
你好 Jason,对于 XBGRegressor,我从 Big Mart 数据集得到了 RMSE = 1043,我得到的最佳分数是 0.59974,所以我可以使用最佳分数作为我的准确性吗,因为 RMSE 值看起来非常大,请建议。
这是我在这里回答的一个常见问题
https://machinelearning.org.cn/faq/single-faq/how-to-know-if-a-model-has-good-performance
嗨,Jason,
我刚发现这个很棒的博客。我仍然对使用 XGBoost 有一些疑问。我不知道我是否可以向您寻求帮助。
我是 XGBoost 的新手。使用 XGBClassifier 构建模型。我使用了 GridSearchCV 来创建一个调整网格以找到最佳超参数,并且我已经得到了我的最终模型。我使用“auc”作为我的分类指标。我的问题是,我使用
yPred = model.predict(Xtest),
但结果 (yPred) 是从 0 到 1 的浮点值。我如何决定将这些值映射到 0 和 1 的阈值?
我看到您使用了 round(value),这相当于将阈值设置为 0.5,我想。我的模型有没有什么规则需要遵循才能找到阈值?我期待您的回复。非常感谢。
诚挚地,
丹尼
诚挚地,
王一林
谢谢!
如果您使用 ROC AUC,您可以直接使用达到最佳 F-measure 或 J-metric 的阈值。
如果不确定,请针对 F-measure 分数测试 ROC 曲线中的每个阈值。
希望这能有所帮助。
嗨 Jason
感谢您的教程。
本教程基于 Sklearn API,您有没有在 XGBoost 的原生 API 中进行分层 K 折交叉验证的例子?
谢谢
抱歉,我没有使用原生 API 的教程。
你好 Jason,
感谢这篇教程。有没有办法查看每次验证的混淆矩阵?
谢谢。
不,通常混淆矩阵是为单个保留数据集计算的。