SCI图表复现:利用小提琴图折线图综合展示训练集、验证集、测试集模型性能对比

大模型机器学习关系型数据库

picture.image

背景

在机器学习的回归任务中,不同模型的选择和性能评估对于提升预测效果和避免模型过拟合、欠拟合至关重要,本文参考 Wei Zhuang 等人在《Water Research》期刊上发表的研究文章,该文采用了多种机器学习模型对数据集进行预测,并通过 R² 和 RMSE 等评价指标分析了模型在不同数据集上的表现——图a

picture.image

picture.image

在此基础上,本文对其进行扩展,采用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()
      

picture.image

加载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
      

picture.image

定义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
      

picture.image

定义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
      

picture.image

使用随机森林回归模型进行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
      

picture.image

使用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
      

picture.image

使用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
      

picture.image

将多个模型的训练集和验证集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()
      

picture.image

使用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
      

picture.image

计算每个训练好的模型在测试集上的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()
      

picture.image

通过折线图展示各个模型在测试集上的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()
      

picture.image

创建一个主图(小提琴图)和一个嵌入图(折线图),综合展示各个模型在训练集、验证集和测试集上的性能表现,当然我这里只是结合文献采用的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()
      

picture.image

最后这个结果显示了各模型在训练集、验证集上的R²分数(通过小提琴图)和在测试集上的R²分数(通过嵌入的折线图),其中CatBoost 在训练集、验证集和测试集上都表现最好,泛化能力最强

往期推荐

SCI图表复现:整合数据分布与相关系数的高级可视化策略

复现顶刊Streamlit部署预测模型APP

树模型系列:如何通过XGBoost提取特征贡献度

SHAP进阶解析:机器学习、深度学习模型解释保姆级教程

特征选择:Lasso和Boruta算法的结合应用

从基础到进阶:优化SHAP力图,让样本解读更直观

SCI图表复现:优化SHAP特征贡献图展示更多模型细节

多模型中的特征贡献度比较与可视化图解

SCI图表复现:特征相关性气泡热图展示

基于SHAP值的 BorutaShap 算法在特征选择中的应用与优化

复现SCI文章 SHAP 依赖图可视化以增强机器学习模型的可解释性

picture.image

picture.image

picture.image

微信号|deep_ML

欢迎添加作者微信进入Python、ChatGPT群

进群请备注Python或AI进入相关群

无需科学上网、同步官网所有功能、使用无限制

如果你对类似于这样的文章感兴趣。

欢迎关注、点赞、转发~

个人观点,仅供参考

0
0
0
0
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论