聚类后的分析:推断簇的类型
知识点回顾: 推断簇含义的两个思路:先选特征和后选特征。先选特征是指在聚类之前根据领域知识或假设选择特定的特征进行聚类;后选特征则是在聚类完成后,通过分析簇的特征来推断其含义。
通过可视化图形借助AI定义簇的含义。可视化工具如散点图、热图等可以帮助直观地观察簇的分布和特征,结合AI算法可以更准确地定义簇的含义。
科研逻辑闭环:通过精度判断特征工程价值。在聚类分析中,特征工程的质量直接影响模型的精度。通过比较特征工程前后模型的精度,可以评估特征工程的价值。
作业:参考示例代码对心脏病数据集采取类似操作,并且评估特征工程后模型效果有无提升。具体步骤包括数据预处理、特征选择、聚类分析、模型训练与评估等。通过比较特征工程前后模型的性能指标(如准确率、召回率等),可以判断特征工程是否提升了模型效果。
首先是构建随机森林模型,用shap值来筛选重要特征
print(x.columns)
x1 = x.drop(['KMeans_Cluster'], axis=1)
y1 = x['KMeans_Cluster']
from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier(n_estimators=100, random_state = 42)
model.fit(x1, y1)
import shap
shap.initjs() # 初始化 JS 环境不调用可能会使得可视化图表无法显示
# 初始化 SHAP 解释器
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(x1) # 这个计算耗时
shap_values.shape # 第一维是样本数,第二维是特征数,第三维是类别数
print("--- 1. SHAP 特征重要性条形图 ---")
shap.summary_plot(shap_values[:, :, 0], x1, plot_type="bar",show=False) # 这里的show=False表示不直接显示图形,这样可以继续用plt来修改元素,不然就直接输出了
plt.title("SHAP Feature Importance (Bar Plot)")
plt.show()
此时我选择前4个重要特征对其进行判断是离散的还是连续的
#此时判断一下这几个特征是离散型还是连续型
import pandas as pd
selected_features = ['sex', 'age', 'thalach', 'slope']
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} 可能是连续型变量')
绘制总样本中前四个重要特征的特征分布图
import matplotlib.pyplot as plt
# 总样本中的前四个重要性的特征分布图
fig, axes = plt.subplots(2, 2, figsize=(12, 8))
axes = axes.flatten()# 将2x2二维数组展平为包含4个元素的一维数组
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()
输出聚类的簇的分类,并绘制出每个簇所对应的这四个特征的分布图
print(x[['KMeans_Cluster']].value_counts())
绘制每个簇所对应的4个特征的分布图,示例代码
x_cluster0 = x[x['KMeans_Cluster'] == 0]
x_cluster1 = x[x['KMeans_Cluster'] == 1]
x_cluster2 = x[x['KMeans_Cluster'] == 2]
x_cluster3 = x[x['KMeans_Cluster'] == 3]
# 先绘制簇0的分布图
import matplotlib.pyplot as plt
# 总样本中的前四个重要性的特征分布图
fig, axes = plt.subplots(2, 2, figsize=(12, 8))
axes = axes.flatten()
for i, feature in enumerate(selected_features):
axes[i].hist(x_cluster3[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
簇1
簇2
簇3
总结:
特征总结:以男性为主,年龄集中在 40 - 55 岁,最大心率多在 160 - 170,斜率常为 2.0。
定义依据:从“Histogram of sex”图中看到,sex 值为 1.0 的频率远高于 0.0,说明男性占主导;“Histogram of age”显示年龄在 40 - 55 岁区间频率较高;“Histogram of thalach”表明 thalach 值在 160 - 170 左右出现明显高峰;“Histogram of slope”里 slope 值为 2.0 的频率极高。
特征总结:男性居多,年龄集中在 50 - 60 岁,最大心率多在 140 左右,斜率常为 1.0。
定义依据:“Histogram of sex”体现 sex 为 1.0 的频率高,即男性为主;“Histogram of age”中 50 - 60 岁年龄段频率突出;“Histogram of thalach”显示 thalach 在 140 处频率较高;“Histogram of slope”里 slope 为 1.0 时频率较高。
特征总结:以女性为主,年龄集中在中老年(50 - 70 岁),最大心率集中在 140 - 160,斜率常为 2.0。
定义依据:“Histogram of sex”中 sex 为 0.0 的频率极高,意味着女性占主导;“Histogram of age”显示 50 - 70 岁频率相对较高;“Histogram of thalach”表明 thalach 在 140 - 160 之间有多个峰值;“Histogram of slope”里 slope 为 2.0 时频率很高。
特征总结:男性为主,年龄集中在 50 - 65 岁,最大心率分布较分散(140 - 170 之间),斜率多为 1.0,部分为 2.0。
定义依据:“Histogram of sex”呈现 sex 为 1.0 的频率高,即男性居多;“Histogram of age”显示 50 - 65 岁频率较高;“Histogram of thalach”中 thalach 在 140 - 170 间有多个峰值,分布分散;“Histogram of slope”里 slope 在 1.0 处频率高,2.0 处也有一定频率。
然后我将特征工程处理后的数据集划分训练集和测试集,用默认参数的随机森林模型进行训练,结果模型预测精准度有所提升,之前好像就0.74,现在0.84
from sklearn.model_selection import train_test_split
x = data.drop(['target'], axis=1) # 特征,axis=1表示按列删除
y = data['target'] # 标签
# 按照8:2划分训练集和测试集
x_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42)
import numpy as np # 引入 numpy 用于计算平均值等
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import StratifiedKFold, cross_validate # 引入分层 K 折和交叉验证工具
from sklearn.metrics import make_scorer, accuracy_score, precision_score, recall_score, f1_score, confusion_matrix, classification_report
import time
import warnings
warnings.filterwarnings("ignore")
print("--- 1. 默认参数随机森林 (训练集 -> 测试集) ---")
start_time = time.time()
rf_model_default = RandomForestClassifier(random_state=42)
rf_model_default.fit(x_train, y_train)
rf_pred_default = rf_model_default.predict(x_test)
end_time = time.time()
print(f"默认模型训练与预测耗时: {end_time - start_time:.4f} 秒")
print("\n默认随机森林 在测试集上的分类报告:")
print(classification_report(y_test, rf_pred_default))
print("默认随机森林 在测试集上的混淆矩阵:")
print(confusion_matrix(y_test, rf_pred_default))
print("-" * 50)
@浙大疏锦行