S'S ALGORITHM

XGBoost梯度提升算法:过程示例


在机器学习领域,XGBoost(eXtreme Gradient Boosting)算法因其出色的性能和广泛应用而备受瞩目。决策树算法本身就是一种优秀的算法了,现在XGBoost算法,让人拥有一大片森林哈哈。

一,XGBoost的原理

XGBoost是一种梯度提升树算法,它通过组合多个弱学习器(通常是决策树)以提高模型性能。是一种监督学习算法。其主要特点包括:

具体来说梯度提升算法(Gradient Boosting Algorithm)是一种集成学习方法,属于监督学习的范畴。它通过逐步构建弱学习器(通常是决策树)来改善模型的性能,弥补单个弱学习器的不足。梯度提升算法的核心思想是通过合并多个弱模型,每次关注前一轮模型的预测误差,从而逐步提升整体模型的预测能力。

XGBoost支持并行处理和分布式计算,使其在处理大规模数据时更为高效。另外,通过监控模型性能,XGBoost能够在模型过拟合之前自动停止训练,提高训练效率。

二,梯度提升算法的基本步骤:

梯度提升算法的名字中包含了”梯度”一词,是因为它通过利用损失函数在当前模型下对训练数据的负梯度来指导模型的更新。这就是”梯度提升”一词的来源。

梯度提升算法的优势在于它的灵活性、鲁棒性和高性能。它可以适应各种类型的数据和问题,包括回归、分类和排序等任务。著名的梯度提升算法包括XGBoost、LightGBM和CatBoost等。

三,XGBoost的基础:数据结构和核心组件

下面是基础部分的代码。关注最初的部分,有一个叫做 DMatrix 的数据结构,这是XGBoost的核心结构,内置的一种矩阵,但是是适应了算法的分布式和并行计算的结构。总之就是这么定义的。只要将数据和标签组合,就可以设置需要进行训练的数据对象。在下面的例子中就是 dtrain。

# data = np.array([
#   [1.2, 3.3, 1.4],
#   [5.1, 2.2, 6.6]])
# labels = np.array([0, 1])
import xgboost as xgb
dtrain = xgb.DMatrix(data, label=labels)

训练部分的核心组件就是模型booster,在训练的时候,可以对训练设置参数。如下是一个二分类算法的参数,定义了训练的树的最大深度,目标,评估标准。目标明示是一个二分类任务,使用逻辑回归的方法。如果是多分类,则可以定义softmax方法,这里关注注释掉的部分,定义了树的深度为2,这是因为这里假设数据集很小不需要很深的训练,最后定义了多分类的类别数量为3。

# training parameters
params = {
  'max_depth': 0,  # no limit on tree depth
  'objective': 'binary:logistic',
  'eval_metric':'logloss'
}

# params = {
#     'max_depth': 2,
#     'objective': 'multi:softmax',
#     'num_class': 3,
# }

print('Start training')
bst = xgb.train(params, dtrain)  # booster
print('Finish training')

使用训练好的核心组件booster进行评估和预测,只要用内置的evalpredict方法即可。

# evaluate
deval = xgb.DMatrix(eval_data, label=eval_labels)
res = bst.eval(deval)  # evaluation
print(res)

# prediction
dpred = xgb.DMatrix(new_data)
# predictions represents probabilities
predictions = bst.predict(dpred)
print(predictions)

XGBoost中的交叉验证

交叉验证(Cross-Validation)是一种常用的评估机器学习模型性能的方法。它通过将数据集分成训练集和验证集,反复地使用不同的训练集和验证集组合来训练和评估模型,从而更准确地评估模型的泛化能力。交叉验证通常用于选择模型的超参数,评估不同模型之间的性能,以及评估特征的重要性等。

在这里可以使用 cv 方法来实现。

