梯度提升算法与模型优化

机器学习领域,梯度提升算法是一种强大的集成学习方法,它通过迭代地训练模型来最小化损失函数。一个关键的挑战是确定最佳的迭代次数,即提升树的数量。本文将探讨如何使用袋外(OOB)误差和交叉验证来估计最优的迭代次数。

袋外误差是一种无需重复模型拟合即可即时计算的估计方法,它与交叉验证误差非常相似。OOB误差仅适用于随机梯度提升(即样本的子采样比例小于1.0),它基于未包含在自助样本中的样本(即所谓的袋外样本)的损失改进来计算。虽然OOB估计器是对真实测试损失的悲观估计,但对于少量树来说,它仍然是一个相当好的近似。

下图显示了负OOB改进的累积和作为提升迭代的函数。如图所示,它在前一百次迭代中跟踪测试损失,但随后以悲观的方式发散。图还显示了3折交叉验证的性能,这通常能给出更好的测试损失估计,但计算上更耗费资源。

在代码实现方面,首先导入了必要的库,包括matplotlib用于绘图,numpy用于数值计算,scipy.special中的expit函数用于计算逻辑函数,以及sklearn中的ensemble和metrics模块用于模型训练和评估。使用train_test_split函数将数据集分为训练集和测试集,然后使用GradientBoostingClassifier进行模型训练,并计算准确率。

import matplotlib.pyplot as plt import numpy as np from scipy.special import expit from sklearn import ensemble from sklearn.metrics import log_loss from sklearn.model_selection import KFold, train_test_split

接下来,定义了heldout_score函数来计算测试集上的偏差分数,并定义了cv_estimate函数来进行交叉验证。使用交叉验证来估计最佳的n_estimators(树的数量),并计算测试数据上的偏差分数。然后,计算了OOB改进的负累积和,并找到了最小损失对应的迭代次数。

def heldout_score(clf, X_test, y_test): """计算X_test和y_test上的偏差分数。""" score = np.zeros((n_estimators,), dtype=np.float64) for i, y_proba in enumerate(clf.staged_predict_proba(X_test)): score[i] = 2 * log_loss(y_test, y_proba[:, 1]) return score def cv_estimate(n_splits=None): cv = KFold(n_splits=n_splits) cv_clf = ensemble.GradientBoostingClassifier(**params) val_scores = np.zeros((n_estimators,), dtype=np.float64) for train, test in cv.split(X_train, y_train): cv_clf.fit(X_train[train], y_train[train]) val_scores += heldout_score(cv_clf, X_train[test], y_train[test]) val_scores /= n_splits return val_scores

最后,绘制了OOB损失、测试损失和交叉验证损失的曲线,并为最佳迭代次数添加了垂直线。使用不同的颜色和线型来区分这三条曲线,并在x轴上添加了标签和图例。

plt.figure(figsize=(8, 4.8)) plt.plot(x, cumsum, label="OOB损失", color=oob_color, linestyle=oob_line) plt.plot(x, test_score, label="测试损失", color=test_color, linestyle=test_line) plt.plot(x, cv_score, label="CV损失", color=cv_color, linestyle=cv_line) plt.axvline(x=oob_best_iter, color=oob_color, linestyle=oob_line) plt.axvline(x=test_best_iter, color=test_color, linestyle=test_line) plt.axvline(x=cv_best_iter, color=cv_color, linestyle=cv_line) plt.legend(loc="upper center") plt.ylabel("归一化损失") plt.xlabel("迭代次数") plt.show()
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485