Python训练营打卡——DAY18(2025.5.7)
目录
一、基于聚类进一步推断类型
1. 聚类分析
2. 簇的总结与定义
二、作业
1. 聚类分析
2. 簇的总结与定义
3. 模型效果提升
一、基于聚类进一步推断类型
选用昨天kmeans得到的效果进行聚类,进而推断出每个簇的实际含义。
1. 聚类分析
# 先运行之前预处理好的代码
import pandas as pd
import pandas as pd #用于数据处理和分析,可处理表格数据。
import numpy as np #用于数值计算,提供了高效的数组操作。
import matplotlib.pyplot as plt #用于绘制各种类型的图表
import seaborn as sns #基于matplotlib的高级绘图库,能绘制更美观的统计图形。
import warnings
warnings.filterwarnings("ignore")# 设置中文字体(解决中文显示问题)
plt.rcParams['font.sans-serif'] = ['SimHei'] # Windows系统常用黑体字体
plt.rcParams['axes.unicode_minus'] = False # 正常显示负号
data = pd.read_csv('data.csv') #读取数据# 先筛选字符串变量
discrete_features = data.select_dtypes(include=['object']).columns.tolist()
# Home Ownership 标签编码
home_ownership_mapping = {'Own Home': 1,'Rent': 2,'Have Mortgage': 3,'Home Mortgage': 4
}
data['Home Ownership'] = data['Home Ownership'].map(home_ownership_mapping)# Years in current job 标签编码
years_in_job_mapping = {'< 1 year': 1,'1 year': 2,'2 years': 3,'3 years': 4,'4 years': 5,'5 years': 6,'6 years': 7,'7 years': 8,'8 years': 9,'9 years': 10,'10+ years': 11
}
data['Years in current job'] = data['Years in current job'].map(years_in_job_mapping)# Purpose 独热编码,记得需要将bool类型转换为数值
data = pd.get_dummies(data, columns=['Purpose'])
data2 = pd.read_csv("data.csv") # 重新读取数据,用来做列名对比
list_final = [] # 新建一个空列表,用于存放独热编码后新增的特征名
for i in data.columns:if i not in data2.columns:list_final.append(i) # 这里打印出来的就是独热编码后的特征名
for i in list_final:data[i] = data[i].astype(int) # 这里的i就是独热编码后的特征名# Term 0 - 1 映射
term_mapping = {'Short Term': 0,'Long Term': 1
}
data['Term'] = data['Term'].map(term_mapping)
data.rename(columns={'Term': 'Long Term'}, inplace=True) # 重命名列
continuous_features = data.select_dtypes(include=['int64', 'float64']).columns.tolist() #把筛选出来的列名转换成列表# 连续特征用中位数补全
for feature in continuous_features: mode_value = data[feature].mode()[0] #获取该列的众数。data[feature].fillna(mode_value, inplace=True) #用众数填充该列的缺失值,inplace=True表示直接在原数据上修改。# 最开始也说了 很多调参函数自带交叉验证,甚至是必选的参数,你如果想要不交叉反而实现起来会麻烦很多
# 所以这里我们还是只划分一次数据集
from sklearn.model_selection import train_test_split
X = data.drop(['Credit Default'], axis=1) # 特征,axis=1表示按列删除
y = data['Credit Default'] # 标签
# # 按照8:2划分训练集和测试集
# X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 80%训练集,20%测试集
import numpy as np
import pandas as pd
from sklearn.cluster import KMeans, DBSCAN, AgglomerativeClustering
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
import seaborn as sns# 标准化数据(聚类前通常需要标准化)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# X_scaled
import numpy as np
import pandas as pd
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.metrics import silhouette_score, calinski_harabasz_score, davies_bouldin_score
import matplotlib.pyplot as plt
import seaborn as sns# 评估不同 k 值下的指标
k_range = range(2, 11) # 测试 k 从 2 到 10
inertia_values = []
silhouette_scores = []
ch_scores = []
db_scores = []for k in k_range:kmeans = KMeans(n_clusters=k, random_state=42)kmeans_labels = kmeans.fit_predict(X_scaled)inertia_values.append(kmeans.inertia_) # 惯性(肘部法则)silhouette = silhouette_score(X_scaled, kmeans_labels) # 轮廓系数silhouette_scores.append(silhouette)ch = calinski_harabasz_score(X_scaled, kmeans_labels) # CH 指数ch_scores.append(ch)db = davies_bouldin_score(X_scaled, kmeans_labels) # DB 指数db_scores.append(db)print(f"k={k}, 惯性: {kmeans.inertia_:.2f}, 轮廓系数: {silhouette:.3f}, CH 指数: {ch:.2f}, DB 指数: {db:.3f}")# # 绘制评估指标图
# plt.figure(figsize=(15, 10))# # 肘部法则图(Inertia)
# plt.subplot(2, 2, 1)
# plt.plot(k_range, inertia_values, marker='o')
# plt.title('肘部法则确定最优聚类数 k(惯性,越小越好)')
# plt.xlabel('聚类数 (k)')
# plt.ylabel('惯性')
# plt.grid(True)# # 轮廓系数图
# plt.subplot(2, 2, 2)
# plt.plot(k_range, silhouette_scores, marker='o', color='orange')
# plt.title('轮廓系数确定最优聚类数 k(越大越好)')
# plt.xlabel('聚类数 (k)')
# plt.ylabel('轮廓系数')
# plt.grid(True)# # CH 指数图
# plt.subplot(2, 2, 3)
# plt.plot(k_range, ch_scores, marker='o', color='green')
# plt.title('Calinski-Harabasz 指数确定最优聚类数 k(越大越好)')
# plt.xlabel('聚类数 (k)')
# plt.ylabel('CH 指数')
# plt.grid(True)# # DB 指数图
# plt.subplot(2, 2, 4)
# plt.plot(k_range, db_scores, marker='o', color='red')
# plt.title('Davies-Bouldin 指数确定最优聚类数 k(越小越好)')
# plt.xlabel('聚类数 (k)')
# plt.ylabel('DB 指数')
# plt.grid(True)# plt.tight_layout()
# plt.show()# 提示用户选择 k 值
selected_k = 3 # 这里选择3后面好分析,也可以根据图选择最佳的k值# 使用选择的 k 值进行 KMeans 聚类
kmeans = KMeans(n_clusters=selected_k, random_state=42)
kmeans_labels = kmeans.fit_predict(X_scaled)
X['KMeans_Cluster'] = kmeans_labels# 使用 PCA 降维到 2D 进行可视化
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_scaled)# KMeans 聚类结果可视化
plt.figure(figsize=(6, 5))
sns.scatterplot(x=X_pca[:, 0], y=X_pca[:, 1], hue=kmeans_labels, palette='viridis')
plt.title(f'KMeans Clustering with k={selected_k} (PCA Visualization)')
plt.xlabel('PCA Component 1')
plt.ylabel('PCA Component 2')
plt.show()# 打印 KMeans 聚类标签的前几行
print(f"KMeans Cluster labels (k={selected_k}) added to X:")
print(X[['KMeans_Cluster']].value_counts())
k=2, 惯性: 218529.50, 轮廓系数: 0.320, CH 指数: 479.34, DB 指数: 3.222 k=3, 惯性: 207982.87, 轮廓系数: 0.209, CH 指数: 441.88, DB 指数: 2.906 k=4, 惯性: 200477.28, 轮廓系数: 0.220, CH 指数: 399.12, DB 指数: 2.441 k=5, 惯性: 192940.36, 轮廓系数: 0.224, CH 指数: 384.19, DB 指数: 2.042 k=6, 惯性: 185411.81, 轮廓系数: 0.227, CH 指数: 380.64, DB 指数: 1.733 k=7, 惯性: 178444.49, 轮廓系数: 0.130, CH 指数: 378.31, DB 指数: 1.633 k=8, 惯性: 174920.27, 轮廓系数: 0.143, CH 指数: 352.31, DB 指数: 1.817 k=9, 惯性: 167383.96, 轮廓系数: 0.150, CH 指数: 364.27, DB 指数: 1.636 k=10, 惯性: 159824.84, 轮廓系数: 0.156, CH 指数: 378.43, DB 指数: 1.502
KMeans Cluster labels (k=3) added to X: KMeans_Cluster 0 5205 1 1381 2 914 dtype: int64
现在需要给这个簇赋予实际的含义,一般当你赋予实际含义的时候,你需要根据某几个特征来赋予,但是源数据特征很多,如何选择特征呢?有2种思路:
-
你最开始聚类的时候,就选择了你想最后用来确定簇含义的特征,那么你需要选择一些特征来进行聚类,那么你最后确定簇含义的特征就是这几个特征,而非全部。如你想聚类消费者购买习惯,那么他过去的消费记录、购买记录、购买金额等等,这些特征都与消费者购买习惯有关,你可以使用这些特征来确定簇含义,一些其他的特征,如消费者年龄,工作行业则不考虑。----适用于你本身就有构造某些明确含义的特征的情况。
-
最开始用全部特征来聚类,把其余特征作为 x,聚类得到的簇类别作为标签构建监督模型,进而根据重要性筛选特征,来确定要根据哪些特征赋予含义。---使用于你想构造什么,目前还不清楚。
【上面这个思路好好学,这是真干货,构造具有价值的特征工程,妥妥的创新点和工作量】
X.columns
Index(['Id', 'Home Ownership', 'Annual Income', 'Years in current job','Tax Liens', 'Number of Open Accounts', 'Years of Credit History','Maximum Open Credit', 'Number of Credit Problems','Months since last delinquent', 'Bankruptcies', 'Long Term','Current Loan Amount', 'Current Credit Balance', 'Monthly Debt','Credit Score', 'Purpose_business loan', 'Purpose_buy a car','Purpose_buy house', 'Purpose_debt consolidation','Purpose_educational expenses', 'Purpose_home improvements','Purpose_major purchase', 'Purpose_medical bills', 'Purpose_moving','Purpose_other', 'Purpose_renewable energy', 'Purpose_small business','Purpose_take a trip', 'Purpose_vacation', 'Purpose_wedding','KMeans_Cluster'],dtype='object')
x1= X.drop('KMeans_Cluster',axis=1) # 删除聚类标签列
y1 = X['KMeans_Cluster']
# 构建随机森林,用shap重要性来筛选重要性
import shap
import numpy as np
from sklearn.ensemble import RandomForestClassifier # 随机森林分类器
model = RandomForestClassifier(n_estimators=100, random_state=42) # 随机森林模型
model.fit(x1, y1) # 训练模型,此时无需在意准确率 直接全部数据用来训练了
RandomForestClassifier(random_state=42)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
shap.initjs()
# 初始化 SHAP 解释器
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(x1) # 这个计算耗时
shap_values.shape # 第一维是样本数,第二维是特征数,第三维是类别数
(7500, 31, 3)
# --- 1. SHAP 特征重要性条形图 (Summary Plot - Bar) ---
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()
--- 1. SHAP 特征重要性条形图 ---
# 此时判断一下这几个特征是离散型还是连续型
import pandas as pd
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 可能是离散型变量
# X["Purpose_debt consolidation"].value_counts() # 统计每个唯一值的出现次数
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[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()
# 绘制出每个簇对应的这四个特征的分布图
X[['KMeans_Cluster']].value_counts()
KMeans_Cluster 0 5205 1 1381 2 914 dtype: int64
# 分别筛选出每个簇的数据
X_cluster0 = X[X['KMeans_Cluster'] == 0]
X_cluster1 = X[X['KMeans_Cluster'] == 1]
X_cluster2 = X[X['KMeans_Cluster'] == 2]
# 先绘制簇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_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的分布图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_cluster1[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()
# 先绘制簇2的分布图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_cluster2[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()
把这三个簇的图发给ai,让ai给你定义
2. 簇的总结与定义
- 第一个簇 - 优质信用稳健财务型
- 特征总结:在债务合并用途上表现一致,几乎无破产记录,信用问题极少,资金用途集中且很少涉及特殊类别。财务状况稳定,信用良好,资金流向明确。
- 定义依据:各项关键财务和信用指标表现优异,显示出良好的财务自律性和信用履约能力,所以定义为 “优质信用稳健财务型”。
- 第二个簇 - 较稳健但信用有分化财务型
- 特征总结:多数无债务合并需求,破产情况少见,但信用问题上存在个体差异,资金用途有一定分散性。整体财务状况相对稳定,但在信用和资金使用方向上不如第一个簇表现一致。
- 定义依据:虽然总体财务状况尚可,但信用记录和资金用途的分化情况使其区别于第一个簇,因此定义为 “较稳健但信用有分化财务型”。
- 第三个簇 - 高风险财务困境型
- 特征总结:债务合并需求分化,破产经历较多,信用问题普遍且严重,资金用途有差异。在财务健康和信用方面存在诸多问题,面临较大财务风险。
- 定义依据:基于明显的财务困境迹象和高风险特征,定义为 “高风险财务困境型”。
现在你就得到了一个全新的特征,完成了你的特征工程
后续研究需要对这个特征独热编码,然后重新建模训练,如果加了这个特征后模型精度提高,说明这个特征是有用的。
二、作业
参考示例代码对心脏病数据集采取类似操作,并且评估特征工程后模型效果有无提升。
1. 聚类分析
# 环境设置
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.preprocessing import StandardScaler, LabelEncoder
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from sklearn.metrics import silhouette_score # 添加缺失的导入
import shap
import warnings
warnings.filterwarnings("ignore")# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False# 1. 数据加载与预处理
def load_and_preprocess():# 加载数据df = pd.read_csv('heart.csv')# 显示列名用于调试print("数据集列名:", df.columns.tolist())# 自动识别目标变量(假设最后一列为目标变量)target_col = df.columns[-1]print(f"\n自动识别目标变量: {target_col}")# 处理分类变量(自动检测)categorical_cols = df.select_dtypes(include=['object', 'category']).columns.tolist()print("\n检测到的分类变量:", categorical_cols)# 标签编码le = LabelEncoder()for col in categorical_cols:df[col] = le.fit_transform(df[col])# 处理缺失值df.fillna(df.median(numeric_only=True), inplace=True)# 分离特征和目标变量X = df.drop(target_col, axis=1) y = df[target_col]# 标准化scaler = StandardScaler()X_scaled = scaler.fit_transform(X)return X_scaled, X, y, target_col# 2. KMeans聚类分析
def perform_clustering(X_scaled):# 寻找最优K值inertia = []silhouette = []k_range = range(2, 8)for k in k_range:kmeans = KMeans(n_clusters=k, random_state=42)labels = kmeans.fit_predict(X_scaled)inertia.append(kmeans.inertia_)silhouette.append(silhouette_score(X_scaled, labels)) # 现在可以正常使用# 可视化评估指标plt.figure(figsize=(12,4))plt.subplot(1,2,1)plt.plot(k_range, inertia, 'bo-')plt.title('肘部法则')plt.xlabel('簇数量')plt.subplot(1,2,2)plt.plot(k_range, silhouette, 'ro-')plt.title('轮廓系数')plt.xlabel('簇数量')plt.tight_layout()plt.show()# 选择K=3进行聚类kmeans = KMeans(n_clusters=3, random_state=42)clusters = kmeans.fit_predict(X_scaled)return clusters# 3. 特征重要性分析
def analyze_features(X, clusters):# 添加聚类标签X_clustered = X.copy()X_clustered['Cluster'] = clusters# 训练随机森林模型from sklearn.ensemble import RandomForestClassifiermodel = RandomForestClassifier(n_estimators=100, random_state=42)model.fit(X, clusters)# SHAP分析explainer = shap.TreeExplainer(model)shap_values = explainer.shap_values(X)# 特征重要性可视化plt.figure(figsize=(10,6))shap.summary_plot(shap_values, X, plot_type="bar", show=False)plt.title('SHAP特征重要性')plt.show()return X_clustered# 4. 聚类结果解释
def interpret_clusters(X_clustered):# PCA可视化pca = PCA(n_components=2)X_pca = pca.fit_transform(X_clustered.drop('Cluster', axis=1))plt.figure(figsize=(8,6))sns.scatterplot(x=X_pca[:,0], y=X_pca[:,1], hue=X_clustered['Cluster'], palette='viridis', alpha=0.8)plt.title('聚类结果可视化 (PCA降维)')plt.xlabel('主成分1')plt.ylabel('主成分2')plt.show()# 关键特征分析print("\n各簇特征分布:")print(X_clustered.groupby('Cluster').agg(['mean', 'median']).T)# 5. 特征工程效果验证
def evaluate_improvement(X_clustered, y, target_col):from sklearn.ensemble import GradientBoostingClassifierfrom sklearn.model_selection import train_test_splitfrom sklearn.metrics import accuracy_score# 添加聚类特征X_new = X_clustered.copy()X_new = pd.get_dummies(X_new, columns=['Cluster'], prefix='Cluster')# 划分数据集X_train, X_test, y_train, y_test = train_test_split(X_new, y, test_size=0.3, random_state=42)# 基准模型base_model = GradientBoostingClassifier(random_state=42)base_model.fit(X_train.drop(columns=X_new.filter(regex='Cluster_').columns), y_train)base_acc = accuracy_score(y_test, base_model.predict(X_test.drop(columns=X_new.filter(regex='Cluster_').columns)))# 新模型new_model = GradientBoostingClassifier(random_state=42)new_model.fit(X_train, y_train)new_acc = accuracy_score(y_test, new_model.predict(X_test))print(f"\n基准模型准确率: {base_acc:.4f}")print(f"新增特征后准确率: {new_acc:.4f}")print(f"准确率提升: {(new_acc - base_acc):.4f}")# 主流程
if __name__ == "__main__":# 数据预处理X_scaled, X, y, target_col = load_and_preprocess()# 显示预处理后的数据print("\n预处理后的数据样例:")print(pd.DataFrame(X_scaled, columns=X.columns).head())# 聚类分析clusters = perform_clustering(X_scaled)# 特征分析X_clustered = analyze_features(X, clusters)# 结果解释interpret_clusters(X_clustered)# 效果验证evaluate_improvement(X_clustered, y, target_col)
输出结果:
数据集列名: ['age', 'sex', 'cp', 'trestbps', 'chol', 'fbs', 'restecg', 'thalach', 'exang', 'oldpeak', 'slope', 'ca', 'thal', 'target']
自动识别目标变量: target
检测到的分类变量: []
预处理后的数据样例:
age sex cp trestbps chol fbs restecg \
0 0.952197 0.681005 1.973123 0.763956 -0.256334 2.394438 -1.005832
1 -1.915313 0.681005 1.002577 -0.092738 0.072199 -0.417635 0.898962
2 -1.474158 -1.468418 0.032031 -0.092738 -0.816773 -0.417635 -1.005832
3 0.180175 0.681005 0.032031 -0.663867 -0.198357 -0.417635 0.898962
4 0.290464 -1.468418 -0.938515 -0.663867 2.082050 -0.417635 0.898962
thalach exang oldpeak slope ca thal
0 0.015443 -0.696631 1.087338 -2.274579 -0.714429 -2.148873
1 1.633471 -0.696631 2.122573 -2.274579 -0.714429 -0.512922
2 0.977514 -0.696631 0.310912 0.976352 -0.714429 -0.512922
3 1.239897 -0.696631 -0.206705 0.976352 -0.714429 -0.512922
4 0.583939 1.435481 -0.379244 0.976352 -0.714429 -0.512922
各簇特征分布:
Cluster 0 1 2
age mean 58.092784 58.150538 48.053097median 59.000000 58.000000 48.000000
sex mean 0.814433 0.268817 0.911504median 1.000000 0.000000 1.000000
cp mean 0.185567 1.419355 1.265487median 0.000000 2.000000 1.000000
trestbps mean 135.876289 133.397849 126.513274median 132.000000 132.000000 125.000000
chol mean 254.752577 257.817204 229.469027median 254.000000 248.000000 229.000000
fbs mean 0.185567 0.182796 0.088496median 0.000000 0.000000 0.000000
restecg mean 0.432990 0.440860 0.681416median 0.000000 0.000000 1.000000
thalach mean 129.824742 150.516129 165.946903median 131.000000 154.000000 168.000000
exang mean 0.731959 0.150538 0.123894median 1.000000 0.000000 0.000000
oldpeak mean 1.965979 0.673118 0.546018median 1.800000 0.400000 0.000000
slope mean 0.979381 1.430108 1.734513median 1.000000 1.000000 2.000000
ca mean 1.381443 0.344086 0.486726median 1.000000 0.000000 0.000000
thal mean 2.597938 1.956989 2.362832median 3.000000 2.000000 2.000000基准模型准确率: 0.7802
新增特征后准确率: 0.8132
准确率提升: 0.0330
2. 簇的总结与定义
(1)Cluster 0(紫色) - 高风险集中群体
分布特征:主成分1(+100 ~ +300)与主成分2(+20 ~ +60)双高区域
潜在特性:
- 可能具有高静息血压(RestingBP)与高胆固醇(Cholesterol)组合
- 年龄分布可能偏大(主成分1正方向常与年龄正相关)
- 最大心率(MaxHR)指标可能较低(与主成分2正相关呈反向趋势)
风险特征:心血管代谢指标异常集中,建议重点关注潜在冠心病高危人群
(2)Cluster 1(青色) - 中度风险过渡群体
分布特征:主成分1(-50 ~ +200)与主成分2(-20 ~ +40)广泛分布
潜在特性:
- 血压与胆固醇指标呈现中间值
- 可能包含非典型症状患者(ST段压低oldpeak值中等)
- 运动诱发心绞痛(exng)发生率具有波动性
风险特征:临床指标存在异质性,需结合其他诊断参数进行分层管理
(3)Cluster 2(黄色) - 低风险健康群体
分布特征:主成分1(-100 ~ +50)与主成分2(-60 ~ 0)双低区域
潜在特性:
- 静息血压与胆固醇水平最优
- 最大心率保持最佳生理范围
- 血管通畅度指标(caa)可能最优
风险特征:心血管系统功能指标良好,建议作为健康对照组重点研究对象
3. 模型效果提升
评估特征工程后模型效果有无提升
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.metrics import accuracy_score, roc_auc_score, f1_score
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt# 1. 数据加载与预处理
def load_data():df = pd.read_csv('heart.csv')# 自动识别目标变量(假设最后一列)target_col = df.columns[-1]print(f"目标变量: {target_col}")# 处理分类变量categorical_cols = df.select_dtypes(include=['object']).columnsle = LabelEncoder()for col in categorical_cols:df[col] = le.fit_transform(df[col])# 填充缺失值df.fillna(df.median(numeric_only=True), inplace=True)# 分离特征和标签X = df.drop(target_col, axis=1)y = df[target_col]return X, y, target_col# 2. 特征工程(添加聚类特征)
def add_cluster_features(X):# 标准化scaler = StandardScaler()X_scaled = scaler.fit_transform(X)# KMeans聚类kmeans = KMeans(n_clusters=3, random_state=42)clusters = kmeans.fit_predict(X_scaled)# 添加聚类特征X_new = X.copy()X_new['Cluster'] = clusters# PCA可视化验证pca = PCA(n_components=2)X_pca = pca.fit_transform(X_scaled)plt.figure(figsize=(8,6))sns.scatterplot(x=X_pca[:,0], y=X_pca[:,1], hue=clusters, palette='viridis', alpha=0.8)plt.title('特征工程后的聚类分布')plt.xlabel('主成分1')plt.ylabel('主成分2')plt.show()return X_new# 3. 模型评估对比
def evaluate_improvement(X_original, X_enhanced, y):# 划分数据集X_train_base, X_test_base, y_train, y_test = train_test_split(X_original, y, test_size=0.3, random_state=42)X_train_enh, X_test_enh = train_test_split(X_enhanced, test_size=0.3, random_state=42)[:2]# 基准模型base_model = GradientBoostingClassifier(random_state=42)base_model.fit(X_train_base, y_train)base_pred = base_model.predict(X_test_base)# 增强模型enhanced_model = GradientBoostingClassifier(random_state=42)enhanced_model.fit(X_train_enh, y_train)enhanced_pred = enhanced_model.predict(X_test_enh)# 指标对比metrics = {'准确率': (accuracy_score(y_test, base_pred), accuracy_score(y_test, enhanced_pred)),'AUC': (roc_auc_score(y_test, base_model.predict_proba(X_test_base)[:,1]), roc_auc_score(y_test, enhanced_model.predict_proba(X_test_enh)[:,1])),'F1': (f1_score(y_test, base_pred), f1_score(y_test, enhanced_pred))}# 可视化对比metrics_df = pd.DataFrame(metrics, index=['基准模型', '增强模型']).Tmetrics_df.plot(kind='bar', figsize=(10,6), color=['skyblue', 'orange'])plt.title('模型性能对比')plt.ylabel('分数')plt.xticks(rotation=0)plt.ylim(0, 1.05)plt.show()return metrics_df# 主流程
if __name__ == "__main__":# 数据准备X, y, target = load_data()# 特征工程X_enhanced = add_cluster_features(X)# 性能评估print("\n模型性能对比:")results = evaluate_improvement(X, X_enhanced, y)print(results)# 效果总结improvement = (results['增强模型'] - results['基准模型']).mean()print(f"\n平均性能提升: {improvement:.2%}")if improvement > 0.05:print("✅ 特征工程显著提升模型性能")elif improvement > 0:print("⚠️ 特征工程带来小幅提升")else:print("❌ 特征工程未产生积极效果")
目标变量: target
模型性能对比:
基准模型 增强模型
准确率 0.780220 0.835165
AUC 0.870244 0.883902
F1 0.791667 0.842105
平均性能提升: 3.97%
⚠️ 特征工程带来小幅提升
@浙大疏锦行
相关文章:
Python训练营打卡——DAY18(2025.5.7)
目录 一、基于聚类进一步推断类型 1. 聚类分析 2. 簇的总结与定义 二、作业 1. 聚类分析 2. 簇的总结与定义 3. 模型效果提升 一、基于聚类进一步推断类型 选用昨天kmeans得到的效果进行聚类,进而推断出每个簇的实际含义。 1. 聚类分析 # 先运行之前预处理…...
初学Python爬虫
文章目录 前言一、 爬虫的初识1.1 什么是爬虫1.2 爬虫的核心1.3 爬虫的用途1.4 爬虫分类1.5 爬虫带来的风险1.6. 反爬手段1.7 爬虫网络请求1.8 爬虫基本流程 二、urllib库初识2.1 http和https协议2.2 编码解码的使用2.3 urllib的基本使用2.4 一个类型六个方法2.5 下载网页数据2…...
【CSS】Grid 的 auto-fill 和 auto-fit 内容自适应
CSS Grid 的 auto-fill 和 auto-fit /* 父元素 */ .grid {display: grid;/* 定义「网格容器」里有多少列,以及每列的宽度 *//* repeat 是个「重复函数」,表示后面的模式会被重复多次 *//* auto-fit 是一个特殊值,自动根据容器宽度ÿ…...
绕线机的制作与研究
绕线机的制作与研究 摘要 本文详细阐述了绕线机的制作过程,涵盖从设计规划到实际制作的各个环节。通过对绕线机工作原理的深入分析,确定了关键技术参数,并依此完成机械结构与控制系统的设计。在制作阶段,运用多种加工工艺完成零件制造与设备组装。经测试,自制绕线机性能…...
引用的使用
引用的语法 作用:起别名 引用的本质是指针常量 数据类型 &别名原名; 引用必须要初始化 引用一旦初始化,不能修改 不能返回局部变量的引用 引用做形参 #include<iostream> #include<string> using namespace std; //通过引用…...
css animation 动画属性
animation // 要绑定的关键帧规则名称 animation-name: slidein;// 定义动画完成一个周期所需的时间,秒或毫秒 animation-duration: 3s;// 定义动画速度曲线 animation-timing-function: ease;// 定义动画开始前的延迟时间 animation-delay: 1s;// 定义动画播放次数…...
Nacos源码—Nacos集群高可用分析(二)
4.集群节点的健康状态变动时的数据同步 (1)Nacos后台管理的集群管理模块介绍 在集群管理模块下,可以看到每个节点的状态和元数据。节点IP就是节点的IP地址以及端口,节点状态就是标识当前节点是否可用,节点元数据就是相关的Raft信息。 其中节点…...
SRAM详解
一、SRAM基础原理 定义与结构 SRAM(Static Random-Access Memory,静态随机存取存储器)是一种基于触发器(Flip-Flop)结构的易失性内存,通过交叉耦合的反相器(6晶体管,6T单元ÿ…...
JavaWeb:MySQL进阶
多表设计 一对多(多对一) 外键 一对一 多对多 多表查询 内连接 外连接 子查询 -- 查询员工表 select * from emp;-- 查询部门表 select * from dept;-- 查询员工和部门 select * from emp, dept; -- 笛卡尔积select * from emp, dept where emp.dept_i…...
Golang 接口 vs Rust Trait:一场关于抽象的哲学对话
一、引言 在现代编程语言中,接口(Interface) 和 Trait 是实现多态和抽象行为的关键机制。它们允许我们定义行为契约,让不同的类型共享相同的语义接口,从而提升代码的复用性和扩展性。 Go 和 Rust 分别代表了两种截然…...
智算中心的搭建标准
智算中心的搭建标准主要涉及以下几个方面: 开放标准: 硬件与软件开放:从硬件到软件、从芯片到架构,都应采用开放、标准的技术。例如,硬件支持如 OCP、ODCC、Open19 等开放社区标准,软件采用如 OpenStack、K…...
商汤科技前端面试题及参考答案
有没有配置过 webpack,讲一下 webpack 热更新原理,能否自己实现一些插件? Webpack 是一个用于现代 JavaScript 应用程序的静态模块打包工具。在实际项目中,经常会对其进行配置,以满足项目的各种需求,比如处理不同类型的文件、优化代码、配置开发服务器等。 Webpack 热更…...
windows下docker的使用
找了个docker教程 Windows Docker 安装 | 菜鸟教程Windows Docker 安装 Docker 并非是一个通用的容器工具,它依赖于已存在并运行的 Linux 内核环境。Docker 实质上是在已经运行的 Linux 下制造了一个隔离的文件环境,因此它执行的效率几乎等同于所部署的…...
AI日报 · 2025年5月07日|谷歌发布 Gemini 2.5 Pro 预览版 (I/O 版本),大幅提升编码与视频理解能力
1、谷歌发布 Gemini 2.5 Pro 预览版 (I/O 版本),大幅提升编码与视频理解能力 谷歌于5月6日提前发布 Gemini 2.5 Pro 预览版 (I/O 版本),为开发者带来更强编码能力,尤其优化了前端与UI开发、代码转换及智能体工作流构建,并在WebDe…...
Redis 8.0 正式版发布,新特性很强!
就在前两天,Redis 8.0 正式版 (GA) 来了!这并不是一次简单的更新,Redis 8.0 不仅带来了性能上的进一步提升,还带来一些实用的新特性与功能增强。并且,最重要的是拥抱 AGPLv3 重归开源! 下面,简单…...
MySQL核心机制:日志系统、锁机制与事务管理的深度剖析
一.介绍 MySQL作为世界上最流行的开源关系型数据库之一,其强大的事务处理能力和高并发支持使其在各种复杂应用场景中得到广泛应用。MySQL的核心机制包括日志系统、锁机制和事务管理,这些机制共同确保了数据库的ACID特性,为应用程序提供了可靠…...
Mybatis标签使用 -association 绑定对象,collection 绑定集合
注意 association标签中的 select , column 属性使用 collection 标签中的 ofType 属性使用 Data public class Tours implements Serializable {private static final long serialVersionUID 1L;private Integer touId;private String tourName;private Integer guideId;pri…...
IBM BAW(原BPM升级版)使用教程Toolkit介绍
本部分为“IBM BAW(原BPM升级版)使用教程系列”内容的补充。 一、系统Toolkit 在 IBM Business Automation Workflow (BAW) 中,System Toolkit 是一组预先定义和配置好的工具、功能和组件,旨在帮助流程设计者和开发人员快速构建…...
排列组合算法:解锁数据世界的魔法钥匙
在 C 算法的奇幻世界里,排列和组合算法就像是两把神奇的魔法钥匙,能够帮我们解锁数据世界中各种复杂问题的大门。今天,作为 C 算法小白的我,就带大家一起走进排列和组合算法的奇妙天地。 排列算法:创造所有可能的顺序…...
LVGL -meter的应用
1 meter介绍 lv_meter 是 LVGL v8 引入的一种图形控件,用于创建仪表盘样式的用户界面元素,它可以模拟像速度表、电压表、温度表这类模拟表盘。它通过可视化刻度、指针、颜色弧线等来展示数值信息,是一种非常直观的数据展示控件。 1.1 核心特…...
MCP学习
一、MCP基础理论与核心概念 1.1 协议定义与设计目标 MCP(Model Context Protocol)是Anthropic公司于2024年11月开源的标准化协议,旨在解决大型语言模型(LLM)与外部工具、数据源之间的动态交互问题。其核心目标包括&…...
软件工程(三):模块的内聚模型
模块内聚的7种类型(从低到高) 等级类型描述示例1️⃣ 最低偶然性内聚(Coincidental Cohesion)模块内部的各功能毫无关系,随机拼凑一个模块中既有文件读写,又有图像压缩、还处理用户登录2️⃣逻辑性内聚&am…...
Java中字符转数字的原理解析 - 为什么char x - ‘0‘能得到对应数字
前言 在Java编程中,我们经常需要将字符形式的数字转换为实际的数值。有很多方法可以实现这一转换,比如使用Integer.parseInt()或Character.getNumericValue()等方法。但有一种简便且高效的方式是直接使用char - 0运算,本文将详细解析这种方法…...
View的事件分发机制
(一)为什么要有事件分发机制 安卓界面上面的View的层级结构是树形的,可能出现多个View重叠在一起的现象(如下图),当我们点击的地方为多个View重叠的区域时,这个点击事件应该给谁呢?为…...
【C++】类和对象【下】
目录 一、再探构造函数1、测试题 二、类型转换三、static成员1. 静态成员变量2. 静态成员函数 四、友元五、内部类六、匿名对象七、对象拷贝时的编译器优化 个人主页<—请点击 C专栏<—请点击 一、再探构造函数 之前我们实现构造函数时,初始化成员变量主要使…...
【JS逆向基础】并发爬虫
前言:所谓并发编程是指在一台处理器上“同时”处理多个任务。并发是在同一实体上的多个事件。强调多个事件在同一时间间隔发生。 1,进程、线程以及协程 【1】进程概念 我们都知道计算机的核心是CPU,它承担了所有的计算任务;而操作系统是计算…...
Android组件化 -> 基础组件进行Application,Activity生命周期分发
在lib_common基础组件模块创建上下文持有类,生命周期派发类 object AppContextProvider {private lateinit var application: Applicationprivate var currentActivityRef: WeakReference<Activity>? null// 应用生命周期监听器列表private val appLifecyc…...
42. PCB防静电环设计
PCB防静电环的作用 1. PCB防静电环的作用2. 防静电环设计技术点 1. PCB防静电环的作用 防静电环主要用于生产、运输、售后等环节人体会直接接触电路板的场景。 防静电环只在顶层和底层设计即可。 2. 防静电环设计技术点...
深入理解Java反射机制
java反射是java语言中一个强大而灵活的特性,它允许程序在运行时检查和操作类、接口、字段和方法。 为了方便理解下文,我先给出Cat对象 public class Cat implements jump,Run {private int age;public String name;protected String color;double he…...
嵌入式音视频通话EasyRTC基于WebRTC技术驱动智能带屏音箱:开启智能交互新体验
一、引言 随着智能家居市场的蓬勃发展,智能带屏音箱作为家庭智能交互中心的重要组成部分,其功能需求日益丰富。EasyRTC凭借其低延迟、高稳定性的特点,为智能带屏音箱带来了全新的交互体验,能满足用户在视频通话、远程监控、在线…...
1987-2023年各省进出口总额数据整理(含进口和出口)(无缺失)
1987-2023年各省进出口总额数据整理(含进口和出口)(无缺失) 1、时间:1987-2023年 2、来源:各省年鉴、统计公报 3、指标:进出口总额(万美元)、进口总额(万美…...
paddle ocr 或 rapid ocr umi ocr 只识别了图片的下部分内容 解决方案
如上图,识别的准确率其实很高,但是只识别了下半部分的内容,上半部分的内容就没有识别到,其实是程序设置有点问题,程序设置的解决方案如下: 如上图,识别的准确率其实很高,但是只识别了下半部分的内容,上半部分的内容就没有识别到,其实是程序设置有点问题,程序设置的…...
【深度学习-Day 7】精通Pandas:从Series、DataFrame入门到数据清洗实战
Langchain系列文章目录 01-玩转LangChain:从模型调用到Prompt模板与输出解析的完整指南 02-玩转 LangChain Memory 模块:四种记忆类型详解及应用场景全覆盖 03-全面掌握 LangChain:从核心链条构建到动态任务分配的实战指南 04-玩转 LangChai…...
如何测试 esp-webrtc-solution_solutions_doorbell_demo 例程?
软件准备 esp-webrtc-solution/solutions/doorbell_demo 例程 此例程集成了 WebSocket 传输视频流的应用 硬件准备 ESP32P4-Function-Ev-Board 环境搭建 推荐基于 esp-idf v5.4.1 版本的环境来编译此例程 若编译时出现依赖的组件报错,可进行如下修改ÿ…...
default和delete final和override
1.default和delete default 1.生成默认成员函数 2.仅适用于特殊成员函数(如构造函数、析构函数、拷贝/移动操作等) delete 1.删除函数 2.可应用于任何函数(不限于特殊成员函数) 2.final 和override final 用于类:…...
Nvidia Orin 安装onnxruntime-gpu
在用英伟达边缘设备Nvidia Orin 安装onnxruntime-gpu环境时, 通常会遇到很多问题。 在正常的Nvidia 服务器上安装onnxruntime-gpu 是非常简单的, 直接pip install onnxruntime-gpu即可, 但是在边缘设备上就没有这么简单了。 直接pip install…...
C++ CRTP技术(奇异递归模版模式)
C 的CRTP技术 最近了解到C的CRTP技术,通过博客来这里记录一下。 我们首先可以了解一下什么是CRTP技术。CRTP是C的一种高级模版变成模式。 他主要的用途有以下的几点: 编译时实现多态(静态多态):通过CRTP技术…...
验证es启动成功
1. 查看命令行输出信息 在启动 Elasticsearch 时,命令行窗口会输出一系列日志信息。若启动成功,日志里通常会有类似下面的信息: plaintext [2025-05-06T13:20:00,000][INFO ][o.e.n.Node ] [node_name] started其中 [node_na…...
AI工场全面激活电商创意链
在当今科技飞速发展的时代,北京先智先行科技有限公司凭借其卓越的创新能力,推出了“先知大模型”、“先行AI商学院”以及“先知AIGC超级工场”这三款旗舰产品,在市场上掀起了不小的波澜。 传统电商设计流程,从需求确认到营销策…...
数 学 函数
gcd int gcd(int a,int b){while(a%b){int ca%b;ab;bc;}return b; } 错位排列 typedef long long ll; ll d(int n){if(n1) return 0;if(n2) return 1;return (n-1)*(d(n-1)d(n-2)); } 快速幂 //注意看是否有mod的需求 int q_pow(int a,int b){int ans1,tempa;while(b){if(…...
springboot集成langchain4j记忆对话
流式输出 LLM 一次生成一个标记(token),因此许多 LLM 提供商提供了一种方式,可以逐个标记地流式传输响应,而不是等待整个文本生成完毕。 这显著改善了用户体验,因为用户不需要等待未知的时间,几…...
C语言初阶:数组
目录 0.数组要讲的知识点 1.一维数组的创建和初始化 1.1 数组的创建: 1.2数组实例: 1.3 数组的初识化: 例子: 2.一维数组的使用 例子: 总结: 3.一维数组在内存中的存储 4.二维数组的创建和初始化 4.…...
案例分享 | 攻克ADAS开发测试难题,实现单元动态测试新突破
汽车行业中的代码动态测试:守护智能汽车的安全与质量 在当今汽车行业,智能网联汽车的快速发展让软件成为了汽车的核心竞争力之一。从自动驾驶辅助系统到车载信息娱乐系统,汽车中的软件数量和复杂度都在不断增加。然而,软件的复杂…...
K8S 基于本地存储的持久卷
假设有如下三个节点的 K8S 集群: k8s31master 是控制节点 k8s31node1、k8s31node2 是工作节点 容器运行时是 containerd 一、背景分析 阅读本文,默认您有 PV-PVC、hostPath 相关知识。 由于安全方面的考虑,K8S 官方并不推荐 hostPath …...
LED实验
目录 1.LED介绍 1.1LED原理图: 2.单片机运行代码的流程 3.进制的转换 4.C51数据类型 5.小编的单片机型号:STC89C52RC/LE52RC,最高波特率:9600 6.点亮一个LED 代码 步骤 代码: 7.LED闪烁 在STC内操作&#x…...
python+pytest接口自动化测试--日志记录
前言:代码可以直接复制使用 解决问题: 问题1:日志重复记录的问题,比如运行一个模块日志会记录很多遍(通过handlers是否存在解决的) 问题2:运行测试用例进行多个模块相互调用.日志记录不全的问题(通过共享公共的handlers解决问题) 首先写一个日志记录的工具 # 这个是个日志的…...
Android 蓝牙开发调试总结
Android 蓝牙开发调试总结 文章目录 Android 蓝牙开发调试总结一、前言二、蓝牙开发1、开关和连接控制2、相关日志3、相关广播4、demo示例 三、其他1、Android 蓝牙开发调试小结2、Android14 蓝牙启动流程3、Android14 蓝牙 BluetoothService 启动和相关代码介绍4、Android13 蓝…...
混淆矩阵(Confusion Matrix)
混淆矩阵(Confusion Matrix)是一个用于评估分类模型性能的工具,特别是在机器学习和统计学领域。它展示了模型预测结果与实际结果之间的关系。混淆矩阵通常用于二分类或多分类问题中,但也可以扩展到更多类别的情况。 一、混淆矩阵…...
C语言——操作符
一.操作符的分类 算术操作符: - * / %移位操作符:<< >>位操作符: & | ^赋值操作符: - * / % > & | ^单⽬操作符: ! -- & * - ~ sizeof …...
大数据处理利器:Hadoop 入门指南
一、Hadoop 是什么?—— 分布式计算的基石 在大数据时代,处理海量数据需要强大的技术支撑,Hadoop 应运而生。Apache Hadoop 是一个开源的分布式计算框架,致力于为大规模数据集提供可靠、可扩展的分布式处理能力。其核心设计理念是…...