首先要确定要进行交叉验证的超参数空间,也就是上面那一部分中提到的 params 这通常包括决定树的数量、树的最大深度、学习率等参数。然后指定交叉验证策略,主要也就是选择交叉验证的折数(folds默认是3)即将数据集分成多少份进行交叉验证。提升迭代的次数(num_boost_round),每次提升迭代都会尝试通过梯度提升来改进模型。默认迭代次数为 10。执行交叉验证,调用 cv 方法,传入训练数据、参数空间和交叉验证策略。XGBoost将自动执行交叉验证过程,并返回每次交叉验证的性能指标,如平均训练误差和平均验证误差等。最终根据交叉验证结果,选择性能最佳的模型,并使用最佳参数进行训练。通常可以根据验证误差选择最佳的超参数组合。

dtrain = xgb.DMatrix(data, label=labels)
params = {
  'max_depth': 2,
  'lambda': 1.5,
  'objective':'binary:logistic',
  'eval_metric':'logloss'

}
cv_results = xgb.cv(
    dtrain=dtrain, 
    params=params, 
    nfold=5, 
    num_boost_round=5, 
    metrics='merror', 
    seed=42
    )
print(f'CV Results: {cv_results}')

它的输出结果类似如下:

CV Results:
   train-logloss-mean  train-logloss-std  test-logloss-mean  test-logloss-std
0            0.483158           0.003513           0.495192          0.004461
1            0.358339           0.002811           0.385320          0.003426
2            0.278666           0.004171           0.312824          0.001838
3            0.224486           0.005180           0.268105          0.001441
4            0.184866           0.006320           0.234053          0.003650

是一个DataFrame对象,其中包含了每次交叉验证的性能指标,比如上面就是平均训练对数误差、训练对数误差的标准差,平均验证对数误差,验证对数误差的标准差等。DataFrame对象的每一行代表一个交叉验证的结果,列则对应不同的性能指标和迭代次数。下面是其他一些常见的列以及它们的含义:

通常的做法还有将这个DF可视化图表进行分析等。

模型save&load

load的时候需要初始化模型后load,其他着实没什么可多说,直接上代码。

bst.save_model('model.bin')

# Load saved Booster
new_bst = xgb.Booster()
new_bst.load_model('model.bin')

xgboost中可以和scikit-learn库无缝连接的API

统计类小数据set的分析,主流使用scikit-learn,为了集成,xgboost中提供了相应了api可以无缝连接scikit-learn的语法。

分类器和回归器示例:

import xgboost as xgb
model_clf = xgb.XGBClassifier(objective='multi:softmax', eval_metric='mlogloss', use_label_encoder=False)
model_clf.fit(data, labels)
predictions = model_clf.predict(new_data)

model_reg = xgb.XGBRegressor(max_depth=2)
model_reg.fit(data, labels)
predictions = model_reg.predict(new_data)

这里的use_label_encoder是指需不需要模型对非数字类型的标签进行编码。

下面这个简单的例子,以波士顿房价数据库为例,使用xgboost对回归模型和sklearn。作为一个集成api示例。

import xgboost as xgb
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error

# 加载波士顿房价数据集
boston = load_boston()
X, y = boston.data, boston.target

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建 XGBoost 回归模型
model = xgb.XGBRegressor(objective='reg:squarederror', random_state=42)

# 训练模型
model.fit(X_train, y_train)

# 在测试集上进行预测
y_pred = model.predict(X_test)

# 计算均方根误差(Root Mean Squared Error)
rmse = mean_squared_error(y_test, y_pred, squared=False)
print("Root Mean Squared Error:", rmse)

重要特征排序

使用model.feature_importances_可以查看在模型中哪些特征的重要度更高。

还可以通过 matplotlib 库和 xgboost 的内置方法组合绘出特征重要性的横向直方图。

import matplotlib.pyplot as plt
xgb.plot_importance(model)
plt.show()

绘图会显示特征的索引下标,以FX表示,F1表示index为1的特征。

重要性比较的标准默认为在决策树中该特征出现的次数。还可以设置别的标准,比如信息增益(information gain),

