🔎大家好,我是Sonhhxg_柒,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎
📝个人主页-Sonhhxg_柒的博客_CSDN博客 📃
🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝
📣系列专栏 - 机器学习【ML】 自然语言处理【NLP】 深度学习【DL】
🖍foreword
✔说明⇢本人讲解主要包括Python、机器学习(ML)、深度学习(DL)、自然语言处理(NLP)等内容。
如果你对这个系列感兴趣的话,可以关注订阅哟👋
文章目录
在本章中,您将在 XGBoost 中分析和应用不同的基础学习器。在 XGBoost 中,基础学习器是单个模型,最常见的是树,每个提升轮次都会对其进行迭代。除了 XGBoost 定义为gbtree的默认决策树外,基础学习器的其他选项包括gblinear和dart。此外,XGBoost 有自己的随机森林实现作为基础学习器和树集成算法,您将在本章中进行试验。
通过学习如何应用替代基础学习器,您将使用 XGBoost 大大扩展您的范围。您将有能力构建更多模型,并且您将学习开发线性、基于树和随机森林机器学习算法的新方法。本章的目标是让您熟练使用替代基础学习器构建 XGBoost 模型,以便您可以利用高级 XGBoost 选项为各种情况找到最佳模型。
在本章中,我们涵盖以下主要主题:
-
探索替代基础学习器
-
应用gblinear
-
比较dart
-
寻找 XGBoost 随机森林
探索替代基础学习器
基础学习器是XGBoost 用于构建其集成中的第一个模型的机器学习模型。使用词库是因为它是首先出现的模型,而使用词学习器是因为模型在从错误中学习后会自我迭代。
决策树已成为 XGBoost 的首选基础学习器,因为提升树始终产生出色的分数。决策树的流行从 XGBoost 扩展到其他集成算法,例如随机森林和极其随机的树,您可以在 scikit-learn 文档中的ExtraTreesClassifier和ExtraTreesRegressor ( https://scikit-learn.org/stable/modules/ ) 中进行预览合奏.html)。
在 XGBoost 中,默认的基础学习器,称为gbtree,是其中之一几个基础学习者。还有gblinear,一种梯度提升的线性模型,和dart,一种决策树的变体,包括基于神经网络的 dropout 技术。此外,还有 XGBoost 随机森林。在下一节中,我们将探讨这些基础学习器之间的差异,然后再将它们应用于后续部分。
gb线性
决策树是非线性数据的最佳选择,因为它们可以通过根据需要多次拆分数据来轻松访问点。决策树通常最好作为基础学习器,因为真实数据通常是非线性的。
但是,在某些情况下,线性模型是理想的。如果真实数据具有线性关系,则决策树可能不是最佳选择。对于这种情况,XGBoost 提供gblinear作为线性基学习器的选项。
提升线性模型背后的一般思想与提升树模型相同。建立一个基础模型,并根据残差对每个后续模型进行训练。最后,将各个模型相加得出最终结果。线性基础学习器的主要区别在于集成中的每个模型都是线性的。
与Lasso和Ridge一样,线性回归的变体添加了正则化项(参见第 1 章,机器学习领域),gblinear也将正则化项添加到线性回归中。XGBoost 的创始人和开发者 Tianqi Chin 在 GitHub 上评论说,多轮 boosting gblinear可能用于返回单个 lasso 回归(What exactly does gblinear+reg:linear do? And other questions · Issue #332 · dmlc/xgboost · GitHub)。
gblinear也可以通过逻辑回归用于分类问题。这是因为逻辑回归也是通过寻找最优系数(加权输入)来构建的,就像在线性回归中一样,并通过sigmoid 方程求和(参见第 1 章,机器学习领域)。
我们将在本章的应用 gblinear部分探讨gblinear的细节和应用。现在,让我们了解一下dart。
DART
Dropouts满足多个加性回归树,简单被称为DART,被引入2015 年,加州大学伯克利分校的 KV Rashmi 和微软的 Ran Gilad-Bachrach 在以下论文中发表:http: //proceedings.mlr.press/v38/korlakaivinayak15.pdf。
Rashmi 和 Gilad-Bachrach 强调多重加性回归树( MART ) 是一个成功的模型,它过度依赖早期的树。他们没有关注收缩(一个标准的惩罚术语),而是使用神经网络的dropout技术。简单地说,dropout 技术从神经网络的每一层学习中消除了节点(数学点),从而减少了过拟合。换句话说,dropout 技术通过消除每一轮的信息来减慢学习过程。
在 DART 中,在每一轮新的提升中,DART 不是对所有先前树的残差求和以构建新模型,而是选择先前树的随机样本,并通过一个比例因子对叶子进行归一化,其中
是丢弃的树的数量。
DART 是决策树的一种变体。DART 的 XGBoost 实现类似于gbtree,具有额外的超参数以适应 dropout。
有关 DART 的数学细节,请参考本节第一段中突出显示的原始论文。
您将在本章后面的比较 dart部分练习使用DART基础学习器构建机器学习模型。
XGBoost 随机森林
最后的选择我们将在其中探索本节是 XGBoost 随机森林。随机森林可以通过将num_parallel_trees设置为大于1的整数来实现为基础学习器,并作为 XGBoost 中定义为XGBRFRegressor和XGBRFClassifier的类选项。
请记住,梯度提升旨在改善相对较弱的基础学习者的错误,而不是像随机森林这样的强基础学习者。尽管如此,可能存在随机森林基础学习器可能具有优势的边缘情况,因此它是一个不错的选择。
作为额外的奖励,XGBoost 提供了XGBRFRegressor和XGBRFClassifier作为随机森林机器学习算法,它们不是基础学习器,而是它们自己的算法。这些算法的工作方式与 scikit-learn 的随机森林类似(参见第 3 章,随机森林装袋)。主要区别在于 XGBoost 包含用于抵消过度拟合的默认超参数以及它们自己构建单个树的方法。XGBoost 随机森林一直处于实验阶段,但到 2020 年底,它们开始超越 scikit-learn 的随机森林,正如您将在本章中看到的那样。
在本章的最后一节,我们将试验 XGBoost 的随机森林,既可以作为基础学习器,也可以作为模型本身。
现在您已经了解了 XGBoost 基础学习器,让我们一次应用一个。
应用 gblinear
很有挑战性找到最适合线性模型的真实数据集。通常情况下,真实数据是混乱的,更复杂的模型(如树集成)会产生更好的分数。在其他情况下,线性模型可能会更好地泛化。
机器学习算法的成功取决于它们如何处理真实世界的数据。下一个部分,我们将首先将gblinear应用于糖尿病数据集,然后通过构造应用于线性数据集。
将 gblinear 应用于糖尿病数据集
糖尿病数据集是由 scikit-learn 提供的 442 名糖尿病患者的回归数据集。预测列包括年龄、性别、BMI(体重指数)、BP(血压)和五种血清测量值。目标列是 1 年后疾病的进展。您可以在此处阅读原始论文中的数据集:http ://web.stanford.edu/~hastie/Papers/LARS/LeastAngle_2002.pdf 。
Scikit-learn 的数据集已经为您分成预测列和目标列。它们被预处理用于机器学习,其中X(预测变量列)和y(目标列)分别加载。
以下是您需要使用此数据集和本章其余部分的完整导入列表:
import pandas as pd
import numpy as np
from sklearn.datasets import load_diabetes
from sklearn.model_selection import cross_val_score
from xgboost import XGBRegressor, XGBClassifier, XGBRFRegressor, XGBRFClassifier
from sklearn.ensemble import RandomForestRegressor, RandomForestClassifier
from sklearn.linear_model import LinearRegression, LogisticRegression
from sklearn.linear_model import Lasso, Ridge
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import KFold
from sklearn.metrics import mean_squared_error as MSE
让我们开始!要使用糖尿病数据集,请执行以下操作:
-
您首先需要使用load_diabetes定义X和y,并将return_X_y参数设置为True:
X, y = load_diabetes(return_X_y=True)
计划是使用cross_val_score和GridSearchCV,所以让我们提前创建折叠以获得一致的分数。在第 6 章XGBoost超参数中,我们使用了StratifiedKFold,它对目标列进行分层,确保每个测试集包含相同数量的类。
这种方法适用于分类,但不适用于回归,其中目标列采用连续值并且不涉及类。KFold实现了类似的通过在数据中创建一致的拆分来实现不分层的目标。
-
现在,使用以下参数对数据进行洗牌并使用KFold进行5次拆分:
kfold = KFold(n_splits=5, shuffle=True, random_state=2)
-
使用cross_val_score构建一个函数,该函数将机器学习模型作为输入并返回5折的平均分数作为输出,确保设置cv=kfold:
def regression_model(model): scores = cross_val_score(model, X, y, scoring='neg_mean_squared_error', cv=kfold) rmse = (-scores)**0.5 return rmse.mean()
-
要使用gblinear作为基础模型,只需在回归函数中为XGBRegressor设置booster='gblinear' :
regression_model(XGBRegressor(booster='gblinear'))
分数如下:
55.4968907398679
-
让我们对照其他线性模型检查这个分数,包括LinearRegression、使用L1或绝对值正则化的Lasso和使用L2或欧几里得距离正则化的Ridge:
a)线性回归如下:
regression_model(LinearRegression())
分数如下:
55.50927267834351
b)Lasso如下:
regression_model(Lasso())
分数如下:
62.64900771743497
c) Ridge如下:
regression_model(Ridge())
分数如下:
58.83525077919004
正如你可以看到,以gblinear作为基础学习器的XGBRegressor以及LinearRegression表现最好。
-
现在将booster='gbtree'放在XGBRegressor中,这是默认的基础学习器:
regression_model(XGBRegressor(booster='gbtree'))
分数如下:
65.96608419624594
如您所见,在这种情况下, gbtree基学习器的性能几乎不如gblinear基学习器,这表明线性模型是理想的。
让我们看看我们是否可以修改超参数以使用gblinear作为基础学习器来获得一些收益。
gblinear 超参数
理解很重要gblinear和gbtree在调整超参数时的区别。第 6 章XGBoost超参数中介绍的许多 XGBoost 超参数是树超参数,不适用于gblinear。例如,max_depth和min_child_weight是专门为树设计的超参数。
以下列表是为线性模型设计的 XGBoost gblinear超参数的摘要。
reg_lambda
Scikit-learn 使用reg_lambda代替lambda,后者是 lambda 的保留关键字Python 中的函数。这是Ridge使用的标准 L2 正则化。接近0的值往往效果最好:
-
默认值:0
-
范围:[0, inf)
-
增加防止过拟合
-
别名:alpha
reg_alpha
Scikit-学习接受reg_alpha和alpha。这是Lasso使用的标准 L1 正则化。接近0的值往往效果最好:
-
默认值:0
-
范围:[0, inf)
-
增加防止过拟合
-
别名:阿尔法
更新者
这是 XGBoost 使用的算法在每一轮提升期间建立线性模型。shotgun使用带有坐标下降的hogwild并行性来产生非确定性解决方案。相比之下,coord_descent是具有确定性解的普通坐标下降:
-
默认:shotgun
-
射程:shotgun,coord_descent
笔记
坐标下降是一个机器学习术语,定义为通过一次找到一个坐标来最小化误差。
特征选择器
feature_selector确定如何使用以下选项选择权重:
a)cyclic——迭代地循环特征
b) shuffle – 在每一轮中循环随机特征洗牌
c) random – 坐标下降期间的坐标选择器是随机的
d)greedy——耗时;选择梯度幅度最大的坐标
e) thrifty – 近似贪婪,根据权重变化对特征重新排序
-
默认值:cyclic
-
Range 必须与 updater 一起使用,如下所示:
a)shotgun:cyclic, shuffle
b) coord_descent:random, greedy, thrifty
笔记
greedy对于大型数据集的计算成本很高,但是通过更改参数top_k可以减少greedy考虑的特征数量(见下文)。
top_k
-
默认值:0(所有功能)
-
范围:[0,最大特征数]
笔记
有关 XGBoost gblinear超参数的更多信息,请参阅官方 XGBoostXGBoost Parameters — xgboost 1.7.0-dev documentation的文档页面。
gblinear grid search
既然熟悉了有了gblinear可能使用的超参数范围,让我们在自定义的grid_search函数中使用GridSearchCV来找到最好的:
-
这是第 6 章XGBoost超参数中我们的grid_search函数的一个版本:
def grid_search(params, reg=XGBRegressor(booster='gblinear')): grid_reg = GridSearchCV(reg, params, scoring='neg_mean_squared_error', cv=kfold) grid_reg.fit(X, y) best_params = grid_reg.best_params_ print("Best params:", best_params) best_score = np.sqrt(-grid_reg.best_score_) print("Best score:", best_score)
-
grid_search(params={'reg_alpha':[0.001, 0.01, 0.1, 0.5, 1, 5]})
输出如下:
Best params: {'reg_alpha': 0.01} Best score: 55.485310447306425
分数大致相同,略有改善。
-
接下来,让我们用相同的范围修改reg_lambda :
grid_search(params={'reg_lambda':[0.001, 0.01, 0.1, 0.5, 1, 5]})
输出如下:
Best params: {'reg_lambda': 0.001} Best score: 56.17163554152289
这里的分数非常相似,但稍差一些。
-
现在让我们将feature_selector与updater结合使用。默认情况下,updater=shotgun和feature_selector=cyclic。当updater=shotgun时, feature_selector的唯一其他选项是shuffle。
让我们看看shuffle是否能比cyclic表现更好:
grid_search(params={'feature_selector':['shuffle']})
输出如下:
Best params: {'feature_selector': 'shuffle'} Best score: 55.531684115240594
在这种情况下,shuffle并没有表现得更好。
-
现在让我们将updater更改为coord_descent。结果,feature_selector可能采取random、greedy或thrifty的态度。通过输入以下代码,在grid_search中尝试所有feature_selector替代方案:
grid_search(params={'feature_selector':['random', 'greedy', 'thrifty'], 'updater':['coord_descent'] })
输出如下:
Best params: {'feature_selector': 'thrifty', 'updater': 'coord_descent'} Best score: 55.48798105805444
这比基本分数略有提高。
最后要检查的超参数是top_k ,它定义了在坐标下降期间贪婪和节俭检查的特征数量。2到9的范围是可以接受的,因为总共有 10 个特征。
-
在grid_search中输入top_k的范围,以寻找最佳选择:
grid_search(params={'feature_selector':['greedy', 'thrifty'], 'updater':['coord_descent'], 'top_k':[3, 5, 7, 9]})
输出如下:
Best params: {'feature_selector': 'thrifty', 'top_k': 3, 'updater': 'coord_descent'} Best score: 55.478623763746256
这是迄今为止最好的成绩。
在继续之前,请注意也可以使用不限于树的其他超参数,例如n_estimators和learning_rate。
现在让我们看看gblinear如何在构造上是线性的数据集上工作。
Linear datasets
一种方法来确保一个数据集是线性的。我们可以选择一系列X值,比如1到99,然后将它们乘以包含一些随机性的比例因子。
以下是构建线性数据集的步骤:
-
将X值的范围设置为1到100:
X = np.arange(1,100)
-
使用 NumPy 声明一个随机种子,以确保结果的一致性:
np.random.seed(2)
-
创建一个定义为y的空列表:
y = []
-
遍历X,将每个条目乘以从-0.2到0.2的随机数:
for i in X: y.append(i * np.random.uniform(-0.2, 0.2))
-
将y转换为用于机器学习的numpy数组:
y = np.array(y)
-
重塑X和y以便它们包含与数组中的成员一样多的行和一列,因为列应该作为 scikit-learn 的机器学习输入:
X = X.reshape(X.shape[0], 1) y = y.reshape(y.shape[0], 1)
我们现在有一个线性数据集,其中包括X和y方面的随机性。
让我们以gblinear作为基础学习器再次运行回归模型函数:
regression_model(XGBRegressor(booster='gblinear', objective='reg:squarederror'))
分数如下:
6.214946302686011
regression_model(XGBRegressor(booster='gbtree', objective='reg:squarederror'))
分数如下:
9.37235946501318
如您所见,gblinear在我们构建的线性数据集中表现得更好。
为了更好地衡量,让我们在同一数据集上尝试LinearRegression :
regression_model(LinearRegression())
分数如下:
6.214962315808842
在这种情况下,gblinear 的表现稍好一些,可能可以忽略不计,得分比 LinearRegression 低0.00002分。
分析 gblinear
gblinear是一个令人信服的选项,但只有在您有理由相信线性模型时才应使用它可能比基于树的模型表现更好。gblinear在真实数据集和构建数据集中的表现确实比 LinearRegression 稍微好一点。在 XGBoost 中,当数据集很大且呈线性时,gblinear是基础学习器的一个强有力的选择。gblinear也是分类数据集的一个选项,您将在下一节中应用该选项。
比较dart
基础学习器dart类似于gbtree,因为两者都是梯度提升树。主要区别在于dart在每一轮提升过程中都会删除树(称为 dropout)。
在本节中,我们将在回归和分类问题中应用基础学习器Dart并将其与其他基础学习器进行比较。
DART 与 XGBRegressor
-
首先,像以前一样使用load_diabetes重新定义X和y:
X, y = load_diabetes(return_X_y=True)
-
要将dart用作 XGBoost 基础学习器,请在regression_model函数中设置XGBRegressor参数booster='dart':
regression_model(XGBRegressor(booster='dart', objective='reg:squarederror'))
分数如下:
65.96444746130739
dart基础学习器给出与gbtree基础学习器相同的结果,精确到小数点后两位。结果的相似性是由于小数据集和gbtree默认超参数的成功,以防止过度拟合而不需要 dropout 技术。
让我们看看dart在更大的分类数据集上与gbtree相比的表现如何。
使用 XGBClassifier dart
你用过本书多个章节中的人口普查数据集。一个干净的我们在第 1 章“机器学习景观”中修改的数据集版本已与第 8 章“ XGBoost 替代基础学习者”的代码一起预加载,位于https://github.com/PacktPublishing/Hands-On- Gradient-Boosting-with-XGBoost-and-Scikit-learn/tree/master/Chapter08。现在让我们开始测试dart在更大数据集上的表现:
-
将 Census 数据集加载到 DataFrame 中,并使用最后一个索引 ( -1 ) 作为目标列将预测变量和目标列拆分为X和y :
df_census = pd.read_csv('census_cleaned.csv') X_census = df_census.iloc[:, :-1] y_census = df_census.iloc[:, -1]
-
定义一个新的分类函数,它使用cross_val_score,机器学习模型作为输入,平均分数作为输出,类似于本章前面定义的回归函数:
def classification_model(model): scores = cross_val_score(model, X_census, y_census, scoring='accuracy', cv=kfold) return scores.mean()
-
现在使用带有booster='gbtree'和booster='dart'的XGBClassifier调用该函数两次以比较结果。请注意,由于数据集更大,运行时间会更长:
a) 让我们首先使用booster='gbtree'调用XGBClassifier:
classification_model(XGBClassifier(booster='gbtree'))
分数如下:
0.8701208195968675
b) 现在,让我们用booster='dart'调用XGBClassifier:
classification_model(XGBClassifier(booster='dart')
分数如下:
0.8701208195968675
这是令人惊讶的。对于所有 16 位小数,dart给出的结果与gbtree完全相同!目前尚不清楚树木是否被倒下或树木倒下的影响为零。
我们可以调整超参数以确保删除树,但首先,让我们看看dart与gblinear的比较。回想一下gblinear也适用于分类sigmoid 函数与逻辑回归一样缩放权重:
-
使用XGBClassifier调用分类模型函数并设置booster='gblinear':
classification_model(XGBClassifier(booster='gblinear'))
分数如下:
0.8501275704120015
这种线性基学习器的性能不如树基学习器。
-
让我们看看gblinear与逻辑回归的比较。由于数据集很大,最好将逻辑回归的max_iter超参数从100调整到1000,以留出更多时间进行收敛并消除警告。请注意,在这种情况下,增加max_iter会提高准确性:
classification_model(LogisticRegression(max_iter=1000))
分数如下:
0.8008968643699182
在这种情况下, gblinear比逻辑回归保持明显优势。值得强调的是,XGBoost 在分类中的gblinear选项提供了逻辑回归的可行替代方案。
现在您已经看到dart与gbtree和gblinear作为基础学习器的比较,让我们修改dart的超参数。
DART 超参数
dart包含所有gbtree超参数以及它自己的一组额外的超参数,旨在调整辍学树的百分比、频率和概率。有关详细信息,请参阅XGBoost Parameters — xgboost 1.7.0-dev documentation上的 XGBoost 文档。
以下部分是对dart独有的 XGBoost 超参数的总结。
样本类型
sample_type的选项包括uniform,其中均匀地丢弃树,并加权,它按照权重的比例丢弃树:
-
默认值:“统一”
-
范围:[“统一”,“加权”]
-
确定如何选择丢弃的树
规范化类型
normalize_type的选项包括tree,其中新树的权重与丢弃的树,和forest,其中新树的权重与丢弃的树的总和相同:
-
默认值:“树”
-
范围:[“树”,“森林”]
-
根据掉落的树木计算树木的权重
rate_drop
-
默认值:0.0
-
范围:[0.0, 1.0]
-
被丢弃的树木百分比
one_drop
当设置为1时,one_drop确保在 boosting 轮中总是至少丢弃一棵树:
-
默认值:0
-
范围:[0, 1]
-
用于确保滴
跳过
skip_drop给出完全跳过 dropout 的概率。在官方文档中,XGBoost 表示skip_drop的优先级高于rate_drop或one_drop。默认情况下,每棵树都以相同的概率被丢弃,因此对于给定的提升轮,有可能没有树被丢弃。skip_drop允许更新此概率以控制 dropout 轮数:
-
默认值:0.0
-
范围:[0.0, 1.0]
-
跳过 dropout 的概率
现在让我们修改dart超参数来区分分数。
修改dart超参数
为了确保至少每一轮提升中的一棵树被丢弃,我们可以设置one_drop=1。现在通过classification_model函数对人口普查数据集执行此操作:
classification_model(XGBClassifier(booster='dart', one_drop=1))
结果如下:
0.8718714338474818
这是一个十分之一百分点的改进,表明每轮提升至少丢弃一棵树可能是有利的。
现在我们正在删除树来改变分数,让我们回到更小更快的糖尿病数据集来修改剩余的超参数:
-
使用regression_model函数,将sample_type从uniform更改为weighted:
regression_model(XGBRegressor(booster='dart', objective='reg:squarederror', sample_type='weighted'))
分数如下:
65.96444746130739
这比之前得分的gbtree模型好 0.002 分。
-
将 normalize_type更改为forest以在更新权重时包括树的总和:
regression_model(XGBRegressor(booster='dart', objective='reg:squarederror', normalize_type='forest'))
分数如下:
65.96444746130739
分数没有变化,这可能发生在浅数据集上。
-
将 one_drop更改为1以保证每轮提升至少丢弃一棵树:
regression_model(XGBRegressor(booster='dart', objective='reg:squarederror', one_drop=1))
分数如下:
61.81275131335009
当谈到rate_drop时,将被丢弃的树的百分比,百分比范围可以与grid_search函数一起使用,如下所示:
grid_search(params={'rate_drop':[0.01, 0.1, 0.2, 0.4]},
reg=XGBRegressor(booster='dart', objective='reg:squarederror', one_drop=1))
结果如下:
Best params: {'rate_drop': 0.2}
Best score: 61.07249602732062
这是迄今为止最好的结果。
我们可以用skip_drop实现一个类似的范围,它给出了给定树没有被丢弃的概率:
grid_search(params={'skip_drop':[0.01, 0.1, 0.2, 0.4]},
reg=XGBRegressor(booster='dart', objective='reg:squarederror'))
结果如下:
Best params: {'skip_drop': 0.1}
Best score: 62.879753748627635
这是一个不错的分数,但skip_drop并没有带来实质性的收益。
现在您已经了解了dart是如何工作的,让我们分析一下结果。
分析dart
dart提供了一个引人注目的XGBoost 框架中的选项。由于dart接受所有gbtree超参数,因此在修改超参数时很容易将基础学习器从gbtree更改为dart。实际上,优点是您可以尝试新的超参数,包括one_drop、rate_drop、normalize等,看看您是否可以获得额外的收益。dart绝对值得作为基础学习者尝试使用 XGBoost 进行研究和模型构建。
现在您已经对dart有了很好的了解,是时候继续学习随机森林了。
寻找 XGBoost 随机森林
那里有两个在 XGBoost 中实现随机森林的策略。第一个是使用随机森林作为基础学习器,第二个是使用 XGBoost 的原始随机森林XGBRFRegressor和XGBRFClassifier。我们从最初的主题开始,将随机森林作为替代基础学习器。
随机森林作为基础学习器
没有一个将助推器超参数设置为随机森林的选项。相反,超参数num_parallel_tree可以从其默认值1增加以将gbtree(或dart)转换为增强随机森林。这里的想法是,每一轮提升将不再由一棵树组成,而是由许多平行的树组成,这些树又组成了一个森林。
以下是 XGBoost 超参数num_parallel_tree的快速总结。
num_parallel_tree
num_parallel_tree给出数字在每轮增强期间建造的树木,可能超过 1 棵:
-
默认值:1
-
范围:[1, inf)
-
给出并行提升的树数
-
大于 1 的值将助推器变成随机森林
通过每轮包含多棵树,基础学习器不再是一棵树,而是一片森林。由于 XGBoost 包含与随机森林相同的超参数,因此当num_parallel_tree超过 1 时,基学习器被适当地分类为随机森林。
让我们看看 XGBoost 随机森林基础学习器在实践中是如何工作的:
-
使用XGBRegressor调用regression_model并设置booster='gbtree'。此外,设置num_parallel_tree=25表示每个增强轮由25棵树的森林组成:
regression_model(XGBRegressor(booster='gbtree', objective='reg:squarederror', num_parallel_tree=25))
分数如下:
65.96604877151103
分数是可观的,在这种情况下,它几乎与提升单个gbtree相同。原因是梯度提升旨在从先前树的错误中学习。从一个健壮的随机森林开始,几乎没有什么可学的,而且收益最多是最小的。
理解梯度提升作为一种算法的强度来自学习过程的基本点是必不可少的。因此,为num_parallel_tree尝试更小的值是有意义的,例如5。
-
在同一回归模型中设置num_parallel_tree=5 :
regression_model(XGBRegressor(booster='gbtree', objective='reg:squarederror', num_parallel_tree=5))
分数如下:
65.96445649315855
从技术上讲,这分数比 25 棵树的森林产生的分数高 0.002 分。虽然提升不大,但一般来说,在构建 XGBoost 随机森林时,num_parallel_tree的值越低越好。
现在您已经了解了如何在 XGBoost 中将随机森林实现为基础学习器,是时候将随机森林构建为原始 XGBoost 模型了。
随机森林作为 XGBoost 模型
在除了XGBRegressor和XGBClassifier 之外,XGBoost还附带了XGBRFRegressor和XGBRFClassifier来构建随机森林。
根据Random Forests(TM) in XGBoost — xgboost 1.7.0-dev documentation上的官方 XGBoost 文档,随机森林 scikit-learn 包装器仍处于试验阶段,可能随时更改默认值。在撰写本文时,2020 年包含以下XGBRFRegressor和XGBRFClassifier默认值。
n_estimators
使用XGBRFRegressor或XGBRFClassifier构建随机森林时,使用n_estimators而不是num_parallel_tree 。请记住,当使用XGBRFRegressor和XGBRFClassifier时,您不是梯度提升,而是仅在一轮中装袋树,就像传统随机森林的情况一样:
-
默认值:100
-
范围:[1, inf)
-
自动转换为随机森林的 num_parallel_tree
learning_rate
learning_rate通常设计用于学习的模型,包括助推器,而不是XGBRFRegressor或XGBRFClassifier,因为它们由一轮树组成。尽管如此,将learning_rate从 1 更改会改变分数,因此通常不建议修改此超参数:
-
默认值:1
-
范围:[0, 1]
subsample,colsample_by_node
Scikit-learn 的随机森林将这些默认值保持在1,使默认的XGBRFRegressor和XGBRFClassifier不太容易过度拟合。这是 XGBoost 和 scikit-learn 之间的主要区别随机森林默认实现:
-
默认值:0.8
-
范围:[0, 1]
-
减少有助于防止过度拟合
现在,让我们看看 XGBoost 的随机森林在实践中是如何工作的:
-
首先,将XGBRFRegressor放在regression_model函数中:
regression_model(XGBRFRegressor(objective='reg:squarederror'))
分数如下:
59.447250741400595
这个分数比前面介绍的gbtree模型好一点,比本章介绍的最好的线性模型差一点。
-
作为比较,让我们看看RandomForestRegressor如何通过将它放在同一个函数中来执行:
regression_model(RandomForestRegressor())
分数如下:
59.46563031802505
这个分数比XGBRFRegressor 略差。
现在让我们比较一下XGBoost 随机使用更大的人口普查数据集进行分类的 scikit-learn 标准随机森林的森林:
-
将XGBRFClassifier放在classification_model函数中,看看它对用户收入的预测效果如何:
classification_model(XGBRFClassifier())
分数如下:
0.856085650471878
这是一个不错的分数,与之前给出的 87%的gbtree有点偏离。
-
现在将RandomForestClassifier放在同一个函数中以比较结果:
classification_model(RandomForestClassifier())
分数如下:
0.8555328202034789
这比 XGBoost 的实现稍差。
由于 XGBoost 的随机森林仍处于开发阶段,我们将在此停下来分析结果。
分析 XGBoost 随机森林
您可以随时通过将num_parallel_tree增加到一个值来尝试使用随机森林作为 XGBoost 基础学习器大于1。虽然,正如您在本节中看到的,boosting 旨在从弱模型而不是强模型中学习,因此num_parallel_tree的值应保持接近1。应谨慎使用随机森林作为基础学习器。如果提升单棵树无法产生最佳分数,则可以选择随机森林基础学习器。
或者,XGBoost 随机森林的XGBRFRegressor和XGBRFClassifier可以作为 scikit-learn 随机森林的替代方案来实现。XGBoost 的新XGBRFRegressor和XGBRFClassifier优于 scikit-learn 的RandomForestRegressor和RandomForestClassifier,尽管比较非常接近。鉴于 XGBoost 在机器学习社区的整体成功,绝对值得使用XGBRFRegressor和XGBRFClassifier作为未来可行的选择。
概括
在本章中,您通过将所有 XGBoost 基础学习器(包括gbtree、dart、gblinear和随机森林)应用于回归和分类数据集,极大地扩展了 XGBoost 的范围。您预览、应用和调整了基础学习者特有的超参数以提高分数。此外,您使用线性构造的数据集和XGBRFRegressor和XGBRFClassifier对gblinear进行了实验,以构建 XGBoost 随机森林,而无需任何增强。现在您已经与所有基础学习者一起工作,您对 XGBoost 范围的理解处于高级水平。
在下一章中,您将分析 Kaggle 大师的技巧和窍门,以进一步提升您的 XGBoost 技能!