复现Nature图表——基于PCA降维与模型预测概率的分类效果可视化

机器学习关系型数据库图像处理

picture.image

背景

在机器学习模型的分类性能评估中,如何有效地将高维数据的分类效果直观地展示出来是一个问题,Nature Communications 的一项研究展示了一种通过结合预测概率与主成分分析(PCA)的方法来可视化模型的分类效果,这一方法可以应用于多个领域的数据分类任务中

picture.image

picture.image

接下来作者将复现这一图表,展示如何将模型的预测概率和PCA的降维结果结合,来更直观地展现模型的分类性能,通过在二维空间中将预测概率与PCA的第一主成分结合,可以看到模型在不同类别上的分布情况,从而评估模型的分类效果,这种可视化方法对于理解模型的决策边界、评估分类结果的可靠性、以及发现潜在误分类样本具有重要意义

代码实现

数据读取处理


          
import pandas as pd
          
import numpy as np
          
from sklearn.model_selection import train_test_split
          
import matplotlib.pyplot as plt
          
import matplotlib.ticker as ticker
          
plt.rcParams['font.family'] = 'Times New Roman'
          
plt.rcParams['axes.unicode_minus'] = False
          
# 读取数据
          
df = pd.read_excel('2024-11-2-0公众号Python机器学习AI—class.xlsx')
          
# 划分特征和目标变量
          
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, stratify=df['y'])
      

读取数据并将特征和目标变量分离,然后将数据分为训练集和测试集,以便用于机器学习模型的训练和评估

模型构建


          
from hyperopt import fmin, tpe, hp
          
from sklearn.ensemble import RandomForestClassifier
          
from sklearn.metrics import accuracy_score
          

          
# 定义超参数空间
          
parameter_space_rf = {
          
    'n_estimators': hp.choice('n_estimators', [50, 100, 200, 300]),    # 决策树数量
          
    'max_depth': hp.choice('max_depth', [5, 10, 20, None]),            # 最大深度
          
    'min_samples_split': hp.uniform('min_samples_split', 0.01, 0.5),   # 分裂所需最小样本比例
          
    'min_samples_leaf': hp.uniform('min_samples_leaf', 0.01, 0.5)      # 叶节点最小样本比例
          
}
          

          
# 定义目标函数
          
def objective(params):
          
    # 初始化模型并传入超参数
          
    model = RandomForestClassifier(
          
        n_estimators=params['n_estimators'],
          
        max_depth=params['max_depth'],
          
        min_samples_split=params['min_samples_split'],
          
        min_samples_leaf=params['min_samples_leaf'],
          
        random_state=42
          
    )
          
    
          
    # 模型拟合
          
    model.fit(X_train, y_train)
          
    
          
    # 测试集上的预测
          
    y_pred = model.predict(X_test)
          
    
          
    # 计算准确率
          
    accuracy = accuracy_score(y_test, y_pred)
          
    
          
    # 返回负的准确率(因为Hyperopt默认最小化目标函数)
          
    return -accuracy
          

          
# 运行贝叶斯优化
          
best_params = fmin(
          
    fn=objective,                  # 目标函数
          
    space=parameter_space_rf,       # 搜索空间
          
    algo=tpe.suggest,               # 贝叶斯优化算法
          
    max_evals=100                   # 最大评估次数
          
)
          

          
# 显示最优参数
          
print("Best hyperparameters:", best_params)
          

          
# 使用最佳参数创建最终模型
          
best_model_class = RandomForestClassifier(
          
    n_estimators=[50, 100, 200, 300][best_params['n_estimators']],
          
    max_depth=[5, 10, 20, None][best_params['max_depth']],
          
    min_samples_split=best_params['min_samples_split'],
          
    min_samples_leaf=best_params['min_samples_leaf'],
          
    random_state=42
          
)
          

          
# 在训练集上拟合模型
          
best_model_class.fit(X_train, y_train)
      

使用贝叶斯优化(通过 Hyperopt 库)来寻找随机森林分类器的最佳超参数配置,并用优化后的超参数训练最终的模型

模型预测概率结果


          
# 预测类别的概率
          
