H5W3
当前位置:H5W3 > 其他技术问题 > 正文

在Python中使用XGBoost

本文概述

众所周知, XGBoost提供了比其他机器学习算法更好的解决方案。实际上, 自诞生以来, 它已成为处理结构化数据的”最新”机器学习算法。

在本教程中, 你将学习使用python中的XGBoost构建机器学习模型。更具体地说, 你将学习:

  • 什么是Boosting, 以及XGBoost的运作方式。
  • 如何将XGBoost应用于数据集并验证结果。
  • 有关可以在XGBoost中进行调整以改善模型性能的各种超参数。
  • 如何可视化增强树和特征重要性

但是, 什么使XGBoost如此受欢迎?

  • 速度和性能:最初是用C ++编写的, 它比其他整体分类器要快。
  • 核心算法是可并行化的:因为核心XGBoost算法是可并行化的, 所以它可以利用多核计算机的功能。它还可以并行化到GPU上以及跨计算机网络, 从而也可以在非常大的数据集上进行训练。
  • 始终优于其他算法方法:在各种机器学习基准数据集上均显示出更好的性能。
  • 各种各样的调整参数:XGBoost内部具有用于交叉验证, 正则化, 用户定义的目标函数, 缺失值, 树参数, 与scikit-learn兼容的API等参数。

XGBoost(极端梯度增强)属于增强算法家族, 其核心使用梯度增强(GBM)框架。这是一个优化的分布式梯度提升库。但是, 等等, 正在促进什么?好吧, 继续阅读。

增强

增强是一种基于合奏原理的顺序技术。它结合了一组学习能力较弱的人, 并提高了预测准确性。在任何时刻t, 模型结果都基于先前时刻t-1的结果进行加权。正确预测的结果的权重较低, 而未分类的结果的权重较高。请注意, 学习能力较弱的人比随机猜测的人略好。例如, 决策树的预测略高于50%。让我们用一个简单的例子来了解一般的提升。

在Python中使用XGBoost2

上面显示的四个分类器(在4个方框中)正尝试尽可能均匀地对+和-类进行分类。

1.方框1:第一个分类器(通常是决策树桩)在D1处创建一条垂直线(分割线)。它说D1左边的任何东西都是+, D1右边的任何东西都是-。但是, 该分类器对三个+点进行了错误分类。

请注意, 决策树桩是仅在一个级别拆分的决策树模型, 因此最终预测仅基于一个功能。

2.方框2:第二个分类器将更多的权重分配给三个+错误分类的点(请参见+的较大尺寸), 并在D2处创建一条垂直线。它再次说, D2右边的任何东西都是-, 而左边的是+。尽管如此, 它仍会通过错误地将三点分类而犯错误。

3.方框3:同样, 第三个分类器对三个错误分类的点给予了更大的权重, 并在D3处创建了一条水平线。尽管如此, 该分类器仍无法正确分类(在圆圈中)点。

4.方框4:这是弱分类器的加权组合(方框1, 2和3)。如你所见, 它在正确分类所有点方面做得很好。

那就是增强算法背后的基本思想是建立一个弱模型, 得出各种特征重要性和参数的结论, 然后使用这些结论建立一个新的, 更强的模型并利用先前模型的错误分类错误并尝试减少它。现在, 让我们进入XGBoost。首先, 你应该了解XGBoost的默认基础学习者:树合奏。树集成模型是一组分类树和回归树(CART)。一棵又一棵地生长, 并在随后的迭代中尝试降低错误分类率。这是一个CART的简单示例, 该示例可以根据XGBoost的文档对是否有人喜欢计算机游戏进行分类。

如果在”树组合”部分中检查图像, 你会注意到每棵树根据其所看到的数据给出不同的预测分数, 并且将每棵树的分数相加得出最终分数。

在本教程中, 你将使用XGBoost解决回归问题。数据集来自UCI机器学习存储库, 并且也存在于sklearn的数据集模块中。它有14个解释变量来描述波士顿住宅的各个方面, 所面临的挑战是预测每1000美元拥有者所拥有房屋的中位数。

在Python中使用XGBoost

首先, 就像处理其他数据集一样, 你将要导入Boston Housing数据集并将其存储在一个名为boston的变量中。要从scikit-learn导入它, 你将需要运行此代码段。

from sklearn.datasets import load_boston
boston = load_boston()

波士顿变量本身是一个字典, 因此你可以使用.keys()方法检查其键。

print(boston.keys())
dict_keys(['data', 'target', 'feature_names', 'DESCR'])

