✨ 欢迎关注 ✨
本节介绍:XGBoost模型采用Early Stopping策略提高模型的泛化能力减少过拟合,作者根据个人对机器学习的理解进行代码实现与图表输出,仅供参考。 完整 数据和代码将在稍后上传至交流群,成员可在交流群中获取下载。需要的朋友可关注公众文末提供的获取方式。 获取 前请咨询,避免不必要的问题。
✨ 文献信息 ✨
文献中进行了数据预处理:首先,将数据集分为80%的训练集和20%的测试集。为了提高模型的泛化能力,进行皮尔逊相关性分析,筛选出多重共线性,以减少特征数量避免多重共线性影响,特征选择:通过SHAP值对16个初始特征的显著性进行评估,并排除一些影响力较小的特征。最终,构建一个包含13个关键特征的数据集,这些特征经过平衡考虑了特征的重要性、相关性和模型复杂度,这部分可以参考往期文章——期刊复现:基于Pearson相关分析与SHAP评估特征重要性优化特征减少冗余
模型开发采用XGBoost、支持向量机(SVM)、LightGBM、随机森林(RF)、CatBoost等算法。为了防止过拟合和过度训练,采用Early Stopping(早停)策略,即如果验证集的误差在连续50个训练轮次中没有改进,则停止训练,从而避免模型过拟合,当然这里以XGBoost为案例实现,性能评估在训练过程中使用多个评估指标,如确定系数(R²)和均方根误差(RMSE)。R² 用来评估模型的拟合度,而RMSE用来量化预测值与实际值之间的差异。通过这些指标对模型的性能进行比较和优化,同时进行超参数优化提高模型的表现,使用网格搜索法和5-fold交叉验证来评估模型的性能
接下来,主要的重点是在这些模型中实现XGBoost。XGBoost是一种极为流行的提升树模型,它以其高效的计算能力和较强的泛化能力广泛应用于回归和分类任务。在该过程中的模型开发部分,XGBoost是其中的一个重要算法,并且在通过早停策略防止过拟合、超参数优化等步骤后
✨ 基础代码 ✨
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'Times New Roman'
plt.rcParams['axes.unicode_minus'] = False
import warnings
# 忽略所有警告
warnings.filterwarnings("ignore")
path = r"2025-8-2公众号Python机器学习AI.xlsx"
df = pd.read_excel(path)
from sklearn.model_selection import train_test_split
# 划分特征和目标变量
X = df.drop(['SR', 'salinity', 'T', 'infpro'], axis=1) # 特征 https://mp.weixin.qq.com/s/V6tBbYxm157oZhtU7Dn4vg 多重共线性剔除
y = df['SR'] # 目标变量
# 划分训练集和测试集,测试集占 20%
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=42)
from sklearn.preprocessing import StandardScaler
import pickle
# 初始化标准化器
scaler = StandardScaler()
# 标准化训练集
X_train_scaled = scaler.fit_transform(X_train)
# 用相同参数标准化测试集
X_test_scaled = scaler.transform(X_test)
读取数据文件,划分特征和目标变量,剔除 'salinity'、'T' 和 'infpro' 这三个被认为存在多重共线性或SHAP贡献较低的特征后,使用标准化方法对训练集和测试集进行数据预处理,当然对于有些机器学习模型对于数据量纲并不敏感不进行标准化也没有问题,也方便后续对模型的解释在原始数据上进行,如XGBoost不需要标准化数据,也不太受量纲影响,但在某些情况下(如特征尺度差异过大时),标准化数据可能对训练过程和模型性能有一定的帮助
from xgboost import XGBRegressor
from sklearn.model_selection import GridSearchCV
# 定义超参数搜索范围
param_grid = {
'n_estimators': [100, 300], # 弱学习器数量 树的数量
'max_depth': [3, 5], # 树的最大深度
'learning_rate': [0.01, 0.1], # 学习率
'subsample': [0.6, 0.8], # 每棵树使用的数据采样比例
'colsample_bytree': [0.6, 0.8], # 每棵树使用的特征采样比例
'gamma': [0, 1], # 分裂节点所需的最小损失减少
'reg_alpha': [0.1, 1], # L1 正则化系数
'reg_lambda': [1.5, 2] # L2 正则化系数
}
# 初始化基础 XGBoost 模型
base_model = XGBRegressor(objective='reg:squarederror', random_state=42)
# 设置网格搜索
grid_search = GridSearchCV(
estimator=base_model, # 基础模型
param_grid=param_grid, # 超参数组合
scoring='neg_mean_squared_error', # 评价指标:负均方误差
cv=5, # 5 折交叉验证
verbose=2, # 输出搜索过程
n_jobs=-1 # 使用所有 CPU 核心加速
)
# 在训练集上进行网格搜索
grid_search.fit(X_train_scaled, y_train)
# 获取最佳超参数
best_params = grid_search.best_params_
通过网格搜索(GridSearchCV)在给定的超参数空间中寻找最优组合,以优化XGBoost回归模型的性能,这里还没有引入早停机制
# 使用最佳超参数初始化 XGBoost 模型
xgboost_model = XGBRegressor(**best_params, objective='reg:squarederror', random_state=42)
print("\nBest Parameters Found:")
print(best_params)
使用从网格搜索中获得的最佳超参数初始化一个新的XGBoost回归模型,并打印出最佳超参数组合
Best Parameters Found:
{'colsample_bytree': 0.6, 'gamma': 0, 'learning_rate': 0.1, 'max_depth': 5, 'n_estimators': 100, 'reg_alpha': 1, 'reg_lambda': 1.5, 'subsample': 0.8}
这里显示了通过网格搜索得到的最佳超参数组合,用于优化XGBoost回归模型的性能
XGBoost早停(Early Stopping)是一种用于防止过拟合的技巧,它通过在训练过程中监控模型的表现,自动停止训练,以避免模型在训练集上过度拟合,从而提高模型在未知数据上的泛化能力,在每次迭代中,XGBoost会使用训练数据训练模型,并通过交叉验证或验证集评估模型的表现。每次迭代后,计算模型在验证集上的损失(如均方误差),在每一轮训练之后,XGBoost会评估模型在验证集上的性能。如果验证集的性能没有得到提升(即验证集的损失没有显著下降),训练过程就会提前停止。这样可以防止模型在训练集上训练得过多,导致过拟合。然后它会改变你的模型参数
Fold 1 - Early Stopping Best Iteration: 97
Fold 2 - Early Stopping Best Iteration: 80
Fold 3 - Early Stopping Best Iteration: 75
Fold 4 - Early Stopping Best Iteration: 58
Fold 5 - Early Stopping Best Iteration: 46
Average Training Set Results:
Average R²: 0.9799354786447795
Average RMSE: 3.957077228559158
Average Test Set Results:
Average R²: 0.8649901276335829
Average RMSE: 10.20956007910245
这里是使用5折交叉验证(KFold)对XGBoost模型进行训练和评估,采用Early Stopping来防止过拟合。每一折中,数据被划分为训练集、验证集和测试集(不是实际的测试集),模型首先在训练集上训练,然后通过验证集来确定最佳的迭代轮数(通过early_stopping_rounds)。最终,模型会在训练集和测试集上进行预测,计算并记录R²和RMSE 评分,以评估模型在训练集和测试集上的表现,最后输出这些指标的平均值
这个参数变化的原因是因为原始数据没有单独划分验证集,而是利用K折交叉验证在训练集内额外进行训练集、验证集和测试集的划分。在每一折中,模型使用训练集进行训练,使用验证集来进行早停(确定最佳迭代次数),然后使用测试集计算最终结果。第一次早停时,模型的n_estimators参数默认为网格搜索和K折交叉验证得到的初始值('n_estimators': 100),但早停后,该参数被调整为最佳迭代次数(97)。接下来,模型会在此基础上继续迭代,并在每次早停时调整迭代次数,直到最后一折得到58。与直接划分验证集的做法不同,K折交叉验证不仅可以用于早停,还能帮助评估模型在不同数据子集上的表现,从而判断模型的稳定性,当然更详细的内容直接参考上传的代码会更方便,理解更透彻
print("XGBoost Model Parameters:")
for param, value in xgboost_model.get_params().items():
print(f"{param}: {value}")
打印出XGBoost模型的所有超参数及其当前值,可以发现通过早停修改的是n_estimators参数,并可以与之前通过 K折交叉验证和网格搜索得到的初始结果进行对比,查看其它模型参数是否有变化
XGBoost Model Parameters:
objective: reg:squarederror
base_score: None
booster: None
callbacks: None
colsample_bylevel: None
colsample_bynode: None
colsample_bytree: 0.6
device: None
early_stopping_rounds: None
enable_categorical: False
eval_metric: None
feature_types: None
gamma: 0
grow_policy: None
importance_type: None
interaction_constraints: None
learning_rate: 0.1
max_bin: None
max_cat_threshold: None
max_cat_to_onehot: None
max_delta_step: None
max_depth: 5
max_leaves: None
min_child_weight: None
missing: nan
monotone_constraints: None
multi_strategy: None
n_estimators: 46
n_jobs: None
num_parallel_tree: None
random_state: 42
reg_alpha: 1
reg_lambda: 1.5
sampling_method: None
scale_pos_weight: None
subsample: 0.8
tree_method: None
validate_parameters: None
verbosity: None
# xgboost_model = grid_search.best_estimator_ 如果这里获取前面网格搜索中训练得到的最佳模型那么参数将是'n_estimators': 100 早停就没有其作用
# 在训练集和测试集上进行预测
xgboost_train_pred = xgboost_model.predict(X_train_scaled)
xgboost_test_pred = xgboost_model.predict(X_test_scaled)
# 计算训练集的 R² 和 RMSE
xgboost_r2_train = r2_score(y_train, xgboost_train_pred)
xgboost_rmse_train = np.sqrt(mean_squared_error(y_train, xgboost_train_pred))
# 计算测试集的 R² 和 RMSE
xgboost_r2_test = r2_score(y_test, xgboost_test_pred)
xgboost_rmse_test = np.sqrt(mean_squared_error(y_test, xgboost_test_pred))
# 输出结果
print(f"xgboost 训练集结果: R² = {xgboost_r2_train:.4f}, RMSE = {xgboost_rmse_train:.4f}")
print(f"xgboost 测试集结果: R² = {xgboost_r2_test:.4f}, RMSE = {xgboost_rmse_test:.4f}")
对训练集X_train_scaled和测试集X_test_scaled进行预测,并计算R²和RMSE评价指标,最后输出训练集和测试集的结果。需要注意的是,这里的训练集和测试集是最开始划分得到的原始数据集,而使用的xgboost_model是通过K折交叉验证对原始训练集进行划分后训练得到的模型。如果重新用当前的xgboost_model对原始训练集进行训练,会得到一个基于早停优化后的模型(n_estimators: 46),但是性能略有不同,因为训练数据发生了变化,但模型参数未变
xgboost 训练集结果: R² = 0.9514, RMSE = 6.2884
xgboost 测试集结果: R² = 0.8805, RMSE = 9.9375
这里的结果是对原始 训练集和测试集得到的 ,使用的xgboost_model是通过K折交叉验证对原始训练集进行划分后训练得到的模型,下图为这种情况下的原始训练集和测试集可视化
xgboost_model = xgboost_model.fit(X_train_scaled, y_train)
# 在训练集和测试集上进行预测
xgboost_train_pred = xgboost_model.predict(X_train_scaled)
xgboost_test_pred = xgboost_model.predict(X_test_scaled)
# 计算训练集的 R² 和 RMSE
xgboost_r2_train = r2_score(y_train, xgboost_train_pred)
xgboost_rmse_train = np.sqrt(mean_squared_error(y_train, xgboost_train_pred))
# 计算测试集的 R² 和 RMSE
xgboost_r2_test = r2_score(y_test, xgboost_test_pred)
xgboost_rmse_test = np.sqrt(mean_squared_error(y_test, xgboost_test_pred))
# 输出结果
print(f"xgboost 训练集结果: R² = {xgboost_r2_train:.4f}, RMSE = {xgboost_rmse_train:.4f}")
print(f"xgboost 测试集结果: R² = {xgboost_r2_test:.4f}, RMSE = {xgboost_rmse_test:.4f}")
当前的xgboost_model对原始训练集X_train_scaled进行重新训练,得到一个基于早停优化后的模型(n_estimators: 46),然后在原始训练集和测试集上进行预测,并计算相应评价指标。通过这种方式,模型会在原始的训练集上进行拟合,并根据早停调整后的参数进行预测,从而可能导致性能上的细微变化
xgboost 训练集结果: R² = 0.9642, RMSE = 5.4008
xgboost 测试集结果: R² = 0.8860, RMSE = 9.7041
这个结果是 基于早停优化后模型在原始训练集、测试集上的结果
# 获取通过网格搜索得到的最佳模型(包括最佳超参数)
grid_xgboost_model = grid_search.best_estimator_
# 在训练集和测试集上进行预测
grid_xgboost_train_pred = grid_xgboost_model.predict(X_train_scaled)
grid_xgboost_test_pred = grid_xgboost_model.predict(X_test_scaled)
# 计算训练集的 R² 和 RMSE
grid_xgboost_r2_train = r2_score(y_train, grid_xgboost_train_pred)
grid_xgboost_rmse_train = np.sqrt(mean_squared_error(y_train, grid_xgboost_train_pred))
# 计算测试集的 R² 和 RMSE
grid_xgboost_r2_test = r2_score(y_test, grid_xgboost_test_pred)
grid_xgboost_rmse_test = np.sqrt(mean_squared_error(y_test, grid_xgboost_test_pred))
# 输出结果
print(f"XGBoost 训练集结果: R² = {grid_xgboost_r2_train:.4f}, RMSE = {grid_xgboost_rmse_train:.4f}")
print(f"XGBoost 测试集结果: R² = {grid_xgboost_r2_test:.4f}, RMSE = {grid_xgboost_rmse_test:.4f}")
这里是使用通过网格搜索和K折交叉验证得到的最佳模型(n_estimators: 100),在原始训练集X_train_scaled上进行训练,并计算训练集和测试集的R²和RMSE结果,未使用早停,因此得到的模型没有经过早停优化
XGBoost 训练集结果: R² = 0.9847, RMSE = 3.5247
XGBoost 测试集结果: R² = 0.8867, RMSE = 9.6753
可以发现早停确实有助于降低模型的过拟合程度。虽然没有使用早停的模型在训练集上表现更好(0.985),但它在测试集上的优势并不明显,说明其可能存在过拟合的风险。而使用早停的模型虽然在训练集上略逊一筹,但能保持在测试集上较为稳定的表现,且训练集和测试集性能更接近了,这表明早停能够有效控制过拟合,从而使模型更具泛化能力,需要注意的是,结合K折交叉验证和早停的方法会产生多个不同的模型(因为每次训练集的划分不同、每折都有自己的最佳迭代次数),因此,最简单的做法是直接对原始数据划分训练集、验证集、测试集,而不使用K折交叉验证,以避免不必要的复杂性,且 如果需要进行模型解释,应该基于早停优化后的模型而不是网格搜索得到的原始参数模型,因为早停会调整超参数(n_estimators),使得最终的模型更具泛化能力,并反映出实际训练过程中的表现
当然,公众号中还有更多机器学习期刊实战技巧,您可以通过历史文章进行检索和阅读,关注公众号,点击“发信息”>“历史文章”即可搜索公众号所有文章信息
✨ 该文章案例 ✨
在上传至交流群的文件中,像往期文章一样,将对案例进行逐步分析,确保读者能够达到最佳的学习效果。内容都经过详细解读,帮助读者深入理解模型的实现过程和数据分析步骤,从而最大化学习成果。
同时,结合提供的免费AI聚合网站进行学习,能够让读者在理论与实践之间实现融会贯通,更加全面地掌握核心概念。
✨ 介绍 ✨
本节介绍到此结束,有需要学习数据分析和Python机器学习相关的朋友欢迎到淘宝店铺:Python机器学习AI,下方提供淘宝店铺二维码获取作者的公众号合集。截至目前为止,合集已包含近300多篇文章,购买合集的同时,还将提供免费稳定的AI大模型使用。
更新的内容包含数据、代码、注释和参考资料。 作者仅分享案例项目,不提供额外的答疑服务。项目中将提供详细的代码注释和丰富的解读,帮助您理解每个步骤 。 获取 前请咨询,避免不必要的问题。
✨ 群友反馈 ✨
✨ 淘宝店铺 ✨
请大家打开淘宝扫描上方的二维码,进入店铺,获取更多Python机器学习和AI相关的内容 ,希望能为您的学习之路提供帮助!
往期推荐
期刊复现:连续数据与分类数据共存的SHAP可视化散点图与箱形图组合形式
期刊复现:多分类任务如何拆分为二分类任务并进行堆叠预测提高模型预测性能
期刊配图:SHAP值分析模型可解释性在柱状图与蜂窝图中的进阶组合展示
期刊配图:通过堆叠Mean|SHAP|展示不同区间对模型贡献度的可视化分析
期刊复现:利用UMAP降维算法可视化深度学习随着训练次数的增加模型区分能力的变化
期刊配图:PCA、t-SNE与UMAP三种降维方法简化高维数据的展示应用对比
Science期刊复现:分类、回归与Shap分析多角度揭示同一数据集变量对目标的影响
多模型SHAP+PDP解读Stacking集成模型:从基学习器到元学习器的可解释性与模型调参实现
如果你对类似于这样的文章感兴趣。
欢迎关注、点赞、转发~
个人观点,仅供参考