probabilities = best_model_class.predict_proba(X_test)
          
# 创建一个 DataFrame,列名为类别
          
probability_df = pd.DataFrame(probabilities, columns=[f'Prob_Class_{i}' for i in range(probabilities.shape[1])])
          
# 如果需要,可以添加 X_test 的索引或其他标识列
          
probability_df.index = X_test.index
          
# 重置索引,并选择是否保留原索引作为一列
          
probability_df.reset_index(drop=True, inplace=True)
          
probability_df.head()
      

picture.image

计算模型在测试集上对每个类别的预测概率,并将结果存储在一个带有类别列名的 DataFrame 中

主成分分析 (PCA):降维与方差解释


          
from sklearn.decomposition import PCA
          
df_selected = X_test
          
# 创建PCA对象,设置提取1个主成分
          
pca = PCA(n_components=1)
          
# 进行PCA降维
          
pca_result = pca.fit_transform(df_selected)
          
# 获取解释方差比率(贡献度)
          
explained_variance = pca.explained_variance_ratio_
          
# 将PCA结果保存为DataFrame,并用贡献度标记列名
          
pca_df = pd.DataFrame(pca_result, columns=[f"PC1 ({explained_variance[0]*100:.2f}%)"])
          
pca_df.head()
      

对测试集数据进行PCA降维,将其压缩到一个主成分中,并创建一个包含该主成分(带有解释方差百分比)的DataFrame

合并预测概率与PCA结果:构建最终分析数据集


          
combined_df = pd.concat([probability_df, pca_df, y_test.reset_index(drop=True)], axis=1)
          
combined_df.rename(columns={y_test.name: 'True'}, inplace=True)
          
combined_df.head()
      

picture.image

将预测概率、PCA结果和真实标签合并为一个DataFrame,以便于进一步分析和可视化模型分类效果

结合PCA与预测概率的分类效果可视化散点图


          
colors = combined_df['True'].map({0: '#A0D6B4', 1: '#C3A6D8'})
          

          
# 绘制散点图,设置更大的点和黑色边框
          
plt.figure(figsize=(10, 6),dpi=1200)
          
plt.scatter(combined_df['Prob_Class_1'], combined_df['PC1 (69.29%)'], 
          
            c=colors, edgecolor='black', s=100)  # s=100 增大点的大小,edgecolor='black' 添加黑色边框
          

          
# 添加分界线和轴标签
          
plt.axvline(x=0.5, color='gray', linestyle='--')
          
plt.xlabel('Predicted value for GC')
          
plt.ylabel('PC1 (69.29%)')
          
plt.title('Test set')
          
# 添加类别图例并移到图外
          
for true_value, color, label in [(0, '#A0D6B4', 'NGC'), (1, '#C3A6D8', 'GC')]:
          
    plt.scatter([], [], color=color, edgecolor='black', s=100, label=label)
          
plt.legend(title="Class", loc="center left", bbox_to_anchor=(1, 0.5))
          
plt.tight_layout(rect=[0, 0, 0.85, 1])
          
plt.savefig('1.pdf', format='pdf', bbox_inches='tight')
          
plt.show()
      

picture.image

生成一个散点图,用于可视化分类模型的预测效果,首先,根据真实类别 (True) 为数据点设置颜色,分别对应不同类别(NGC和GC)。图中,X轴表示模型对GC类别的预测概率,Y轴显示PCA的第一主成分(解释了数据69.29%的方差),通过绘制分界线(X=0.5)展示模型的决策阈值,图例则在图外标识出不同类别(当然作者这里是模拟数据)

分类效果:大多数紫色点(GC)位于虚线右侧,绿色点(NGC)位于左侧,这表明模型在区分GC和NGC类别时有一定的效果,错误分类:有少量绿色点在虚线右侧,和少量紫色点在左侧,这些可以认为是误分类的样本,图表展示了模型的分类效果及其对不同类别的信心,模型在区分GC和NGC类别方面表现不错,但仍有少量误分类的样本,可以进一步优化模型或分析这些误分类样本的特征

训练集分类效果可视化:结合PCA与预测概率的散点图展示


          
# 预测类别的概率
          
