使用 Intel 优化 XGBoost 进行梯度提升
XGBoost 算法及其与 Python 中 Intel 的 xgboost 包装器的比较。
xgboost
库为 Python* 提供了可扩展、可移植、分布式的梯度提升算法。XGBoost
算法的关键特性包括稀疏感知(自动处理缺失数据)、支持并行化的块结构以及持续训练。本文将 XGBoost
算法称为 XGBoost
,将 Python 库称为 xgboost
,以示区分。
XGBoost
算法的流行度迅速增长,促使公司开发产品来支持其发展。Intel 在这方面做出了重大贡献,自 0.81 版本起,对每一次开源 xgboost
的发布都进行了优化。 Intel® AI Analytics Toolkit (AI Kit) 包含 Intel® Optimization for XGBoost* 以及许多其他优化的机器学习库,例如优化的 Python 版本、Scikit-learn* (sklearn) 和 Modin*,以增强数据预处理和分析能力。
本文将重点介绍 XGBoost
算法,并将其性能与相关的基于树的模型进行比较。我们可以使用 Anaconda*、Python pip 或其他包管理器,通过 Python 包 (xgboost
) 来访问 XGBoost
算法。在本教程中,我们将逐步安装相关的依赖项。
什么是梯度提升?
梯度提升,也称为随机梯度或梯度提升机,结合了梯度下降和集成提升的思想,创造了一种算法,该算法通过添加新的决策树到序列中来减少误差。它通过迭代计算凸函数沿最小化方向的梯度来最小化误差。在本教程中,我们将训练和测试一个提升树,并使用 sklearn 的默认损失函数 log loss 进行评估。
决策树模型特别容易出现欠拟合,因为其简单的设计有利于解释性。我们可以使用集成学习来降低欠拟合的风险。单个集成架构将多个模型组合到一个架构中,该架构使用基学习器的预测来训练额外的模型,直到收敛。集成的两种主要类型是装袋 (bagging) 和提升 (boosting)。装袋随机地、有放回地以相等的概率选择数据点,从而降低方差。提升根据迄今为止的性能选择数据点,从而减少偏差。XGBoost
算法结合了这些概念,以确保低偏差和低方差。
如何执行梯度提升
在此项目中,我们将使用 Intel Optimization for XGBoost
来实现、评估和比较一个简单的决策树模型、一个梯度提升决策树和一个 XGBoost
算法。任务是获取一组描述汽车的属性,并将其质量分类为不可接受、可接受、良好或非常好。
让我们开始吧。首先,从加州大学欧文分校 (UCI) 机器学习存储库网站或 Kaggle* 下载数据集。
数据集包含以下六个用于对汽车质量进行分类的特征:
- 购买价格
- 维护成本
- 门数
- 乘员数
- 后备箱容量
- 预估安全等级
其次,导入必要的库并加载整个数据集。在您选择的集成开发环境 (IDE) 中的 Anaconda 环境中运行代码片段。我们在 Jupyter* Notebook 中运行本文中的所有代码。按照此教程在笔记本中进行操作将最大限度地降低运行时的错误风险。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns; sns.set()
import warnings
import category_encoders as ce
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split
import time
import warnings
df = pd.read_csv("pathToData\\car_evaluation.csv")
第三,我们进行一些探索性数据分析,以更好地了解数据。pandas 包的 df.info
命令返回有关数据框特征(如 null
值是否存在以及我们特征的数据类型)的相关信息。
执行 df.info()
。结果如下:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1727 entries, 0 to 1726
Data columns (total 7 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 vhigh 1727 non-null object
1 vhigh.1 1727 non-null object
2 2 1727 non-null object
3 2.1 1727 non-null object
4 small 1727 non-null object
5 low 1727 non-null object
6 unacc 1727 non-null object
dtypes: object(7)
memory usage: 94.6+ KB
虽然我们可以根据数据集的描述推断出每一列的含义,但目前这些列的名称是通用的。因此,我们传递一个名称列表来为每一列赋予描述性标签。
df.columns= ['buying','maint','doors','persons','lug_boot','safety','class']
在实例化我们的模型之前,我们需要对所有分类变量进行编码,并将我们的数据集分割成训练集和测试集。我们可以使用 sklearn
的 train_test_split
函数轻松分割数据。
# Separate class column for target variable
X = df.drop(['class'], axis=1)
y = df['class']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.3, random_state = 42)
请注意,分类变量的性质是序数的。我们可以使用 categorical encoders 包中的序数编码器 (OrdinalEncoder
) 以此方式对数据进行编码。
# Encode training features with ordinal encoding
encoder = ce.OrdinalEncoder(cols=X_train.columns)
X_train = encoder.fit_transform(X_train)
X_test = encoder.transform(X_test)
在接下来的三个部分中,我们将实现三种方法进行比较:一个简单的决策树、一个梯度提升机和一个 Intel 的 XGBoost
算法。
创建简单的决策树
scikit-learn
Python 包提供了许多用于访问、训练和评估机器学习模型的功能。DecisionTreeClassifier
对应于一个用于分类任务的简单决策树模型。
我们将训练后的默认模型准确率得分作为我们的基准。
我们在选择的 IDE 中运行以下代码,使用 sklearn
实例化并训练一个决策树分类器。
from sklearn.tree import DecisionTreeClassifier
tree = DecisionTreeClassifier(random_state=42)
# fit the model
tree.fit(X_train, y_train)
接下来,我们通过计算准确率得分来评估模型的预测。准确率是正确分类的预测所占的百分比,使用以下代码:
# Predict and test on test data
y_hat = tree.predict(X_test)
accuracy_score(y_test, y_hat)
> 0.9441233140655106
因此,我们的基准得分是 94.4% 的预测准确率。
梯度提升
然后,我们使用 GradientBoostingClassifier
类将梯度提升实现到我们刚刚创建的简单决策树中进行分类。为了了解提升如何影响模型性能,我们运行以下代码:
from sklearn.ensemble import GradientBoostingClassifier
boostedTree = GradientBoostingClassifier(random_state=42)
boostedTree = boostedTree.fit(X_train, y_train)
boosted_y_hat = boostedTree.predict(X_test)
accuracy_score(y_test, boosted_y_hat)
> 0.9653179190751445
预测准确率提高了大约两个百分点,从 94.4% 提高到 96.5%。通过梯度提升,我们牺牲了速度来换取更高的准确率和可解释性。
要访问有关模型认为的每个变量重要性的洞察,我们使用 feature_importances_
函数,如下所示:
boostedTree.feature_importances_
array([0.14527816, 0.10707345, 0.01425489, 0.36412543, 0.04581993, 0.32344813])
该方法返回一个数组,其中包含我们数据集中每个变量对应的权重。
XGBoost
为了加快训练和推理速度,我们使用 Intel Optimization for XGBoost
。要将其作为 AI Kit 的一部分进行安装,让我们创建一个新的 Anaconda 环境。
如果您使用的是命令提示符,请运行以下命令。否则,请使用 GUI 界面。有关详细信息,请参阅官方 文档。
conda create –name envName
然后,我们像安装其他包一样使用 conda 安装 AI Kit:
conda install intel-aikit-modin -c intel
最后,在访问工具之前,我们通过运行 Anaconda 命令提示符来激活环境:
conda activate intel-aikit-modin
安装并激活 Intel 的 AI Kit 后,我们可以像使用常规 xgboost
框架一样进行操作。由于 AI Kit 还包含优化的 Scikit-learn
版本,我们可以遵循相同的语法来拟合和测试我们的 XGBoost 算法。以下代码通过最小化 log loss 并计算预测准确率来实例化 XGBoost
。为防止意外错误,请确保您的 xgboost
版本为 1.5 或更低。如果您使用的是 Jupyter 或 Google Colab* 等笔记本,可以使用以下命令检查您的版本。如果您是从终端进行交互,请记住不要包含感叹号。
!xgboost --version
> XGBoost: 1.5.0
否则,请运行以下命令:
import xgboost
print(xgboost.__version__)
最后,我们只需几行代码即可加载、训练和测试模型。
from xgboost import XGBClassifier
xgb = XGBClassifier(eval_metric='mlogloss')
xgb.fit(X_train, y_train)
# Predict and test on test data
xgb_y_hat = xgb.predict(X_test)
accuracy_score(y_test, xgb_y_hat)
> 0.9691714836223507
与我们之前的梯度提升分类器相比,这只是一个微不足道的改进,从 96.5% 提高到 96.9%。正如我们在本文前面所指出的,这是一个简单的数据集。此外,这些准确率分数异常高。因此,让我们探索其他维度来比较我们的模型。
模型比较
到目前为止,我们使用了一个单独的训练-测试分割来评估每个模型的准确率得分。对于我们这样的小型数据集,这会增加对过拟合的敏感性。更好的方法是在每个训练迭代中分批训练模型并打乱数据。
sklearn
中的 model_selection
类提供了实现 K 折交叉验证的功能。通过利用 K 折交叉验证,我们可以更好地捕捉每个模型的实际平均性能,而不会冒数据泄露的风险。
from sklearn import model_selection
models = [('TR', tree),
('BT', boostedTree),
('XGB', xgb)]
# evaluate each model in turn
results = []
names = []
scoring = 'accuracy'
for name, model in models:
time_start = time.time()
kfold = model_selection.KFold(n_splits=10)
cv_results = model_selection.cross_val_score
(model, X_train, y_train, cv=kfold, scoring=scoring)
results.append(cv_results)
names.append(name)
time_end = time.time()
msg = f"{name}: Mean score {cv_results.mean()} -
Std {cv_results.std()} - Seconds {round((time_end - time_start), 3)}"
请注意,您的结果可能有所不同,因为交叉验证包括反复选择整个数据集的 K 个随机打乱的子集。因此,分数可能因每次训练会话使用的样本而异。在这里,我们可以看到 XGBoost
模型在准确率和运行时方面平均提供了比提升树显著的改进。
> TR: Mean score 0.932961432506 - Std 0.0186055525846 - Seconds 0.043
> BT: Mean score 0.966907713498 - Std 0.0156554455448 - Seconds 3.529
> XGB: Mean score 0.97847796143 - Std 0.0099176064591 - Seconds 2.047
boxplot
帮助我们直观地理解模型之间的性能准确率如何变化,如下所示:
最后,我们可以绘制每个模型的混淆矩阵,以更好地理解其决策过程。请记住,正确的阅读方法是预测类别与实际类别匹配的次数百分比(因此被正确分类)。
所有三种算法都能比其他可能类别更好地捕捉好车的本质特征,准确率达到 68% 或更高;其次是不可接受质量的车辆特征,准确率达到 20% 或更高。其余两个类别的分数极低,表明在这种情况下需要更多数据。
结论
在本文中,我们通过构建两个简单的模型并将它们与 Intel 的 Python xgboost
包装器进行比较,探索了 XGBoost
算法。最后,我们进行了简单的评估,通过测量准确率和运行时来更好地了解每个模型的性能。K 折 (K=10) 交叉验证和混淆矩阵的结果证明了 Intel 的 xgboost 库在分类准确率和运行时方面提供了显著的改进。
只需几行代码,并且无需学习任何新语法,Intel 的 AI Kit 就允许我们无缝地改进了我们基于树的模型。我们涵盖了开始使用此新开源产品的主要步骤。如前所述,优化的 XGBoost
算法只是我们可用的众多功能之一。AI Kit 包含更有效地预处理数据和增强项目机器学习管道的高级功能。下一步包括:
- 尝试超参数调优
- 通过添加 daal4py 包获得更快的速度提升
- 在预测任务上测试 daal4py 包
- 使用更大的数据集测试算法