你可以使用boston.data.shape属性轻松检查其形状, 该属性将返回数据集的大小。

print(boston.data.shape)
(506, 13)

如你所见, 它返回了(506, 13), 这意味着有506行数据和13列。现在, 如果你想知道这13列是什么, 只需使用.feature_names属性, 它将返回要素名称。

print(boston.feature_names)
['CRIM' 'ZN' 'INDUS' 'CHAS' 'NOX' 'RM' 'AGE' 'DIS' 'RAD' 'TAX' 'PTRATIO'
 'B' 'LSTAT']

数据集的描述在数据集本身中可用。你可以使用.DESCR进行查看。

print(boston.DESCR)
Boston House Prices dataset
===========================

Notes
------
Data Set Characteristics:  

    :Number of Instances: 506

    :Number of Attributes: 13 numeric/categorical predictive

    :Median Value (attribute 14) is usually the target

    :Attribute Information (in order):
        - CRIM     per capita crime rate by town
        - ZN       proportion of residential land zoned for lots over 25, 000 sq.ft.
        - INDUS    proportion of non-retail business acres per town
        - CHAS     Charles River dummy variable (= 1 if tract bounds river; 0 otherwise)
        - NOX      nitric oxides concentration (parts per 10 million)
        - RM       average number of rooms per dwelling
        - AGE      proportion of owner-occupied units built prior to 1940
        - DIS      weighted distances to five Boston employment centres
        - RAD      index of accessibility to radial highways
        - TAX      full-value property-tax rate per $10, 000
        - PTRATIO  pupil-teacher ratio by town
        - B        1000(Bk - 0.63)^2 where Bk is the proportion of blacks by town
        - LSTAT    % lower status of the population
        - MEDV     Median value of owner-occupied homes in $1000's

    :Missing Attribute Values: None

    :Creator: Harrison, D. and Rubinfeld, D.L.

This is a copy of UCI ML housing dataset.
http://archive.ics.uci.edu/ml/datasets/Housing


This dataset was taken from the StatLib library which is maintained at Carnegie Mellon University.

The Boston house-price data of Harrison, D. and Rubinfeld, D.L. 'Hedonic
prices and the demand for clean air', J. Environ. Economics & Management, vol.5, 81-102, 1978.   Used in Belsley, Kuh & Welsch, 'Regression diagnostics
...', Wiley, 1980.   N.B. Various transformations are used in the table on
pages 244-261 of the latter.

The Boston house-price data has been used in many machine learning papers that address regression
problems.   