probabilities = best_model_class.predict_proba(X_train)
          
# 创建一个 DataFrame,列名为类别
          
probability_df = pd.DataFrame(probabilities, columns=[f'Prob_Class_{i}' for i in range(probabilities.shape[1])])
          
# 如果需要,可以添加 X_test 的索引或其他标识列
          
probability_df.index = X_train.index
          
# 重置索引,并选择是否保留原索引作为一列
          
probability_df.reset_index(drop=True, inplace=True)
          
df_selected = X_train
          
# 创建PCA对象,设置提取1个主成分
          
pca = PCA(n_components=1)
          
# 进行PCA降维
          
pca_result = pca.fit_transform(df_selected)
          
# 获取解释方差比率(贡献度)
          
explained_variance = pca.explained_variance_ratio_
          
# 将PCA结果保存为DataFrame,并用贡献度标记列名
          
pca_df = pd.DataFrame(pca_result, columns=[f"PC1 ({explained_variance[0]*100:.2f}%)"])
          
combined_df = pd.concat([probability_df, pca_df, y_train.reset_index(drop=True)], axis=1)
          
combined_df.rename(columns={y_train.name: 'True'}, inplace=True)
          

          
colors = combined_df['True'].map({0: '#A0D6B4', 1: '#C3A6D8'})
          

          
# 绘制散点图,设置更大的点和黑色边框
          
plt.figure(figsize=(10, 6),dpi=1200)
          
plt.scatter(combined_df['Prob_Class_1'], combined_df['PC1 (75.91%)'], 
          
            c=colors, edgecolor='black', s=100)  # s=100 增大点的大小,edgecolor='black' 添加黑色边框
          

          
# 添加分界线和轴标签
          
plt.axvline(x=0.5, color='gray', linestyle='--')
          
plt.xlabel('Predicted value for GC')
          
plt.ylabel('PC1 (75.91%)')
          
plt.title('Train set')
          
# 添加类别图例并移到图外
          
for true_value, color, label in [(0, '#A0D6B4', 'NGC'), (1, '#C3A6D8', 'GC')]:
          
    plt.scatter([], [], color=color, edgecolor='black', s=100, label=label)
          
plt.legend(title="Class", loc="center left", bbox_to_anchor=(1, 0.5))
          
plt.tight_layout(rect=[0, 0, 0.85, 1])
          
plt.savefig('2.pdf', format='pdf', bbox_inches='tight')
          
plt.show()
      

picture.image

也可以在训练集上绘制一个结合PCA主成分和模型预测概率的散点图,可视化模型的分类效果,类似之前在测试集上的图表,通过这种方法在训练集上展示模型对不同类别的区分能力

多分类绘制

picture.image

picture.image

对于多分类模型,可以使用类似的可视化方法,将模型的预测概率与PCA主成分结合在散点图上展示不同类别的分布情况,这种方法为每个样本在不同类别中的预测概率和主成分值提供了直观的展示,代码获取:如果您希望获取本文展示的改进版代码,请添加作者微信联系获取

🎁 赠书活动来啦! 🎁

picture.image

picture.image

支持知识分享,畅享学习乐趣!特别感谢清华出版社 对本次赠书活动的鼎力支持!即日起,只需

点赞、在看、转发 此文章,作者将从后台随机抽取一位幸运儿,免费包邮赠送清华出版社提供的《细说Python编程:从入门到科学计算》这本精彩书籍📚!

💡 赶快参与,一键三连,说不定你就是那位幸运读者哦!

往期推荐

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

SCI图表:基于相关性和标准差的多模型评价——泰勒图解析

期刊文章配图:基于分组折线图的多机器学习模型表现评估对比

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

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

复现 Nature 图表——基于PCA的高维数据降维与可视化实践及其扩展

复现 Nature 图表可视化——基于模型残差分析与显著性检验的模型解释

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

期刊文章配图:基于雷达图的多机器学习模型表现评估对比

期刊文章配图:斯皮尔曼相关系数热图反应非线性变量相关性

picture.image

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

欢迎关注、点赞、转发~

个人观点,仅供参考

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