信息增益:信息增益的计算依赖于信息熵(Entropy)。信息熵是度量数据集的混乱程度的指标,它表示在给定的数据集中随机选择一个样本的时候,这个样本所含信息的平均量。信息增益越大,表示使用特征进行分裂能够带来更多的信息量,即使得子集更加纯净,样本更倾向于属于同一类别。

xgb.plot_importance(model, importance_type='gain')
plt.show()

另外还可以使图表不现实数值,以及保存为图片等选项。

xgb.plot_importance(model, show_values=False)
plt.savefig('importances.png')

利用GridSearchCV进行调参

使用scikit-learn的api封装xgboost的模型的另一个好处就是可以方便地使用sk的网格搜索。

model = xgb.XGBClassifier(objective='binary:logistic', eval_metric='logloss', use_label_encoder=False)
params = {'max_depth': range(2, 5)}

from sklearn.model_selection import GridSearchCV
cv_model = GridSearchCV(model, params, cv=4)

cv_model.fit(data, labels)
print(f'Best max_depth: {cv_model.best_params_['max_depth']}')
print(f'Predictions: {cv_model.predict(new_data)}')

补充解释:

交叉验证(Cross-Validation)和网格搜索(Grid Search)是两个常用于模型选择和调优的技术,它们通常在机器学习中一起使用,但是它们解决的是不同的问题。

  1. 交叉验证: 交叉验证是一种评估模型性能的统计方法,它通过将数据集划分为训练集和测试集,并多次重复使用这一过程来评估模型的表现。常见的交叉验证方法包括 k 折交叉验证和留一交叉验证。在 k 折交叉验证中,将数据集分为 k 个子集,然后进行 k 次迭代,每次选择其中一个子集作为测试集,其余的子集作为训练集。最后,将 k 次迭代的结果进行平均,得到最终的评估指标,如准确率、精确度、召回率等。交叉验证可以更好地评估模型的泛化能力,减少由于数据分布不均匀或者随机性导致的评估误差。

  2. 网格搜索: 网格搜索是一种用于选择模型超参数的方法,它通过遍历指定的参数组合来搜索最优的参数组合。通常,我们会事先定义一个参数网格(grid),其中包含了我们希望调优的各种参数及其取值范围。然后,对于网格中的每一种参数组合,都会使用交叉验证来评估模型的性能。最终,选择在交叉验证中性能最好的参数组合作为最优参数,用于训练最终的模型。网格搜索能够帮助我们在给定的参数空间中寻找到最优的参数组合,从而提高模型的性能。

总的来说,交叉验证用于评估模型的性能,而网格搜索用于选择模型的最优超参数。这两个技术经常结合在一起使用,以帮助我们选择并构建出性能最好的模型。

使用joblib进行模型保存

同样这里的回归和分类模型可以像sklearn中的模型一样,使用joblib进行保存和载入。

from joblib import dump, load
dump(clf, 'filename.joblib') 
clf = load('filename.joblib') 

关于以上两种API范式

一般情况下,使用 xgb.DMatrix 直接构建 DMatrix 对象相比使用 XGBClassifierXGBRegressor 类构建模型更快一些,因为在后者中,还需要进行一些额外的处理,如参数解析、模型初始化等。

直接使用 xgb.DMatrix 的优势在于它更加灵活,可以接受各种类型的数据作为输入,比如 NumPy 数组、Pandas DataFrame、SciPy 稀疏矩阵等,而不仅仅局限于 scikit-learn 的输入格式。因此,在处理特殊数据格式或需要更多控制的情况下,使用 xgb.DMatrix 可能更为合适。

但是,对于一般情况下的数据处理和建模任务,使用 XGBClassifierXGBRegressor 类更为方便和直观,因为它们更符合 scikit-learn 的 API 规范,同时也提供了更多的功能和选项。因此,在实际应用中,可以根据具体需求来选择使用哪种方式。