梯度提升是一种集成学习方法,它通过组合多个弱预测模型来构建一个强预测模型。这种方法可以用于回归和分类问题。本文将介绍如何使用梯度提升回归模型来处理糖尿病数据集的回归问题。将使用最小二乘损失函数和500个深度为4的回归树来训练模型。对于更大的数据集(样本数大于等于10000),建议使用HistGradientBoostingRegressor。
首先,需要加载数据。糖尿病数据集是一个常用的回归数据集,包含了糖尿病患者的10个生理变量。将数据集分为90%的训练集和10%的测试集。此外,还将设置回归模型的参数,包括提升阶段的数量、树的最大深度、内部节点分裂所需的最小样本数、每个树的贡献缩小比例以及优化的损失函数。
from sklearn import datasets, ensemble
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
# 加载数据集
diabetes = datasets.load_diabetes()
X, y = diabetes.data, diabetes.target
# 数据集划分
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=13)
接下来,将初始化梯度提升回归器,并使用训练数据来拟合它。还将计算测试数据上的均方误差(MSE)。
from sklearn.ensemble import GradientBoostingRegressor
# 设置模型参数
params = {
"n_estimators": 500,
"max_depth": 4,
"min_samples_split": 5,
"learning_rate": 0.01,
"loss": "squared_error"
}
# 训练模型
reg = GradientBoostingRegressor(**params)
reg.fit(X_train, y_train)
# 计算均方误差
mse = mean_squared_error(y_test, reg.predict(X_test))
print(f"测试集上的均方误差(MSE): {mse:.4f}")
最后,将可视化结果。首先计算测试集的偏差,然后将其与提升迭代次数作图。
import numpy as np
import matplotlib.pyplot as plt
# 计算测试集偏差
test_score = np.zeros((params["n_estimators"],), dtype=np.float64)
for i, y_pred in enumerate(reg.staged_predict(X_test)):
test_score[i] = mean_squared_error(y_test, y_pred)
# 绘制偏差图
fig = plt.figure(figsize=(6, 6))
plt.subplot(1, 1, 1)
plt.title("偏差")
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("提升迭代次数")
plt.ylabel("偏差")
fig.tight_layout()
plt.show()
在高基数特征(许多唯一值)的情况下,基于不纯度的特征重要性可能会产生误导。作为替代方案,可以在保留的测试集上计算模型的排列重要性。本文中,基于不纯度和排列方法识别出的两个最强预测特征相同,但顺序不同。第三个最具预测性的特征“bp”在两种方法中也相同。其余特征的预测性较低,排列图中的误差条显示它们与0重叠。
# 计算特征重要性
feature_importance = reg.feature_importances_
sorted_idx = np.argsort(feature_importance)
# 绘制特征重要性图
pos = np.arange(sorted_idx.shape[0]) + 0.5
fig = plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.barh(pos, feature_importance[sorted_idx], align="center")
plt.yticks(pos, np.array(diabetes.feature_names)[sorted_idx])
plt.title("特征重要性(MDI)")
# 计算排列重要性
from sklearn.inspection import permutation_importance
result = permutation_importance(reg, X_test, y_test, n_repeats=10, random_state=42, n_jobs=2)
sorted_idx = result.importances_mean.argsort()
plt.subplot(1, 2, 2)
plt.boxplot(result.importances[sorted_idx].T, vert=False, labels=np.array(diabetes.feature_names)[sorted_idx])
plt.title("排列重要性(测试集)")
fig.tight_layout()
plt.show()
脚本总运行时间:0分钟1.439秒。
以下是一些相关的示例,它们展示了梯度提升模型的不同应用场景: