当前位置: 首页 > news >正文

python打卡day18

聚类后的分析:推断簇的类型

知识点回顾:

  1. 推断簇含义的2个思路:先选特征和后选特征
  2. 通过可视化图形借助ai定义簇的含义
  3. 科研逻辑闭环:通过精度判断特征工程价值

作业:参考示例代码对心脏病数据集采取类似操作,并且评估特征工程后模型效果有无提升。

昨天的内容只是使用三种聚类算法完成了聚类以及结果可视化,以KMeans算法K = 6为例:

对于聚类后形成的六个簇没有做论述,现在需要给这个簇赋予实际的含义,一般当你赋予实际含义的时候,你需要根据某几个特征来赋予,但是源数据特征很多,如何选择特征呢?有2种思路:

1. 你最开始聚类的时候,就选择了你想最后用来确定簇含义的特征,那么你需要选择一些特征来进行聚类,那么你最后确定簇含义的特征就是这几个特征,而非全部。如你想聚类消费者购买习惯,那么他过去的消费记录、购买记录、购买金额等等,这些特征都与消费者购买习惯有关,你可以使用这些特征来确定簇含义,一些其他的特征,如消费者年龄,工作行业则不考虑。------适用于你本身就有构造某些明确含义的特征的情况。

2. 最开始用全部特征来聚类,把其余特征作为 x,聚类得到的簇类别作为标签构建监督模型,进而根据重要性筛选特征,来确定要根据哪些特征赋予含义。------使用于你想构造什么,目前还不清楚。

总的来说要么人为选取重要特征再进行聚类;要么全部特征聚类完后,把簇类别当标签转换成分类问题,用shap值等方式显示重要特征,这里选择思路二,选择随机森林分类模型进行操作

import shap
import numpy as np
from sklearn.ensemble import RandomForestClassifier  # 随机森林分类器# 构建随机森林分类模型,用shap重要性来筛选重要性
x1= X.drop('KMeans_Cluster',axis=1) # 聚类的时候把聚类结果添加到原数据里了,删除聚类标签列其余当变量
y1 = X['KMeans_Cluster']
rf_model = RandomForestClassifier(n_estimators=100, random_state=42)  # 随机森林模型
rf_model.fit(x1, y1)  # 训练模型,此时无需在意准确率 直接全部数据用来训练了shap.initjs() # 必须在绘制交互图前调用
# 初始化 SHAP 解释器
explainer = shap.TreeExplainer(rf_model)
shap_values = explainer.shap_values(x1) # 这个计算耗时
shap_values.shape # 第一维是样本数,第二维是特征数,第三维是类别数,结果是(7500, 31, 6)# ---  SHAP 特征重要性条形图 (Summary Plot - Bar) ---
shap.summary_plot(shap_values[:, :, 0], x1, plot_type="bar",show=False)  #  这里的show=False表示不直接显示图形,这样可以继续用plt来修改元素,不然就直接输出了
plt.title("SHAP Feature Importance (Bar Plot)")
plt.show()

很明显前四个特征对于聚类结果比较重要,为了对特征针对性可视化和正确解释聚类结果,下面要区分是连续变量还是离散变量(之前对于这个数据集连续和离散的处理是根据数据类型来的,这里都是数值型,要用唯一值细分一下了)

# 通过唯一值看看是连续还是离散
selected_features = ['Purpose_debt consolidation', 'Bankruptcies','Number of Credit Problems', 'Purpose_other']for feature in selected_features:unique_count = X[feature].nunique() # 唯一值指的是在某一列或某个特征中,不重复出现的值# 连续型变量通常有很多唯一值,而离散型变量的唯一值较少print(f'{feature} 的唯一值数量: {unique_count}')if unique_count < 10:  # 这里 10 是一个经验阈值,可以根据实际情况调整print(f'{feature} 可能是离散型变量')else:print(f'{feature} 可能是连续型变量')# ---------- 打印结果 ------------
Purpose_debt consolidation 的唯一值数量: 2
Purpose_debt consolidation 可能是离散型变量
Bankruptcies 的唯一值数量: 5
Bankruptcies 可能是离散型变量
Number of Credit Problems 的唯一值数量: 8
Number of Credit Problems 可能是离散型变量
Purpose_other 的唯一值数量: 2
Purpose_other 可能是离散型变量

那都按离散变量的可视化来仔细看看,画直方图

