建外贸商城网站,世界十大电商平台,2017优惠券网站怎么做,河北建设工程信息网查前言#xff1a; 在昨天我们已经实现了利用多种聚类方法对已有数据集进行相应的聚类#xff0c;在今天我们将推断聚类后簇的类型#xff0c;并以此为依据建立新的特征工程#xff0c;并评估利用结合新的特征工程后模型的效果有无提升#xff0c;如果精度提高则说明此特征是…前言在昨天我们已经实现了利用多种聚类方法对已有数据集进行相应的聚类在今天我们将推断聚类后簇的类型并以此为依据建立新的特征工程并评估利用结合新的特征工程后模型的效果有无提升如果精度提高则说明此特征是有用的。一、推断思路如何从聚类的数学结果中提炼出有实际业务意义的“簇含义”思路一从起点就聚焦有明确目标时适用场景你已经知道要分析什么业务问题。操作步骤特征预选在聚类前只选择与你的分析目标直接相关的特征执行聚类用这些特征进行K-Means等聚类结果解释聚类结果自然反映了所选特征维度的模式举例目标分析“消费者购买习惯”选择特征购买频次、客单价、品类偏好、消费时间分布等不选特征年龄、职业、地域等与购买习惯不直接相关的特征结果每个簇代表一种购买习惯类型如“高频小金额”、“低频大额”、“周末购物者”优点结果解释性强目标明确缺点可能忽略其他维度的潜在模式思路二从结果倒推探索性分析时适用场景你不清楚数据中隐藏什么模式想探索发现。操作步骤全特征聚类用所有可用特征进行聚类得到簇标签得到聚类结果如簇0、簇1、簇2...构建监督模型X 所有特征y 聚类得到的标签训练分类模型如随机森林特征重要性分析识别哪些特征最能区分不同簇赋予含义根据重要特征解释每个簇的特点举例用100个客户特征聚类得到5个簇用随机森林分析发现簇0最重要的特征是“最近购买时间”和“促销敏感度”→ 可能是“即将流失客户”簇1最重要的特征是“客单价”和“奢侈品购买”→ 可能是“高净值客户”这样“倒推”出每个簇的业务含义优点能发现意想不到的模式缺点解释过程复杂可能需要业务知识辅助二、具体实现我们以心脏病数据集为例在昨天代码的基础上增加以下步骤1、构建随机森林模型、利用shap来筛选重要的特征2、取前四个贡献度最高的特征并分出来连续和离散特征以各自样本数为纵坐标以各个簇的类型为横坐标分别绘制箱线图和直方图。运行代码# 先运行之前预处理好的代码 import pandas as pd #用于数据处理和分析可处理表格数据。 import numpy as np #用于数值计算提供了高效的数组操作。 import matplotlib.pyplot as plt #用于绘制各种类型的图表 import seaborn as sns #基于matplotlib的高级绘图库能绘制更美观的统计图形。 import warnings from sklearn.utils import resample from sklearn.model_selection import train_test_split warnings.filterwarnings(ignore) # 设置中文字体解决中文显示问题 plt.rcParams[font.sans-serif] [SimHei] # Windows系统常用黑体字体 plt.rcParams[axes.unicode_minus] False # 正常显示负号 df pd.read_csv(rD:\Python60DaysChallenge-main\heart.csv) X df.iloc[:, :-1] y df.iloc[:, -1] # 切分数据 X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.2, random_state42) 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_clustersk, random_state42) 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(fk{k}, 惯性: {kmeans.inertia_:.2f}, 轮廓系数: {silhouette:.3f}, CH 指数: {ch:.2f}, DB 指数: {db:.3f}) # 绘制评估指标图 - 调整版解决标签重叠问题 plt.figure(figsize(18, 12)) # 增大图形尺寸 # 肘部法则图Inertia plt.subplot(2, 2, 1) plt.plot(k_range, inertia_values, markero, linewidth2, markersize8) plt.title(肘部法则确定最优聚类数 k\n惯性越小越好, fontsize10, pad15) # 添加换行和增加标题间距 plt.xlabel(聚类数 (k), fontsize10) plt.ylabel(惯性, fontsize12) plt.xticks(k_range) # 明确设置x轴刻度 plt.grid(True, alpha0.3) plt.tight_layout(pad3.0) # 增加子图间距 # 轮廓系数图 plt.subplot(2, 2, 2) plt.plot(k_range, silhouette_scores, markero, colororange, linewidth2, markersize8) plt.title(轮廓系数确定最优聚类数 k\n越大越好, fontsize10, pad15) plt.xlabel(聚类数 (k), fontsize10) plt.ylabel(轮廓系数, fontsize12) plt.xticks(k_range) plt.grid(True, alpha0.3) # CH 指数图 plt.subplot(2, 2, 3) plt.plot(k_range, ch_scores, markero, colorgreen, linewidth2, markersize8) plt.title(Calinski-Harabasz 指数确定最优聚类数 k\n越大越好, fontsize10, pad15) plt.xlabel(聚类数 (k), fontsize10) plt.ylabel(CH 指数, fontsize12) plt.xticks(k_range) plt.grid(True, alpha0.3) # DB 指数图 plt.subplot(2, 2, 4) plt.plot(k_range, db_scores, markero, colorred, linewidth2, markersize8) plt.title(Davies-Bouldin 指数确定最优聚类数 k\n越小越好, fontsize10, pad15) plt.xlabel(聚类数 (k), fontsize10) plt.ylabel(DB 指数, fontsize12) plt.xticks(k_range) plt.grid(True, alpha0.3) # 调整整体布局增加间距 plt.subplots_adjust(wspace0.2, hspace0.4) # 增加水平和垂直间距 plt.suptitle(KMeans聚类评估指标对比, fontsize16, y0.98) # 添加总标题 plt.show() # 提示用户选择 k 值 selected_k 3 # 使用选择的 k 值进行 KMeans 聚类 kmeans KMeans(n_clustersselected_k, random_state42) kmeans_labels kmeans.fit_predict(X_scaled) X[KMeans_Cluster] kmeans_labels # 使用 PCA 降维到 2D 进行可视化 pca PCA(n_components2) X_pca pca.fit_transform(X_scaled) # KMeans 聚类结果可视化 plt.figure(figsize(6, 5)) sns.scatterplot(xX_pca[:, 0], yX_pca[:, 1], huekmeans_labels, paletteviridis) plt.title(fKMeans Clustering with k{selected_k} (PCA Visualization)) plt.xlabel(PCA Component 1) plt.ylabel(PCA Component 2) plt.show() # 打印 KMeans 聚类标签的前几行 print(fKMeans Cluster labels (k{selected_k}) added to X:) print(X[[KMeans_Cluster]].value_counts()) x1 X.drop(KMeans_Cluster,axis1) # 删除聚类标签列 y1 X[KMeans_Cluster] # 构建随机森林用shap重要性来筛选重要性 import shap import numpy as np from sklearn.ensemble import RandomForestClassifier # 随机森林分类器 model RandomForestClassifier(n_estimators100, random_state42) # 随机森林模型 model.fit(x1, y1) # 训练模型,此时无需在意准确率 直接全部数据用来训练了 shap.initjs() # 初始化 SHAP 解释器 explainer shap.TreeExplainer(model) shap_values explainer.shap_values(x1) # 这个计算耗时 shap_values.shape # 第一维是样本数第二维是特征数第三维是类别数 # --- 1. SHAP 特征重要性条形图 (Summary Plot - Bar) --- print(--- 1. SHAP 特征重要性条形图 ---) shap.summary_plot(shap_values[:, :, 0], x1, plot_typebar,showFalse) # 这里的showFalse表示不直接显示图形,这样可以继续用plt来修改元素不然就直接输出了 plt.title(SHAP Feature Importance (Bar Plot)) plt.show() # 此时判断一下这几个特征是离散型还是连续型 import pandas as pd selected_features [age, thalach, slope, sex] 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} 可能是连续型变量) # 绘制出每个簇对应的这四个特征的分布图 X[[KMeans_Cluster]].value_counts() # 分别筛选出每个簇的数据 X_cluster0 X[X[KMeans_Cluster] 0] X_cluster1 X[X[KMeans_Cluster] 1] X_cluster2 X[X[KMeans_Cluster] 2] # 简化的特征分布图绘制 - 优化版本横坐标为簇标签 import matplotlib.pyplot as plt import numpy as np # 设置全局字体参数 plt.rcParams.update({ font.size: 10, axes.titlesize: 12, axes.labelsize: 11, xtick.labelsize: 10, ytick.labelsize: 10, legend.fontsize: 10, figure.titlesize: 14, }) # 设置图形参数 plt.figure(figsize(20, 16)) # 选择的特征 selected_features [age, thalach, slope, sex] feature_names [年龄, 最大心率, 斜率, 性别] # 遍历每个特征 for i, (feature, feature_name) in enumerate(zip(selected_features, feature_names), 1): plt.subplot(2, 2, i) # 判断特征类型 unique_count X[feature].nunique() if unique_count 10: # 离散特征绘制分组柱状图 # 获取特征的所有可能值 feature_values sorted(X[feature].unique()) # 为sex特征添加中文标签 if feature sex: feature_labels [女, 男] # 0女, 1男 else: feature_labels [str(v) for v in feature_values] # 准备数据x轴为簇分组为特征值 cluster_labels [簇 0, 簇 1, 簇 2] bar_width 0.8 / len(feature_values) # 根据特征值数量调整宽度 # 设置颜色映射为每个特征值分配固定颜色 if feature slope: # 斜率为每个取值分配不同颜色 slope_colors { 0: lightblue, 1: orange, 2: lightgreen } bar_colors [slope_colors.get(val, gray) for val in feature_values] elif feature sex: # 性别为每个取值分配不同颜色 sex_colors { 0: lightblue, 1: orange } bar_colors [sex_colors.get(val, gray) for val in feature_values] else: # 其他离散特征使用默认颜色 bar_colors plt.cm.tab10(np.arange(len(feature_values)) / len(feature_values)) for j, (feature_val, color) in enumerate(zip(feature_values, bar_colors)): counts [] for cluster_id in range(3): cluster_data X[X[KMeans_Cluster] cluster_id] count (cluster_data[feature] feature_val).sum() counts.append(count) # 计算x位置 x_pos np.arange(3) # 三个簇 offset (j - (len(feature_values)-1)/2) * bar_width # 绘制柱状图 bars plt.bar(x_pos offset, counts, bar_width, colorcolor, # 设置柱状图颜色 alpha0.7) # 在柱状图上方添加数值标签 for k, val in enumerate(counts): if val 0: plt.text(x_pos[k] offset, val 0.5, str(val), hacenter, vabottom, fontsize9, fontweightbold) # 设置x轴标签为簇 plt.xticks(x_pos, cluster_labels, fontsize10, rotation0) # 设置y轴范围 max_val X[feature].value_counts().max() plt.ylim(0, max_val * 1.2) plt.title(f{feature_name}分布 (离散特征), fontsize12, pad12) # 添加图例说明 if feature slope: plt.text(0.02, 0.98, 蓝色:斜率0\n橙色:斜率1\n绿色:斜率2, transformplt.gca().transAxes, fontsize9, verticalalignmenttop, bboxdict(boxstyleround, facecolorwheat, alpha0.5)) elif feature sex: plt.text(0.02, 0.98, 蓝色:女性(0)\n橙色:男性(1), transformplt.gca().transAxes, fontsize9, verticalalignmenttop, bboxdict(boxstyleround, facecolorwheat, alpha0.5)) else: # 连续特征绘制箱线图保持原样 data_to_plot [] cluster_labels [簇 0, 簇 1, 簇 2] for cluster_id in range(3): cluster_data X[X[KMeans_Cluster] cluster_id] data_to_plot.append(cluster_data[feature].dropna()) # 绘制箱线图 box plt.boxplot(data_to_plot, labelscluster_labels, patch_artistTrue, widths0.6) # 设置颜色 colors [lightblue, lightgreen, lightcoral] for patch, color in zip(box[boxes], colors): patch.set_facecolor(color) patch.set_alpha(0.7) # 设置中位数线颜色 for median in box[medians]: median.set_color(red) median.set_linewidth(2) # 在箱线图上添加统计信息 for j, (cluster_id, data) in enumerate(zip(range(3), data_to_plot)): if len(data) 0: # 显示中位数 median_val np.median(data) plt.text(j 1, median_val, f{median_val:.1f}, hacenter, vabottom, fontsize9, fontweightbold, colordarkred) plt.title(f{feature_name}分布 (连续特征), fontsize12, pad12) # 设置坐标轴标签 if unique_count 10: plt.xlabel(聚类簇, fontsize11, labelpad10) else: plt.xlabel(聚类簇, fontsize11, labelpad10) # 根据特征类型设置纵坐标标签 if feature age: plt.ylabel(年龄分布, fontsize11, labelpad10) elif feature thalach: plt.ylabel(最大心率数值, fontsize11, labelpad10) else: plt.ylabel(样本数量, fontsize11, labelpad10) # 设置图例 if i 1: # 只在第一个子图显示图例 plt.legend(locupper right, fontsize10, framealpha0.9, borderpad0.5, labelspacing0.5, titlef{feature_name}取值) # 添加网格 plt.grid(True, alpha0.2, linestyle--, axisy) # 调整整体布局 plt.subplots_adjust(wspace0.35, hspace0.4, top0.92, bottom0.08, left0.08, right0.95) plt.suptitle(KMeans聚类各簇特征分布分析 (k3), fontsize16, fontweightbold, y0.96) plt.show()运行结果图shap库分析结果聚类特征分布三个簇的特征定义与分析簇 0蓝色主要特征年龄相对年轻年龄中位数约58岁最大心率心率最高中位数约168斜率主要集中为2可能是向上斜表示心脏功能较好性别以男性为主簇定义年轻男性心脏功能较好组这是最年轻的一组心脏功能表现最佳运动时心率能达到较高水平常见于相对健康的年轻男性患者簇 1绿色主要特征年龄最年轻中位数约53岁最大心率心率中等中位数约131斜率分布相对均衡性别女性比例显著高于其他组簇定义年轻女性心脏功能中等组这是最年轻的一组且以女性为主心率表现中等可能反映生理差异或健康状况年龄分布相对集中簇 2红色主要特征年龄最年长中位数约58.5岁最大心率心率最低中位数约131斜率主要集中为1可能是平坦或向下表示心脏功能可能较差性别以男性为主簇定义年长男性心脏功能较差组年龄最大的一组心率表现最差可能反映心脏功能受限斜率分布表明可能有更多心脏功能问题三、验证结果新的特征工程是否有效将聚类获得的新的特征加入到原来的特征上再分析比较多个模型在交叉验证准确率以及F1分数上的变化情况。运行代码# # 新增代码对聚类结果进行独热编码并评估模型效果 # from sklearn.preprocessing import OneHotEncoder from sklearn.ensemble import RandomForestClassifier from sklearn.linear_model import LogisticRegression from sklearn.svm import SVC from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score from sklearn.model_selection import cross_val_score, StratifiedKFold import matplotlib.pyplot as plt import pandas as pd import numpy as np # 保存原始数据用于对比 X_original df.iloc[:, :-1].copy() y_original df.iloc[:, -1].copy() print( * 70) print(特征工程前模型性能评估) print( * 70) # 1. 特征工程前的基准模型性能 def evaluate_models(X_data, y_data, title特征工程前): 评估多个模型在不同特征集上的性能 # 定义模型 models { Random Forest: RandomForestClassifier(n_estimators100, random_state42), Logistic Regression: LogisticRegression(max_iter1000, random_state42), SVM: SVC(probabilityTrue, random_state42) } # 使用5折交叉验证 cv StratifiedKFold(n_splits5, shuffleTrue, random_state42) print(f\n{title} - 5折交叉验证结果:) print(- * 50) results {} for model_name, model in models.items(): # 交叉验证 cv_scores cross_val_score(model, X_data, y_data, cvcv, scoringaccuracy) # 训练模型获取详细指标 train_accuracies [] test_accuracies [] f1_scores [] for train_idx, test_idx in cv.split(X_data, y_data): X_train_fold, X_test_fold X_data.iloc[train_idx], X_data.iloc[test_idx] y_train_fold, y_test_fold y_data.iloc[train_idx], y_data.iloc[test_idx] model.fit(X_train_fold, y_train_fold) # 训练集准确率 y_train_pred model.predict(X_train_fold) train_acc accuracy_score(y_train_fold, y_train_pred) # 测试集准确率 y_test_pred model.predict(X_test_fold) test_acc accuracy_score(y_test_fold, y_test_pred) # F1分数 f1 f1_score(y_test_fold, y_test_pred, averageweighted) train_accuracies.append(train_acc) test_accuracies.append(test_acc) f1_scores.append(f1) # 存储结果 results[model_name] { cv_mean: cv_scores.mean(), cv_std: cv_scores.std(), train_mean: np.mean(train_accuracies), test_mean: np.mean(test_accuracies), f1_mean: np.mean(f1_scores) } print(f{model_name}:) print(f 交叉验证准确率: {cv_scores.mean():.4f} (±{cv_scores.std():.4f})) print(f 训练集准确率: {np.mean(train_accuracies):.4f}) print(f 测试集准确率: {np.mean(test_accuracies):.4f}) print(f F1分数: {np.mean(f1_scores):.4f}) print() return results # 评估原始特征 baseline_results evaluate_models(X_original, y_original) print(\n * 70) print(对聚类结果进行独热编码并加入特征) print( * 70) # 2. 对KMeans聚类结果进行独热编码 kmeans_labels X[KMeans_Cluster].values.reshape(-1, 1) # 使用OneHotEncoder encoder OneHotEncoder(sparse_outputFalse, dropfirst) cluster_encoded encoder.fit_transform(kmeans_labels) # 创建编码后的特征名 cluster_feature_names [fCluster_{i} for i in range(1, selected_k)] # dropfirst所以特征数减少1 # 将独热编码特征转换为DataFrame cluster_encoded_df pd.DataFrame( cluster_encoded, columnscluster_feature_names, indexX_original.index ) print(f聚类独热编码特征: {cluster_feature_names}) print(f聚类独热编码特征形状: {cluster_encoded_df.shape}) print(f每个聚类编码特征的样本分布:) for i, col in enumerate(cluster_feature_names, 1): count cluster_encoded_df[col].sum() print(f {col}: {int(count)} 个样本 ({count/len(X_original)*100:.1f}%)) # 3. 创建新的特征集原始特征 聚类编码特征 X_with_clusters pd.concat([X_original, cluster_encoded_df], axis1) print(f\n原始特征数量: {X_original.shape[1]}) print(f新增聚类特征数量: {cluster_encoded_df.shape[1]}) print(f合并后总特征数量: {X_with_clusters.shape[1]}) print(f样本数量: {X_with_clusters.shape[0]}) print(\n * 70) print(特征工程后模型性能评估) print( * 70) # 4. 评估特征工程后的模型性能 enhanced_results evaluate_models(X_with_clusters, y_original, title特征工程后) # 5. 性能对比分析 print( * 70) print(特征工程前后模型性能对比分析) print( * 70) comparison_data [] for model_name in baseline_results.keys(): baseline baseline_results[model_name] enhanced enhanced_results[model_name] # 计算准确率提升 accuracy_improvement enhanced[cv_mean] - baseline[cv_mean] accuracy_pct_improvement (accuracy_improvement / baseline[cv_mean]) * 100 if baseline[cv_mean] 0 else 0 # 计算F1分数提升 f1_improvement enhanced[f1_mean] - baseline[f1_mean] f1_pct_improvement (f1_improvement / baseline[f1_mean]) * 100 if baseline[f1_mean] 0 else 0 comparison_data.append({ Model: model_name, Baseline_Acc: baseline[cv_mean], Enhanced_Acc: enhanced[cv_mean], Accuracy_Improvement: accuracy_improvement, Accuracy_%_Improvement: accuracy_pct_improvement, Baseline_F1: baseline[f1_mean], Enhanced_F1: enhanced[f1_mean], F1_Improvement: f1_improvement, F1_%_Improvement: f1_pct_improvement }) print(f\n{model_name}:) print(f 准确率: {baseline[cv_mean]:.4f} → {enhanced[cv_mean]:.4f} f(变化: {accuracy_improvement:.4f}, {accuracy_pct_improvement:.2f}%)) print(f F1分数: {baseline[f1_mean]:.4f} → {enhanced[f1_mean]:.4f} f(变化: {f1_improvement:.4f}, {f1_pct_improvement:.2f}%)) # 6. 可视化性能对比 plt.figure(figsize(14, 8)) # 准确率对比图 plt.subplot(1, 2, 1) models [d[Model] for d in comparison_data] baseline_acc [d[Baseline_Acc] for d in comparison_data] enhanced_acc [d[Enhanced_Acc] for d in comparison_data] x np.arange(len(models)) width 0.35 plt.bar(x - width/2, baseline_acc, width, label原始特征, alpha0.8, colorlightblue) plt.bar(x width/2, enhanced_acc, width, label原始特征聚类特征, alpha0.8, colorlightcoral) plt.xlabel(模型, fontsize12) plt.ylabel(交叉验证准确率, fontsize12) plt.title(特征工程前后准确率对比, fontsize14, fontweightbold) plt.xticks(x, models) plt.legend() plt.grid(True, alpha0.3, axisy) # 在每个柱子上添加数值 for i, (b, e) in enumerate(zip(baseline_acc, enhanced_acc)): plt.text(i - width/2, b 0.01, f{b:.3f}, hacenter, vabottom, fontsize9) plt.text(i width/2, e 0.01, f{e:.3f}, hacenter, vabottom, fontsize9) # 添加提升百分比 improvement (e - b) * 100 plt.text(i, max(b, e) 0.02, f{improvement:.1f}%, hacenter, vabottom, fontsize10, fontweightbold, colorgreen if improvement 0 else red) # F1分数对比图 plt.subplot(1, 2, 2) baseline_f1 [d[Baseline_F1] for d in comparison_data] enhanced_f1 [d[Enhanced_F1] for d in comparison_data] plt.bar(x - width/2, baseline_f1, width, label原始特征, alpha0.8, colorlightgreen) plt.bar(x width/2, enhanced_f1, width, label原始特征聚类特征, alpha0.8, colororange) plt.xlabel(模型, fontsize12) plt.ylabel(F1分数, fontsize12) plt.title(特征工程前后F1分数对比, fontsize14, fontweightbold) plt.xticks(x, models) plt.legend() plt.grid(True, alpha0.3, axisy) # 在每个柱子上添加数值 for i, (b, e) in enumerate(zip(baseline_f1, enhanced_f1)): plt.text(i - width/2, b 0.01, f{b:.3f}, hacenter, vabottom, fontsize9) plt.text(i width/2, e 0.01, f{e:.3f}, hacenter, vabottom, fontsize9) # 添加提升百分比 improvement (e - b) * 100 plt.text(i, max(b, e) 0.02, f{improvement:.1f}%, hacenter, vabottom, fontsize10, fontweightbold, colorgreen if improvement 0 else red) plt.tight_layout() plt.suptitle(特征工程效果对比分析, fontsize16, fontweightbold, y1.02) plt.show() # 7. 分析聚类特征的重要性 print(\n * 70) print(聚类特征重要性分析) print( * 70) # 使用随机森林分析特征重要性 rf_model RandomForestClassifier(n_estimators100, random_state42) rf_model.fit(X_with_clusters, y_original) # 获取特征重要性 feature_importance pd.DataFrame({ feature: X_with_clusters.columns, importance: rf_model.feature_importances_ }).sort_values(importance, ascendingFalse) print(\nTop 10最重要的特征:) print(- * 50) for i, row in feature_importance.head(10).iterrows(): print(f{row[feature]:20} 重要性: {row[importance]:.4f}) # 分析聚类特征的排名 print(\n聚类特征的相对重要性:) print(- * 50) cluster_features_rank [] for cluster_feat in cluster_feature_names: if cluster_feat in feature_importance[feature].values: rank feature_importance[feature_importance[feature] cluster_feat].index[0] 1 importance feature_importance[feature_importance[feature] cluster_feat][importance].values[0] cluster_features_rank.append((cluster_feat, rank, importance)) for feat, rank, imp in sorted(cluster_features_rank, keylambda x: x[1]): print(f{feat:15} 排名: {rank:2d}/{len(feature_importance)} 重要性: {imp:.4f}) # 8. 总结分析 print(\n * 70) print(特征工程效果总结) print( * 70) # 计算整体提升 avg_accuracy_improvement np.mean([d[Accuracy_Improvement] for d in comparison_data]) avg_f1_improvement np.mean([d[F1_Improvement] for d in comparison_data]) print(f\n平均准确率提升: {avg_accuracy_improvement:.4f}) print(f平均F1分数提升: {avg_f1_improvement:.4f}) if avg_accuracy_improvement 0: print(f✓ 特征工程有效模型准确率平均提升了 {avg_accuracy_improvement*100:.2f}%) if avg_f1_improvement 0: print(f✓ 同时F1分数也提升了 {avg_f1_improvement*100:.2f}%说明特征工程改善了模型的综合性能) else: print(f✗ 特征工程效果不明显准确率平均变化 {avg_accuracy_improvement*100:.2f}%) # 找出提升最大的模型 best_model max(comparison_data, keylambda x: x[Accuracy_Improvement]) print(f\n提升最大的模型: {best_model[Model]}) print(f 准确率提升: {best_model[Accuracy_Improvement]*100:.2f}%) print(f F1分数提升: {best_model[F1_Improvement]*100:.2f}%) # 保存特征工程后的数据 X_final X_with_clusters.copy() y_final y_original.copy() print(f\n最终数据集形状:) print(f 特征数量: {X_final.shape[1]}) print(f 样本数量: {X_final.shape[0]}) # 9. 额外分析不同模型对聚类特征的敏感度 print(\n * 70) print(不同模型对聚类特征的敏感度分析) print( * 70) # 训练-测试集划分比例对结果的影响 test_sizes [0.2, 0.3, 0.4] test_size_results {} for test_size in test_sizes: X_train, X_test, y_train, y_test train_test_split( X_with_clusters, y_original, test_sizetest_size, random_state42, stratifyy_original ) model_performance {} for model_name, model in { Random Forest: RandomForestClassifier(n_estimators100, random_state42), Logistic Regression: LogisticRegression(max_iter1000, random_state42) }.items(): model.fit(X_train, y_train) y_pred model.predict(X_test) acc accuracy_score(y_test, y_pred) f1 f1_score(y_test, y_pred, averageweighted) model_performance[model_name] {accuracy: acc, f1: f1} test_size_results[test_size] model_performance # 输出不同测试集大小的结果 for test_size, perf in test_size_results.items(): print(f\n测试集比例: {test_size*100:.0f}%) for model_name, scores in perf.items(): print(f {model_name}: 准确率{scores[accuracy]:.4f}, F1分数{scores[f1]:.4f}) print(\n * 70) print(特征工程完成) print( * 70)运行结果总结可以看出KMeans聚类作为特征工程方法是有效的特别是对于树模型。在实际部署时建议采用特征工程后的Random Forest模型。浙大疏锦行