梯度提升是一种强大的机器学习技术,它通过组合多个弱预测模型来构建一个强预测模型。这种方法既可以用于回归问题,也可以用于分类问题。在本例中,将使用梯度提升回归模型来处理糖尿病回归任务。将使用GradientBoostingRegressor,它使用最小二乘损失函数和500个深度为4的回归树。对于更大的数据集(n_samples >= 10000),请参考HistGradientBoostingRegressor。
首先,需要加载数据。将使用sklearn库中的datasets模块来加载糖尿病数据集。然后,将数据分为特征矩阵X和目标变量y。
from sklearn import datasets
diabetes = datasets.load_diabetes()
X, y = diabetes.data, diabetes.target
接下来,将数据集分为90%的训练集和10%的测试集。还将设置回归模型的参数。这些参数可以调整,以观察结果的变化。
from sklearn.model_selection import train_test_split
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
from sklearn.metrics import mean_squared_error
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("测试集的平均平方误差(MSE):{:.4f}".format(mse))
最后,将可视化结果。为此,首先计算测试集的偏差,然后将其与提升迭代次数绘制在一起。
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()
注意,基于不纯度的特征重要性可能对高基数特征(许多唯一值)具有误导性。作为替代方案,可以在保留的测试集上计算reg的排列重要性。有关更多详细信息,请参见排列特征重要性。
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()