**References**

   - Belsley, Kuh & Welsch, 'Regression diagnostics: Identifying Influential Data and Sources of Collinearity', Wiley, 1980. 244-261.
   - Quinlan, R. (1993). Combining Instance-Based and Model-Based Learning. In Proceedings on the Tenth International Conference of Machine Learning, 236-243, University of Massachusetts, Amherst. Morgan Kaufmann.
   - many more! (see http://archive.ics.uci.edu/ml/datasets/Housing)

现在, 将其转换为pandas DataFrame!为此, 你需要导入熊猫库并调用传递参数boston.data的DataFrame()函数。要标记列的名称, 请使用pandas DataFrame的.columnns属性, 并将其分配给boston.feature_names。

import pandas as pd

data = pd.DataFrame(boston.data)
data.columns = boston.feature_names

通过在熊猫DataFrame上使用head()方法浏览数据集的前5行。

data.head()
在Python中使用XGBoost3

你会注意到, DataFrame中没有名为PRICE的列。这是因为目标列在另一个名为boston.target的属性中可用。将boston.target附加到你的pandas DataFrame。

data['PRICE'] = boston.target

在你的DataFrame上运行.info()方法, 以获取有关数据的有用信息。

data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 506 entries, 0 to 505
Data columns (total 14 columns):
CRIM       506 non-null float64
ZN         506 non-null float64
INDUS      506 non-null float64
CHAS       506 non-null float64
NOX        506 non-null float64
RM         506 non-null float64
AGE        506 non-null float64
DIS        506 non-null float64
RAD        506 non-null float64
TAX        506 non-null float64
PTRATIO    506 non-null float64
B          506 non-null float64
LSTAT      506 non-null float64
PRICE      506 non-null float64
dtypes: float64(14)
memory usage: 55.4 KB

事实证明, 该数据集具有14列(包括目标变量PRICE)和506行。注意, 这些列是浮点数据类型的, 指示仅存在连续特征, 而在任何列中都没有缺失值。为了获得有关数据集中不同功能的更多摘要统计信息, 你将在DataFrame上使用describe()方法。

请注意, describe()仅给出本质上是连续的而不是分类的列的摘要统计信息。

data.describe()
在Python中使用XGBoost4

如果你打算在具有分类特征的数据集上使用XGBoost, 则可能需要在训练模型之前考虑对这些特征应用一些编码(例如”单热”编码)。另外, 如果数据集中有一些缺失值(例如NA), 则可能会或可能不会对其进行单独处理, 因为XGBoost能够在内部处理缺失值。如果你想了解更多信息, 可以查看此链接。

现在, 无需深入研究探索性分析和特征工程, 你将专注于应用算法在此数据上训练模型。

你将使用XGBoost的scikit-learn兼容API使用Trees作为基础学习者(默认的基础学习者)来构建模型。在此过程中, 你还将学习XGBoost提供的一些常用调整参数, 以改善模型的性能, 并使用均方根误差(RMSE)性能度量来检查训练后模型在测试集上的性能。均方根误差是实际值和预测值之间平方差的均方根。像往常一样, 首先要导入库xgboost和其他将用于构建模型的重要库。

请注意, 你可以在cmd上使用pip install xgboost在系统上安装xgboost之类的python库。

import xgboost as xgb
from sklearn.metrics import mean_squared_error
import pandas as pd
import numpy as np

使用.iloc分隔目标变量和其余变量以子集数据。

X, y = data.iloc[:, :-1], data.iloc[:, -1]

现在, 你将数据集转换为XGBoost支持的称为Dmatrix的优化数据结构, 并为其提供了令人赞叹的性能和效率提升。你将在本教程的后面部分中使用它。

data_dmatrix = xgb.DMatrix(data=X, label=y)

XGBoost的超参数

此时, 在构建模型之前, 你应该了解XGBoost提供的调整参数。好吧, XGBoost中有很多针对基于树的学习者的调整参数, 你可以在此处阅读有关它们的全部信息。但是, 你应该知道的最常见的是:

  • learning_rate:用于防止过度拟合的步长收缩。范围是[0, 1]
  • max_depth:确定在任何增强回合中允许每棵树生长的深度。
  • 子样本:每棵树使用的样本百分比。较低的值可能导致拟合不足。
  • colsample_bytree:每棵树使用的功能的百分比。较高的值可能导致过度拟合。
  • n_estimators:你要构建的树数。
  • 目标:确定要使用的损失函数, 例如reg:线性表示回归问题, reg:逻辑表示仅决策的分类问题, 二进制:逻辑表示具有概率的分类问题。

XGBoost还支持正则化参数, 以在模型变得更加复杂时对其进行惩罚, 并将其简化为简单(简约)模型。

  • gamma:根据拆分后预期的损失减少, 控制给定节点是否拆分。较高的值导致较少的分割。仅支持基于树的学习者。
  • alpha:叶权重的L1正则化。较大的值导致更正规化。
  • lambda:L2正则化在叶子权重上比L1正则化更平滑。

还值得一提的是, 尽管你使用树作为基础学习器, 但是你也可以使用XGBoost相对较不流行的线性基础学习器和另一种称为dart的树学习器。你所要做的就是将booster参数设置为gbtree(默认), gblinear或dart。

现在, 你将使用来自sklearn的model_selection模块的train_test_split函数创建test和test集合, 以交叉验证结果, test_size的大小等于数据的20%。同样, 为了保持结果的可重复性, 还分配了random_state。

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=123)

下一步是通过使用传递为参数的超参数调用XGBoost库中的XGBRegressor()类来实例化XGBoost回归对象。对于分类问题, 你应该使用XGBClassifier()类。

xg_reg = xgb.XGBRegressor(objective ='reg:linear', colsample_bytree = 0.3, learning_rate = 0.1, max_depth = 5, alpha = 10, n_estimators = 10)

使回归变量适合训练集, 并使用熟悉的.fit()和.predict()方法对测试集进行预测。

xg_reg.fit(X_train, y_train)

preds = xg_reg.predict(X_test)

通过调用sklearn的指标模块中的mean_sqaured_error函数来计算均方根值。

rmse = np.sqrt(mean_squared_error(y_test, preds))
print("RMSE: %f" % (rmse))
RMSE: 10.569356

好了, 你可以看到你的RMSE预测价格为每千$ 10.8左右。

使用XGBoost进行k折交叉验证

为了构建更强大的模型, 通常会进行k倍交叉验证, 其中原始训练数据集中的所有条目都用于训练和验证。而且, 每个条目仅用于验证一次。 XGBoost通过cv()方法支持k倍交叉验证。你所需要做的就是指定nfolds参数, 该参数是你要构建的交叉验证集的数量。此外, 它还支持许多其他参数(请查看此链接), 例如:

  • num_boost_round:表示你构建的树的数量(类似于n_estimators)
  • 指标:告诉你在简历期间要观察的评估指标
  • as_pandas:将结果返回到pandas DataFrame中。
  • early_stopping_rounds:如果在给定的回合数内保持率(本例中为” rmse”)没有改善, 则尽早完成模型的训练。
  • 种子:结果的可重复性。

这次, 你将创建一个超参数字典参数, 该参数将所有超参数及其值作为键值对保存, 但将从超参数字典中排除n_estimators, 因为你将改用num_boost_rounds。

你将通过调用XGBoost的cv()方法使用这些参数来构建三折交叉验证模型, 并将结果存储在cv_results DataFrame中。请注意, 这里使用的是之前创建的Dmatrix对象。

params = {"objective":"reg:linear", 'colsample_bytree': 0.3, 'learning_rate': 0.1, 'max_depth': 5, 'alpha': 10}

cv_results = xgb.cv(dtrain=data_dmatrix, params=params, nfold=3, num_boost_round=50, early_stopping_rounds=10, metrics="rmse", as_pandas=True, seed=123)

cv_results包含每个提升轮次的训练和测试RMSE指标。

cv_results.head()
测试均值 测试rmse-std 均方根 Train-rmse-std
0 21.746693 0.019311 21.749371 0.033853
1 19.891096 0.053295 19.859423 0.029633
2 18.168509 0.014465 18.072169 0.018803
3 16.687861 0.037342 16.570206 0.018556
4 15.365013 0.059400 15.206344 0.015451

提取并打印最终的增强舍入指标。

print((cv_results["test-rmse-mean"]).tail(1))
49    4.031162
Name: test-rmse-mean, dtype: float64

你可以看到, 与上次相比, 价格预测的RMSE有所降低, 约为每1000 $ 4.03。对于一组不同的超参数, 你甚至可以达到更低的RMSE。你可能会考虑应用诸如网格搜索, 随机搜索和贝叶斯优化之类的技术来获得最佳的超参数集。

可视化增强树和功能重要性

你还可以使用XGBoost使用整个房屋数据集创建的完全增强的模型来可视化单个树木。 XGBoost具有plot_tree()函数, 使这种类型的可视化变得容易。使用XGBoost学习API训练模型后, 你可以将其与你要使用num_trees参数绘制的树数一起传递给plot_tree()函数。

xg_reg = xgb.train(params=params, dtrain=data_dmatrix, num_boost_round=10)

使用matplotlib库绘制第一棵树:

import matplotlib.pyplot as plt

xgb.plot_tree(xg_reg, num_trees=0)
plt.rcParams['figure.figsize'] = [50, 10]
plt.show()
在Python中使用XGBoost5

这些图提供了对模型如何做出最终决策的理解, 以及为做出这些决策所做的拆分。

请注意, 如果以上图解在你的系统上引发” graphviz”错误, 请考虑通过在cmd上通过pip install graphviz安装graphviz软件包。你可能还需要在cmd上运行sudo apt-get install graphviz。 (链接)

可视化XGBoost模型的另一种方法是检查模型中原始数据集中每个要素列的重要性。

一种简单的方法包括计算每个特征在模型中所有增强轮次(树)上的分割次数, 然后将结果可视化为条形图, 并根据特征出现的次数进行排序。 XGBoost具有plot_importance()函数, 你可以执行此操作。

xgb.plot_importance(xg_reg)
plt.rcParams['figure.figsize'] = [5, 5]
plt.show()
在Python中使用XGBoost6

如你所见, 在所有功能中, 功能RM的重要性得分最高。因此, XGBoost还为你提供了一种进行特征选择的方法。这不是很棒吗?

总结

你已经到了本教程的结尾。我希望这可能会对你有所帮助。你首先了解了Boosting的总体工作原理, 然后专门研究XGBoost。你还练习了将XGBoost应用于开放源数据集, 并在了解其超参数的过程中进行了交叉验证, 可视化树并最终将其用作特征选择技术。哇!对于初学者来说, 这是一件好事, 但是XGBoost有太多值得探索的内容, 因此无法在单个教程中涵盖。如果你想了解更多信息, 请务必查看我们在srcmini上使用XGBoost进行的极端梯度增强课程。

本文地址:H5W3 » 在Python中使用XGBoost

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址