使用Scikit-learn训练GradientBoostingRegressor
引言
在机器学习领域,梯度提升(Gradient Boosting)是一种强大且广泛使用的集成学习算法。它通过串行方式构建一系列弱学习器(通常是决策树),每一棵树都在修正前一棵树的预测误差,从而形成一个强预测模型。Scikit-learn提供了GradientBoostingRegressor类,让我们可以方便地在Python中应用这一算法进行回归任务。
本文将带你从零开始,系统学习如何使用Scikit-learn训练GradientBoostingRegressor模型,涵盖原理、关键参数、完整代码实战以及模型调优等内容。
一、GradientBoostingRegressor的核心原理
梯度提升回归的核心思想是加法模型与前向分步算法。简单来说:
- 首先用一个初始模型(通常是目标值的均值)进行预测
- 计算残差(真实值与预测值的差)
- 训练一棵决策树来拟合这个残差(即负梯度方向)
- 将新树的预测结果乘以学习率后加到模型中
- 重复步骤2-4,直到达到指定的树的数量
这种“错误驱动学习”机制使得模型能够逐步逼近真实目标函数。
💡 小提示:如果你的数据集较大(
n_samples >= 10000),可以考虑使用HistGradientBoostingRegressor,它是GradientBoostingRegressor的更快变体。
二、关键参数详解
在使用GradientBoostingRegressor之前,理解其核心参数至关重要。
| 参数 | 默认值 | 说明 |
|---|---|---|
loss |
'squared_error' |
损失函数。可选'squared_error'(平方误差)、'absolute_error'(绝对误差)、'huber'(二者的结合)、'quantile'(分位数回归) |
learning_rate |
0.1 |
学习率,控制每棵树的贡献缩水程度。learning_rate与n_estimators之间存在权衡 |
n_estimators |
100 |
boosting的迭代次数(树的数量)。梯度提升对过拟合较为鲁棒,较大的值通常效果更好 |
max_depth |
3 |
每棵决策树的最大深度,限制树的复杂度 |
subsample |
1.0 |
用于拟合每棵树的样本比例。小于1.0时即为随机梯度提升,可降低方差但增加偏差 |
criterion |
'friedman_mse' |
衡量分裂质量的标准,'friedman_mse'通常效果最佳 |
min_samples_split |
2 |
内部节点再划分所需的最小样本数 |
min_samples_leaf |
1 |
叶节点所需的最小样本数 |
random_state |
None |
随机种子,保证结果可复现 |
三、完整实战案例
下面我们以Scikit-learn自带的糖尿病数据集为例,完整演示训练过程。
3.1 导入所需库
import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets, ensemble
from sklearn.inspection import permutation_importance
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
3.2 加载并准备数据
# 加载糖尿病数据集
diabetes = datasets.load_diabetes()
X, y = diabetes.data, diabetes.target
# 划分训练集和测试集(90%训练,10%测试)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.1, random_state=13
)
3.3 配置并训练模型
# 设置模型参数
params = {
'n_estimators': 500, # 500棵树
'max_depth': 4, # 每棵树最大深度为4
'min_samples_split': 2, # 内部节点最小样本数
'learning_rate': 0.01, # 学习率
'loss': 'squared_error' # 平方误差损失
}
# 创建并训练模型
reg = ensemble.GradientBoostingRegressor(**params)
reg.fit(X_train, y_train)
训练完成后,模型就学习到了数据中的模式。
3.4 模型预测与评估
# 在测试集上进行预测
y_pred = reg.predict(X_test)
# 计算均方误差(MSE)
mse = mean_squared_error(y_test, y_pred)
print(f"测试集MSE: {mse:.4f}")
3.5 绘制训练过程中的偏差变化
GradientBoostingRegressor提供了staged_predict()方法,可以获取每一轮boosting迭代后的预测结果,帮助我们观察模型的收敛情况。
# 计算每一轮迭代后在测试集上的偏差
test_score = np.zeros((params['n_estimators'],), dtype=np.float64)
for i, y_pred_iter in enumerate(reg.staged_predict(X_test)):
test_score[i] = reg.loss_(y_test, y_pred_iter)
# 绘制训练集和测试集的偏差曲线
plt.figure(figsize=(10, 5))
plt.plot(np.arange(params['n_estimators']) + 1, reg.train_score_, 'b-',
label='训练集偏差')
plt.plot(np.arange(params['n_estimators']) + 1, test_score, 'r-',
label='测试集偏差')
plt.legend(loc='upper right')
plt.xlabel('Boosting迭代次数')
plt.ylabel('偏差')
plt.title('训练过程中的偏差变化')
plt.show()
通过这张图,我们可以判断模型是否在某个迭代次数后开始过拟合。
四、特征重要性分析
GradientBoostingRegressor训练完成后,可以通过feature_importances_属性获取每个特征的重要性分数。重要性分数越高,表示该特征对预测结果的影响越大。
# 获取特征重要性
feature_importance = reg.feature_importances_
# 归一化到百分比
feature_importance = 100.0 * (feature_importance / feature_importance.max())
# 按重要性排序并绘图
sorted_idx = np.argsort(feature_importance)
pos = np.arange(sorted_idx.shape[0]) + 0.5
plt.figure(figsize=(10, 6))
plt.barh(pos, feature_importance[sorted_idx], align='center')
plt.yticks(pos, np.array(diabetes.feature_names)[sorted_idx])
plt.xlabel('相对重要性 (%)')
plt.title('特征重要性排序')
plt.tight_layout()
plt.show()
五、超参数调优
为了获得更好的模型性能,通常需要进行超参数调优。以下是一个使用GridSearchCV进行网格搜索的示例:
from sklearn.model_selection import GridSearchCV
# 定义参数网格
param_grid = {
'n_estimators': [100, 200, 300],
'max_depth': [3, 4, 5],
'learning_rate': [0.01, 0.05, 0.1],
'subsample': [0.8, 1.0]
}
# 创建GridSearchCV对象
gb = ensemble.GradientBoostingRegressor(random_state=42)
grid_search = GridSearchCV(
estimator=gb,
param_grid=param_grid,
cv=5, # 5折交叉验证
scoring='neg_mean_squared_error',
n_jobs=-1
)
# 执行网格搜索
grid_search.fit(X_train, y_train)
# 输出最优参数
print(f"最优参数: {grid_search.best_params_}")
print(f"最优交叉验证得分: {-grid_search.best_score_:.4f}")
六、高级特性
6.1 早停法(Early Stopping)
Scikit-learn的GradientBoostingRegressor支持通过n_iter_no_change、validation_fraction和tol参数实现早停,当验证集上的得分在若干轮迭代中没有改善时自动停止训练。
reg_early_stop = ensemble.GradientBoostingRegressor(
n_estimators=1000, # 设置较大的初始值
validation_fraction=0.1, # 10%的数据作为验证集
n_iter_no_change=10, # 连续10轮无改善则停止
tol=0.001, # 改善阈值
random_state=42
)
reg_early_stop.fit(X_train, y_train)
print(f"实际使用的树的数量: {reg_early_stop.n_estimators_}")
6.2 增量训练(warm_start)
warm_start=True允许在已有模型的基础上继续添加更多的树:
# 先训练100棵树
reg = ensemble.GradientBoostingRegressor(n_estimators=100, warm_start=True)
reg.fit(X_train, y_train)
# 再增加100棵树(在已有模型基础上继续训练)
reg.set_params(n_estimators=200)
reg.fit(X_train, y_train) # 不会重新开始,而是在现有模型上继续
- 点赞
- 收藏
- 关注作者
评论(0)