背景
在机器学习的回归任务中,不同模型的选择和性能评估对于提升预测效果和避免模型过拟合、欠拟合至关重要,本文参考 Wei Zhuang 等人在《Water Research》期刊上发表的研究文章,该文采用了多种机器学习模型对数据集进行预测,并通过 R² 和 RMSE 等评价指标分析了模型在不同数据集上的表现——图a
在此基础上,本文对其进行扩展,采用CatBoost、XGBoost、随机森林等集成学习模型,对模型在训练集、验证集和测试集上的性能进行全面对比分析,同时,通过结合小提琴图和折线图的可视化方法,直观地展示各个模型在不同数据集上的表现,帮助更好地理解模型的泛化能力及其在不同条件下的稳定性,详细的图形解读放在代码可视化输出后,这里是回归预测模型,分类模型作图同理
代码实现
数据读取分割
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore")
plt.rcParams['font.family'] = 'Times New Roman'
plt.rcParams['axes.unicode_minus'] = False
df = pd.read_excel('2024-10-26-公众号Python机器学习AI.xlsx')
from sklearn.model_selection import train_test_split, KFold
X = df.drop(['待预测变量Y'],axis=1)
y = df['待预测变量Y']
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
df.head()
加载Excel数据集,提取特征和目标变量,并将数据集划分为训练集和测试集,为后续机器学习模型的训练和测试做好准备
模型构建
catboost模型
from sklearn.metrics import r2_score
from catboost import CatBoostRegressor
from sklearn.model_selection import KFold
# CatBoost模型参数
params_cat = {
'learning_rate': 0.02, # 学习率,控制每一步的步长,用于防止过拟合。典型值范围:0.01 - 0.1
'iterations': 1000, # 弱学习器(决策树)的数量
'depth': 6, # 决策树的深度,控制模型复杂度
'eval_metric': 'R2', # 评估指标,改为R2(拟合优度)
'random_seed': 42, # 随机种子,用于重现模型的结果
'verbose': 500 # 控制CatBoost输出信息的详细程度,每500次迭代输出一次
}
# 准备k折交叉验证
kf = KFold(n_splits=10, shuffle=True, random_state=42)
scores_train = []
scores_val = []
best_score = -np.inf # R2的最佳值越大越好
best_model = None
# 交叉验证
for fold, (train_index, val_index) in enumerate(kf.split(X_train, y_train)):
X_train_fold, X_val_fold = X_train.iloc[train_index], X_train.iloc[val_index]
y_train_fold, y_val_fold = y_train.iloc[train_index], y_train.iloc[val_index]
model = CatBoostRegressor(**params_cat)
model.fit(X_train_fold, y_train_fold, eval_set=(X_val_fold, y_val_fold), early_stopping_rounds=100)
# 预测训练集和验证集
y_train_pred = model.predict(X_train_fold)
y_val_pred = model.predict(X_val_fold)
# 计算训练集和验证集的R²
score_train = r2_score(y_train_fold, y_train_pred)
score_val = r2_score(y_val_fold, y_val_pred)
scores_train.append(score_train)
scores_val.append(score_val)
print(f'第 {fold + 1} 折 训练集 R²: {score_train}, 验证集 R²: {score_val}')
# 保存得分最好的模型
if score_val > best_score: # R² 越大越好
best_score = score_val
best_model_cat = model
# 保存2024-10-26-公众号Python机器学习AI训练集和验证集的R²分数为DataFrame
df_scores_catboost = pd.DataFrame({
'catboost_train': scores_train,
'catboost_val': scores_val
})
df_scores_catboost
定义CatBoost回归模型的参数,使用10折交叉验证将训练数据分成10个子集,在每一折中训练模型并在验证集上评估性能,计算每一折训练集和验证集的R²分数(拟合优度),同时记录并保存验证集上表现最好的模型,最终将所有折的R²分数存储在一个DataFrame中用于后续分析
xgboost
import xgboost as xgb
# XGBoost回归模型参数
params_xgb = {
'learning_rate': 0.02, # 学习率
'booster': 'gbtree', # 梯度提升树
'objective': 'reg:squarederror', # 损失函数
'max_leaves': 127, # 控制模型复杂度
'verbosity': 1, # 控制输出信息
'seed': 42, # 随机种子
'nthread': -1, # 并行线程数量
'colsample_bytree': 0.6, # 每棵树随机选择的特征比例
'subsample': 0.7, # 随机选择的样本比例
'eval_metric': 'rmse' # 使用RMSE作为评价指标
}
# 初始化XGBoost回归模型
model_xgb = xgb.XGBRegressor(**params_xgb)
# 准备10折交叉验证
kf = KFold(n_splits=10, shuffle=True, random_state=42)
# 准备存储每折训练集和验证集的拟合优度分数
scores_train_xgb = []
scores_val_xgb = []
# 初始化最好的模型和最高的验证集分数
best_model = None
best_val_score = -np.inf # 因为我们使用的是 R²,越大越好,所以初始值设为-inf
# 交叉验证
for fold, (train_index, val_index) in enumerate(kf.split(X_train)):
X_train_fold, X_val_fold = X_train.iloc[train_index], X_train.iloc[val_index]
y_train_fold, y_val_fold = y_train.iloc[train_index], y_train.iloc[val_index]
# 训练模型
model_xgb.fit(X_train_fold, y_train_fold)
# 预测训练集和验证集
y_train_pred = model_xgb.predict(X_train_fold)
y_val_pred = model_xgb.predict(X_val_fold)
# 计算训练集和验证集的R²
score_train_xgb = r2_score(y_train_fold, y_train_pred)
score_val_xgb = r2_score(y_val_fold, y_val_pred)
scores_train_xgb.append(score_train_xgb)
scores_val_xgb.append(score_val_xgb)
# 保存验证集分数最好的2024-10-26-公众号Python机器学习AI模型
if score_val_xgb > best_val_score:
best_val_score = score_val_xgb
best_model_xgb = model_xgb
print(f'第 {fold + 1} 折 训练集 R²: {score_train_xgb}, 验证集 R²: {score_val_xgb}')
# 保存XGBoost模型的训练集和验证集的R²分数为DataFrame
df_scores_xgb = pd.DataFrame({
'xgboost_train': scores_train_xgb,
'xgboost_val': scores_val_xgb
})
# 将CatBoost和XGBoost的结果合并
df_scores_combined = pd.concat([df_scores_catboost, df_scores_xgb], axis=1)
# 输出最佳模型和它的验证集 R² 分数
print('最佳模型:', best_model)
print(f'最佳验证集 R²: {best_val_score}')
df_scores_combined
定义XGBoost回归模型的参数,使用10折交叉验证对训练数据进行多次训练和验证,在每一折中计算训练集和验证集的R²分数,记录每一折的性能,并保存验证集上表现最好的模型,最后将XGBoost与之前的CatBoost模型的结果合并,综合展示两种模型在不同数据集上的表现,以便比较模型的泛化能力和选择最佳模型
RF
from sklearn.ensemble import RandomForestRegressor
# 随机森林回归模型参数
params_rf = {
'n_estimators': 100, # 树的数量
'max_depth': 7, # 每棵树的最大深度
'random_state': 42, # 随机种子
'n_jobs': -1, # 并行计算,使用所有CPU核心
'min_samples_split': 2, # 内部节点再分裂所需的最小样本数
'min_samples_leaf': 1 # 叶子节点包含的最小样本数
}
# 初始化随机森林回归模型
model_rf = RandomForestRegressor(**params_rf)
# 准备10折交叉验证
kf = KFold(n_splits=10, shuffle=True, random_state=42)
# 准备存储每折训练集和验证集的拟合优度分数
scores_train_rf = []
scores_val_rf = []
# 初始化最好的模型2024-10-26-公众号Python机器学习AI和最高的验证集分数
best_model_rf = None
best_val_score_rf = -np.inf # 因为R²越大越好,所以初始值设为-inf
# 交叉验证
for fold, (train_index, val_index) in enumerate(kf.split(X_train)):
X_train_fold, X_val_fold = X_train.iloc[train_index], X_train.iloc[val_index]
y_train_fold, y_val_fold = y_train.iloc[train_index], y_train.iloc[val_index]
# 训练模型
model_rf.fit(X_train_fold, y_train_fold)
# 预测训练集和验证集
y_train_pred = model_rf.predict(X_train_fold)
y_val_pred = model_rf.predict(X_val_fold)
# 计算训练集和验证集的R²
score_train_rf = r2_score(y_train_fold, y_train_pred)
score_val_rf = r2_score(y_val_fold, y_val_pred)
scores_train_rf.append(score_train_rf)
scores_val_rf.append(score_val_rf)
# 保存验证集分数最好的模型
if score_val_rf > best_val_score_rf:
best_val_score_rf = score_val_rf
best_model_rf = model_rf
print(f'第 {fold + 1} 折 训练集 R²: {score_train_rf}, 验证集 R²: {score_val_rf}')
# 保存随机森林模型的训练集和验证集的R²分数为DataFrame
df_scores_rf = pd.DataFrame({
'rf_train': scores_train_rf,
'rf_val': scores_val_rf
})
# 将CatBoost、XGBoost和RF的结果合并
df_scores_combined = pd.concat([df_scores_combined, df_scores_rf], axis=1)
# 输出最优模型及其验证集 R² 分数
print(f'最佳验证集 R²: {best_val_score_rf}')
print('最佳模型:', best_model_rf)
df_scores_combined
使用随机森林回归模型进行10折交叉验证,定义了模型的参数,如决策树的数量和最大深度等,并通过训练模型在每一折中计算训练集和验证集的R²分数,记录每一折的表现,保存在不同折上表现最佳的模型,最后将随机森林的结果与之前的CatBoost和XGBoost结果合并,输出最终的最优模型及其对应的验证集R²分数,用于比较不同模型的性能表现
lightgbm
import lightgbm as lgb
# LightGBM 回归模型参数
params_lgb = {
'learning_rate': 0.02, # 学习率
'boosting_type': 'gbdt', # 提升方式,使用梯度提升树
'objective': 'regression', # 回归任务
'metric': 'rmse', # 评价指标使用 RMSE
'n_estimators': 100, # 树的数量
'max_depth': 7, # 树的最大深度
'random_state': 42, # 随机种子
'subsample': 0.7, # 每次2024-10-26-公众号Python机器学习AI迭代时随机选择的样本比例
'colsample_bytree': 0.6, # 每棵树随机选择的特征比例
'n_jobs': -1 # 并行计算
}
# 初始化 LightGBM 回归模型
model_lgb = lgb.LGBMRegressor(**params_lgb)
# 准备10折交叉验证
kf = KFold(n_splits=10, shuffle=True, random_state=42)
# 准备存储每折训练集和验证集的拟合优度分数
scores_train_lgb = []
scores_val_lgb = []
# 初始化最好的模型和最高的验证集分数
best_model_lgb = None
best_val_score_lgb = -np.inf # 因为R²越大越好,所以初始值设为-inf
# 交叉验证
for fold, (train_index, val_index) in enumerate(kf.split(X_train)):
X_train_fold, X_val_fold = X_train.iloc[train_index], X_train.iloc[val_index]
y_train_fold, y_val_fold = y_train.iloc[train_index], y_train.iloc[val_index]
# 训练模型
model_lgb.fit(X_train_fold, y_train_fold)
# 预测训练集和验证集
y_train_pred = model_lgb.predict(X_train_fold)
y_val_pred = model_lgb.predict(X_val_fold)
# 计算训练集和验证集的R²
score_train_lgb = r2_score(y_train_fold, y_train_pred)
score_val_lgb = r2_score(y_val_fold, y_val_pred)
scores_train_lgb.append(score_train_lgb)
scores_val_lgb.append(score_val_lgb)
# 保存验证集分数最好的模型
if score_val_lgb > best_val_score_lgb:
best_val_score_lgb = score_val_lgb
best_model_lgb = model_lgb
print(f'第 {fold + 1} 折 训练集 R²: {score_train_lgb}, 验证集 R²: {score_val_lgb}')
# 保存 LightGBM 模型的训练集和验证集的 R² 分数为 DataFrame
df_scores_lgb = pd.DataFrame({
'lgbm_train': scores_train_lgb,
'lgbm_val': scores_val_lgb
})
# 将 CatBoost、XGBoos2024-10-26-公众号Python机器学习AIt、RF 和 LightGBM 的结果合并
df_scores_combined = pd.concat([df_scores_combined, df_scores_lgb], axis=1)
# 输出最优模型及其验证集 R² 分数
print(f'最佳验证集 R²: {best_val_score_lgb}')
print('最佳模型:', best_model_lgb)
df_scores_combined
使用LightGBM回归模型进行10折交叉验证,定义了模型参数(如学习率、树的数量、最大深度等),在每一折中训练模型并计算训练集和验证集的R²分数,将结果存储到列表中,同时记录验证集上R²分数最高的最优模型,最后将LightGBM的结果与之前的CatBoost、XGBoost和随机森林模型的结果合并,综合比较所有模型的性能表现,并输出LightGBM的最佳模型及其验证集R²分数
bagging
from sklearn.ensemble import BaggingRegressor
# Bagging 回归模型参数
params_bagging = {
'n_estimators': 100, # 基模型的数量
'random_state': 42, # 随机种子
'n_jobs': -1 # 并行计算,使用所有 CPU 核心
}
# 初始化 Bagging 回归模型
model_bagging = BaggingRegressor(**params_bagging)
# 准备10折交叉验证
kf = KFold(n_splits=10, shuffle=True, random_state=42)
# 准备存储每2024-10-26-公众号Python机器学习AI折训练集和验证集的拟合优度分数
scores_train_bagging = []
scores_val_bagging = []
# 初始化最好的模型和最高的验证集分数
best_model_bagging = None
best_val_score_bagging = -np.inf # 因为 R² 越大越好,初始值设为负无穷
# 交叉验证
for fold, (train_index, val_index) in enumerate(kf.split(X_train)):
X_train_fold, X_val_fold = X_train.iloc[train_index], X_train.iloc[val_index]
y_train_fold, y_val_fold = y_train.iloc[train_index], y_train.iloc[val_index]
# 训练模型
model_bagging.fit(X_train_fold, y_train_fold)
# 预测训练集和验证集
y_train_pred = model_bagging.predict(X_train_fold)
y_val_pred = model_bagging.predict(X_val_fold)
# 计算训练集和验证集的 R²
score_train_bagging = r2_score(y_train_fold, y_train_pred)
score_val_bagging = r2_score(y_val_fold, y_val_pred)
scores_train_bagging.append(score_train_bagging)
scores_val_bagging.append(score_val_bagging)
# 保存验证集分数最好的模型
if score_val_bagging > best_val_score_bagging:
best_val_score_bagging = score_val_bagging
best_model_bagging = model_bagging
print(f'第 {fold + 1} 折 训练集 R²: {score_train_bagging}, 验证集 R²: {score_val_bagging}')
# 保存 Bagging 模型的训练集和验证集的 R² 分数为 DataFrame
df_scores_bagging = pd.DataFrame({
'bagging_train': scores_train_bagging,
'bagging_val': scores_val_bagging
})
# 将 CatBoost、XGBoost、RF、LightGBM 和 Bagging 的结果合并
df_scores_combined = pd.concat([df_scores_combined, df_scores_bagging], axis=1)
# 输出最优模型及其验证集 R² 分数
print(f'最佳验证集 R²: {best_val_score_bagging}')
print('最佳 Bagging 模型:', best_model_bagging)
df_scores_combined
使用Bagging回归模型进行10折交叉验证,定义了基模型的数量和并行计算等参数,通过对每一折的数据进行训练和验证,计算训练集和验证集的R²分数,将每折的R²结果保存,记录验证集中表现最好的模型,同时将Bagging的结果与之前的CatBoost、XGBoost、随机森林和LightGBM的结果进行合并,最终输出Bagging模型的最佳验证集R²分数及最佳模型,用于综合比较所有模型的性能表现
数据整理
# 重新构建用于绘制小提琴图的数据格式
df_melted = pd.melt(df_scores_combined.reset_index(drop=True), var_name='Model_Dataset', value_name='R2')
# 分离模型名称和2024-10-26-公众号Python机器学习AI数据集(训练/验证)
df_melted['Model'] = df_melted['Model_Dataset'].apply(lambda x: x.split('_')[0])
df_melted['Dataset'] = df_melted['Model_Dataset'].apply(lambda x: 'Train' if 'train' in x else 'Val')
df_melted
将多个模型的训练集和验证集R²分数的结果重新构建为适合绘制小提琴图的数据格式,分离出模型名称和数据集类型(训练集或验证集)以便进行可视化分析
小提琴(训练集、验证集)部分可视化
from matplotlib.colors import to_rgba
import seaborn as sns
# 创建一个单独的画布
plt.figure(figsize=(12, 6), dpi=1200)
# 设置指定的颜色
palette = [to_rgba('#3c5397'), to_rgba('#f57065', alpha=0.7)]
# 绘制训练2024-10-26-公众号Python机器学习AI集和验证集的小提琴图,使用分开的模型位置
sns.violinplot(x='Model', y='R2', hue='Dataset', data=df_melted,
palette=palette,
split=False, dodge=True)
# 调整x轴标签,使其只显示模型名称,并居中显示模型名
plt.xticks(ticks=plt.gca().get_xticks(), labels=df_melted['Model'].unique())
plt.title('Model Comparison based on R² for Training and Validation Sets')
plt.ylabel('R²')
plt.xlabel('Model')
plt.ylim(0, 1)
plt.tight_layout()
plt.savefig("Model Comparison based on R² for Training and Validation Sets.pdf", format='pdf',bbox_inches='tight')
plt.show()
使用Seaborn库创建了一个小提琴图,分别展示不同模型在训练集和验证集上的R²分数分布,通过颜色区分训练集和验证集的表现
解释小提琴图的各部分含义
小提琴图结合了 箱线图 和 核密度图,展示了数据的分布和集中趋势,它由以下几个部分组成:
- 形状宽度:表示数据的分布密度,图形越宽的地方,说明该区域的R²分数在不同折中的出现频率越高;图形越窄的地方,说明该区域的分数较少
- 中间的白色线:表示数据的中位数,它帮助了解模型在不同数据集上的中等表现
- 箱体(黑色部分):显示了数据的四分位范围(IQR),即分布中间 50% 的数据点
- 两端的“触角”:显示数据的最大值和最小值,帮助了解模型在极端情况下的表现
在这个图中,通过两种颜色来区分训练集和验证集的R²分数分布
- 蓝色部分:代表模型在训练集上的R²分数分布
- 红色部分:代表模型在验证集上的R²分数分布
如何阅读小提琴图
- R² 的范围(0-1):R² 值越接近 1,模型对数据的拟合效果越好
- 数据分布的对称性:如果训练集和验证集的 R² 分数分布接近并对称,说明模型在训练和验证集上表现一致,具有较好的泛化能力
- 宽窄分布:宽度显示了不同折中分数的分布,如果图形非常窄,表示该模型在所有折中的表现都非常稳定;如果图形较宽,表示模型在不同折中的表现差异较大,表现不稳定
通过这个小提琴图,直观地分析不同模型在训练集和验证集上的性能,判断模型是否存在过拟合、欠拟合以及模型的稳定性
理想的模型应该是什么样子?
- 训练集和验证集的R²值接近:这表明模型没有过拟合或欠拟合,能够在训练数据和验证数据上都表现出良好的拟合效果
- 分布集中且稳定:小提琴图的宽度应较窄,说明模型在每一折中的表现都一致,具有良好的稳定性和泛化能力
- 中位数较高:R²分数的中位数应接近1,表示模型能够很好地解释数据中的变化
折线图(测试集)可视化
数据整理
from sklearn.metrics import mean_squared_error
models = {
'CatBoost': best_model_cat,
'XGBoost': best_model_xgb,
'RandomForest': best_model_rf,
'LightGBM': best_model_lgb,
'Bagging': best_model_bagging
}
# 创建一个空列表,用于保存模型名和RMSE
rmse_list = []
# 遍历模型,计2024-10-26-公众号Python机器学习AI算每个模型在X_test上的RMSE
for model_name, model in models.items():
y_pred = model.predict(X_test) # 获取预测结果
rmse = np.sqrt(mean_squared_error(y_test, y_pred)) # 计算RMSE
rmse_list.append([model_name, rmse]) # 添加到列表
rmse_df = pd.DataFrame(rmse_list, columns=['Model', 'RMSE'])
rmse_df
计算每个训练好的模型在测试集上的RMSE(均方根误差),将模型名称与对应的RMSE值保存为一个DataFrame,为后续在训练集上绘制折线图部分提供数据
可视化
plt.figure(figsize=(10, 6), dpi=1200)
plt.plot(rmse_df['Model'], rmse_df['RMSE'], marker='o', linestyle='-', color=(134/255, 171/255, 197/255))
plt.ylabel('RMSE', fontsize=12)
plt.tight_layout()
plt.savefig("RMSE of Different Models on X_test.pdf", format='pdf',bbox_inches='tight')
plt.show()
通过折线图展示各个模型在测试集上的RMSE(均方根误差)表现,从图中可以看出 CatBoost 模型的RMSE最小,表现最佳,结合前面的小提琴图就可以全面解释模型在训练集、验证集、测试集上的表现,接下来进行组合绘图
组合小提琴图、折线图可视化
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
# 创建第一个图 (violin plot2024-10-26-公众号Python机器学习AI) 并将第二个图作为 inset 放入其中
fig, ax = plt.subplots(figsize=(12, 6), dpi=1200)
# 设置指定的颜色
palette = [to_rgba('#3c5397'), to_rgba('#f57065', alpha=0.7)]
# 绘制训练集和验证集的小提琴图
sns.violinplot(x='Model', y='R2', hue='Dataset', data=df_melted,
palette=palette, split=False, dodge=True, ax=ax)
# 调整x轴标签,使其只显示模型名称,并居中显示模型名
ax.set_xticks(ax.get_xticks())
ax.set_xticklabels(df_melted['Model'].unique())
ax.set_title('Comparison of Model Performance: R² on Training and Validation Sets, RMSE on Test Set', fontsize=14)
ax.set_ylabel('R²')
ax.set_ylim(0, 1)
# 创建 inset,用于嵌入第二个图
inset_ax = inset_axes(ax, width="90%", height="90%",
bbox_to_anchor=(0.65, 0.1, 0.3, 0.4), # 控制位置和大小
bbox_transform=ax.transAxes)
# 绘制第二个图 (折线图) 在 inset 中,并给折线加上label用于图例
inset_ax.plot(rmse_df['Model'], rmse_df['RMSE'], marker='o', linestyle='-', color=(134/255, 171/255, 197/255), label='Test RMSE')
inset_ax.set_ylabel('RMSE', fontsize=10)
inset_ax.set_xticklabels(rmse_df['Model'], fontsize=8)
# 在镶嵌图 (inset_ax) 中添加图例
inset_ax.legend(loc='best', fontsize=8)
plt.tight_layout()
plt.savefig("Comparison_of_Model_Performance_R2_and_RMSE.pdf", format='pdf', bbox_inches='tight')
plt.show()
创建一个主图(小提琴图)和一个嵌入图(折线图),综合展示各个模型在训练集、验证集和测试集上的性能表现,当然我这里只是结合文献采用的RMSE,文献只展示了它所谓的训练集和测试集,然后对测试集分别用了R² 和RMSE展示,可能出发点在于R² 用来评估模型的拟合优度,而 RMSE 用来判断模型的预测误差大小,所以对于折线图我也采用了RMSE,但是为了统一评价指标接下来都采用R² 来评价训练集、验证集、测试集的性能
models = {
'CatBoost': best_model_cat,
'XGBoost': best_model_xgb,
'RandomForest': best_model_rf,
'LightGBM': best_model_lgb,
'Bagging': best_model_bagging
}
# 创建一个空列表,用于保存模型名和R²
r2_list = []
# 遍历模型,计算每个模型在X_test上的R²
for model_name, model in models.items():
y_pred = model.predict(X_test) # 获取预测结果
r2 = r2_score(y_test, y_pred) # 计算拟合优度 (R²)
r2_list.append([model_name, r2]) # 添加到列表
r2_df = pd.DataFrame(r2_list, columns=['Model', 'R²'])
# 创建第一个图 (violin2024-10-26-公众号Python机器学习AI plot) 并将第二个图作为 inset 放入其中
fig, ax = plt.subplots(figsize=(12, 6), dpi=1200)
# 设置指定的颜色
palette = [to_rgba('#3c5397'), to_rgba('#f57065', alpha=0.7)]
# 绘制训练集和验证集的小提琴图
sns.violinplot(x='Model', y='R2', hue='Dataset', data=df_melted,
palette=palette, split=False, dodge=True, ax=ax)
# 调整x轴标签,使其只显示模型名称,并居中显示模型名
ax.set_xticks(ax.get_xticks())
ax.set_xticklabels(df_melted['Model'].unique())
ax.set_title('Comparison of Model Performance: R² on Training and Validation Sets.Test Set', fontsize=14)
ax.set_ylabel('R²')
ax.set_ylim(0, 1)
# 创建 inset,用于嵌入第二个图
inset_ax = inset_axes(ax, width="90%", height="90%",
bbox_to_anchor=(0.65, 0.1, 0.3, 0.4), # 控制位置和大小
bbox_transform=ax.transAxes)
# 绘制第二个图 (折线图) 在 inset 中,并给折线加上label用于图例
inset_ax.plot(r2_df['Model'], r2_df['R²'], marker='o', linestyle='-', color=(134/255, 171/255, 197/255), label='Test R²')
inset_ax.set_ylabel('R²', fontsize=10)
inset_ax.set_xticklabels(rmse_df['Model'], fontsize=8)
# 在镶嵌图 (inset_ax) 中添加图例
inset_ax.legend(loc='best', fontsize=8)
plt.tight_layout()
plt.savefig("Comparison of Model Performance: R² on Training and Validation Sets、Test Set.pdf", format='pdf', bbox_inches='tight')
plt.show()
最后这个结果显示了各模型在训练集、验证集上的R²分数(通过小提琴图)和在测试集上的R²分数(通过嵌入的折线图),其中CatBoost 在训练集、验证集和测试集上都表现最好,泛化能力最强
往期推荐
基于SHAP值的 BorutaShap 算法在特征选择中的应用与优化
复现SCI文章 SHAP 依赖图可视化以增强机器学习模型的可解释性
微信号|deep_ML
欢迎添加作者微信进入Python、ChatGPT群
进群请备注Python或AI进入相关群
无需科学上网、同步官网所有功能、使用无限制
如果你对类似于这样的文章感兴趣。
欢迎关注、点赞、转发~
个人观点,仅供参考