# 总样本中的前四个重要性的特征分布图
fig, axes = plt.subplots(2, 2, figsize=(12, 8))
axes = axes.flatten() # 将二维的 axes 数组转换为一维数组(方便用单个索引遍历)for i, feature in enumerate(selected_features): # 同时返回当前索引和列名axes[i].hist(X[feature], bins=20)axes[i].set_title(f'Histogram of {feature}')axes[i].set_xlabel(feature)axes[i].set_ylabel('Frequency')plt.tight_layout()
plt.show()

这几个重要特征是找出来了,但没有和簇的分类对应上啊,每个簇和几个特征有关呢?(这里说一下,是要筛选每个簇对应的这四个特征所有行数据,然后画直方图,这个筛选行数据的方法可以注意一下,第一次接触)

clusters = {} # 创建一个字典
for i in range(6):  # 6个簇,循环筛出每簇的所有行clusters[f'cluster{i}'] = X[X['KMeans_Cluster'] == i] # 在簇0中总样本中的前四个重要性的特征分布图
fig, axes = plt.subplots(2, 2, figsize=(12, 8))
axes = axes.flatten()for i, feature in enumerate(selected_features):axes[i].hist(clusters['cluster0'][feature], bins=20) # 字典嘛,通过键来访问axes[i].set_title(f'Histogram of {feature}')axes[i].set_xlabel(feature)axes[i].set_ylabel('Frequency')plt.tight_layout()
plt.show()

这里只画了簇0的,分别画出6个簇的四个重要特征直方图,看不明白很正常,丢给大模型问问,让它总结定义每个簇的含义,比如:

  • 簇 0 代表了在债务合并用途上表现一致,几乎无破产记录,信用问题极少,资金用途集中且很少涉及特殊类别,财务状况稳定,信用良好,资金流向明确的群体
  • 簇 1 代表了多数无债务合并需求,破产情况少见,但信用问题上存在个体差异,资金用途有一定分散性。整体财务状况相对稳定,但在信用和资金使用方向上不如第一个簇表现一致

好了,通过聚类对每个簇进行定义后,簇标签可视为数据的新特征,且这一过程属于特征工程,后续研究需要对这个特征独热编码,然后重新建模训练,如果加了这个特征后模型精度提高,说明这个特征是有用的

收获心得:

这里再辨析一下单括号和双中括号访问,之前没搞清楚,推荐用双中括号不仅能保留列名,还方便后续涉及DataFrame的操作

1. 单中括号 [] 访问
  • X['col'] → Series
  • 返回单列的一维数据结构
  • 相当于从 DataFrame 中"抽取"出一列
  • 项目的例子:X['KMeans_Cluster'] 是 Series
2. 双中括号 [[]] 访问
  • X[['col']] → DataFrame
  • 返回只含该列的二维数据结构
  • 相当于从 DataFrame 中"切片"出子表
  • 项目的例子:X[['KMeans_Cluster']] 是 1 列的 DataFrame

@浙大疏锦行

相关文章:

  • 【一篇详解】深入浅出RabbtiMQ消息队列
  • openstack的网络
  • 第十六次博客打卡
  • Qt开发经验 --- 避坑指南(6)
  • Java中字符转数字的原理解析 - 为什么char x - ‘0‘能得到对应数字
  • C++回顾 Day4
  • Web前端入门及基础代码
  • 创建虚拟服务时实现持久连接。
  • hadoop中的序列化和反序列化(1)
  • 猫咪如厕检测与分类识别系统系列~进阶【一】视频流推流及网页实时展示
  • 如何测试 esp-webrtc-solution_solutions_doorbell_demo 例程?
  • 【Python】通过`Editable Install`模式详解,解决Python开发总是import出错的问题
  • 电商双11美妆数据分析(二)
  • Python案例实战《水果识别模型训练及调用》
  • 写个远程操作Android的调试程序
  • OpenMVS 的编译与运行
  • 电子电器架构 --- 48V架构的一丢丢事情
  • 2014年写的一个文档《基于大数据应用的综合健康服务平台研发及应用示范》
  • 【性能工具】一种简易hook bitmap创建的插件使用
  • 单片机-STM32部分:7、GPIO输入 按键
  • 青岛双星名人集团管理权之争:公司迁址,管理层更迭
  • 上交现场配乐4K修复版《神女》:默片巅峰有了新的打开方式
  • 印巴局势快速升级,外交部:呼吁印巴以和平稳定的大局为重
  • 陕南多地供水形势严峻:有的已呼吁启用自备水井
  • 8小时《大师与玛格丽特》:长度可以是特点,但不是价值标准
  • 夜读丨最美的风景,在亲人的目光里