XGBoost和Random-Forest(RF,随机森林)都属于集成学习(Ensemble Learning),集成学习的目的是通过结合多个基学习器的预测结果来改善单个学习器的泛化能力和鲁棒性,通过组合各个决策树的输出来进行预测(分类或回归)。而集成学习按照个体学习器的生成方式,可以大致分为两类:一类是个体学习器之间存在强依赖关系,必须串行生成序列的方法;以及个体学习器之间不存在强依赖关系,可同时生成的并行化方法。前者的代表就是XGBoost,后者的代表是Random-Forest。
在这篇文章中,将尝试解释如何使用XGBoost和随机森林这两种非常流行的贝叶斯优化方法,而不仅仅是比较这两种模型的主要优点和缺点。
XGBoost vs Random Forest
XGBoost
XGBoost每次构建一个决策树,每个新树校正由先前训练的决策树产生的错误。
XGBoost应用示例
Addepto公司使用XGBoost模型来解决异常检测问题,例如在监督学习方法中,XGB在这种情况下是非常有用的,因为异常检测数据集通常是非常不平衡,比如手机APP中的用户/消费者交易,能量消耗或用户行为等,这些数据也经常用于推荐模型等训练数据,XGBoost模型在推荐系统中也是经典模型之一。
优点
由于提升树是通过优化目标函数得到的,所以XGB基本上可以用来解决几乎所有可以求导的目标函数,包括排名和泊松回归等内容,这是随机森林模型难以实现。
缺点
如果数据中存在噪声,那么XGB模型可能会对过拟合会更为敏感。由于树模型是按顺序建造的,因此训练通常需要花费更长的时间。此外,XGB比随机森林更难调参,XGB通常有三个参数:树的数量,树的深度和学习率。一般而言,构建的每个树通常是浅的。
随机森林
随机森林(RF)使用随机数据样本独立训练每棵树,这种随机性有助于使得模型比单个决策树更健壮。由于这个原因,随机森林算法在训练数据上不太可能出现过拟合现象。
随机森林应用示例
随机森林的差异性已被用于各种应用,例如基于组织标记数据找到患者群$[1]$。 在以下两种情况下,随机森林模型对于这种应用非常实用:
- 目标是为具有强相关特征的高维问题提供高预测精度;
- 数据集非常嘈杂,并且包含许多缺失值,例如某些属性是半连续的;
优点
随机森林中的模型参数调整比XGBoost更容易。在随机森林中,只有两个主要参数:每个节点要选择的特征数量和决策树的数量。此外,随机森林比XGB更难出现过拟合现象。
缺点
随机森林算法的主要限制是大量的树使得算法对实时预测的速度变得很慢。对于包含不同级别数的分类变量的数据,随机森林偏向于具有更多级别的属性。
贝叶斯优化
贝叶斯优化是一种优化函数的技术,其评估成本很高$[2]$。它为目标函数构建后验分布,并使用高斯过程回归计算该分布中的不确定性,然后使用采集函数(acquisition function )来决定采样的位置。贝叶斯优化专注于解决问题:
$max(_x∈AF(X))$
超参数的维度($x∈R_d$)一般设置为$d<20$。
通常设置A超矩形($x∈R^d$:$a_i≤x_i≤b_i$)。目标函数是连续的,这是使用高斯过程回归建模所需的。它也缺乏像凹函数或线性函数这类函数,这使得利用这类函数来提高效率的技术徒劳无功。贝叶斯优化由两个主要组成部分组成:用于对目标函数建模的贝叶斯统计模型和用于决定下一步采样的采集函数。
在根据初始空间初始化实验设计的评估目标后,迭代使用这些目标分配N个评估的预算的剩余部分,如下所示:
- 观察初始点;
- 当$n\leqN$ 时,使用所有可用数据更新后验概率分布,并让$x_n$作为采集函数的最大值时的取值。继续观察$y_n=f(x_n)$ ,增大$n$, 直到循环结束;
- 返回一个解决方案:最大的评估点;
通过上述可以总结到,贝叶斯优化是为黑盒无导数全局优化而设计的,在机器学习中调整超参数中是非常受欢迎的。
下面是整个优化的图形做总结:具有后验分布的高斯过程以及观察值和置信区间,以及效用函数(Utility Function),其中最大值表示下一个样本点。
由于效用函数的存在,贝叶斯优化在机器学习算法的参数调整方面比网格(grid)或随机搜索技术(random search)更有效,它可以有效地平衡“探索”和“开发”在寻找全局最优中的作用。
实践
为了实现贝叶斯优化,使用Python编写的BayesianOptimization库$[3]$来调整随机森林和XGBoost分类算法的超参数。首先需要通过pip安装它:
pip install bayesian-optimization
现在开始训练模型。首先导入所需要的依赖库:
#Import libraries
import pandas as pd
import numpy as np
from bayes_opt import BayesianOptimization
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
import xgboost as xgb
下面定义了一个函数来运行给定数据的贝叶斯优化,以及要优化的函数及其超参数:
#Bayesian optimization
def bayesian_optimization(dataset, function, parameters):
X_train, y_train, X_test, y_test = dataset
n_iterations = 5
gp_params = {"alpha": 1e-4}
BO = BayesianOptimization(function, parameters)
BO.maximize(n_iter=n_iterations, **gp_params)
return BO.max
下面定义了优化函数,即随机森林分类器及其超参数$n\_estimators$,$max\_depth$和$min\_samples\_split$。另外,对给定数据集使用交叉验证获得分数的平均值:
def rfc_optimization(cv_splits):
def function(n_estimators, max_depth, min_samples_split):
return cross_val_score(
RandomForestClassifier(
n_estimators=int(max(n_estimators,0)),
max_depth=int(max(max_depth,1)),
min_samples_split=int(max(min_samples_split,2)),
n_jobs=-1,
random_state=42,
class_weight="balanced"),
X=X_train,
y=y_train,
cv=cv_splits,
scoring="roc_auc",
n_jobs=-1).mean()
parameters = {"n_estimators": (10, 1000),
"max_depth": (1, 150),
"min_samples_split": (2, 10)}
return function, parameters
类似地,为XGBoost分类器定义函数和超参数:
def xgb_optimization(cv_splits, eval_set):
def function(eta, gamma, max_depth):
return cross_val_score(
xgb.XGBClassifier(
objective="binary:logistic",
learning_rate=max(eta, 0),
gamma=max(gamma, 0),
max_depth=int(max_depth),
seed=42,
nthread=-1,
scale_pos_weight = len(y_train[y_train == 0])/
len(y_train[y_train == 1])),
X=X_train,
y=y_train,
cv=cv_splits,
scoring="roc_auc",
fit_params={
"early_stopping_rounds": 10,
"eval_metric": "auc",
"eval_set": eval_set},
n_jobs=-1).mean()
parameters = {"eta": (0.001, 0.4),
"gamma": (0, 20),
"max_depth": (1, 2000)}
return function, parameters
现在,基于选择的分类器,可以对其进行优化并训练模型:
#Train model
def train(X_train, y_train, X_test, y_test, function, parameters):
dataset = (X_train, y_train, X_test, y_test)
cv_splits = 4
best_solution = bayesian_optimization(dataset, function, parameters)
params = best_solution["params"]
model = RandomForestClassifier(
n_estimators=int(max(params["n_estimators"], 0)),
max_depth=int(max(params["max_depth"], 1)),
min_samples_split=int(max(params["min_samples_split"], 2)),
n_jobs=-1,
random_state=42,
class_weight="balanced")
model.fit(X_train, y_train)
return model
作为示例数据,使用来自AdventureWorksDW2017 SQL Server数据库的视图。在该数据库中,根据个人数据,需要预测是否有人购买自行车。这里只给出贝叶斯优化在随机森林算法上的结果:
ITER | AUC | max_depth | min_samples_split | n_estimators |
---|---|---|---|---|
1 | 0.8549 | 45.88 | 6.099 | 34.82 |
2 | 0.8606 | 15.85 | 2.217 | 114.3 |
3 | 0.8612 | 47.42 | 8.694 | 306.0 |
4 | 0.8416 | 10.09 | 5.987 | 563.0 |
5 | 0.7188 | 4.538 | 7.332 | 766.7 |
6 | 0.8436 | 100.0 | 2.0 | 448.6 |
7 | 0.6529 | 1.012 | 2.213 | 315.6 |
8 | 0.8621 | 100.0 | 10.0 | 1E + 03 |
9 | 0.8431 | 100.0 | 2.0 | 154.1 |
10 | 0.653 | 1.0 | 2.0 | 1E + 03 |
11 | 0.8621 | 100.0 | 10.0 | 668.3 |
12 | 0.8437 | 100.0 | 2.0 | 867.3 |
13 | 0.637 | 1.0 | 10.0 | 10.0 |
14 | 0.8518 | 100.0 | 10.0 | 10.0 |
15 | 0.8435 | 100.0 | 2.0 | 317.6 |
16 | 0.8621 | 100.0 | 10.0 | 559.7 |
17 | 0.8612 | 89.86 | 10.0 | 82.96 |
18 | 0.8616 | 49.89 | 10.0 | 212.0 |
19 | 0.8622 | 100.0 | 10.0 | 771.7 |
20 | 0.8622 | 38.33 | 10.0 | 469.2 |
21 | 0.8621 | 39.43 | 10.0 | 638.6 |
22 | 0.8622 | 83.73 | 10.0 | 384.9 |
23 | 0.8621 | 100.0 | 10.0 | 936.1 |
24 | 0.8428 | 54.2 | 2.259 | 122.4 |
25 | 0.8617 | 99.62 | 9.856 | 254.8 |
从上面的结果可以看到,贝叶斯优化在第23步迭代中找到了最佳参数,在测试数据集上得到0.8622 AUC分数。如果数据样本更多,实验结果可能会更好。优化的随机森林模型具有以下ROC-AUC曲线:
在机器学习研究$[4]$中,可以引入一种简单的超参数调整方法——贝叶斯优化,贝叶斯优化比网格或随机搜索策略能更快地找到最优值。
- https://www.researchgate.net/publication/225175169
- https://en.wikipedia.org/wiki/Bayesian_optimization
- https://github.com/fmfn/BayesianOptimization
- https://addepto.com/automated-machine-learning-tasks-can-be-improved/
作者信息
文由阿里云开发者社区组织翻译。
文章原标题《XGBoost and Random Forest with Bayesian Optimisation》
作者:Edwin Lisowski
译者:海棠
文章为简译,更为详细的内容,请查看原文