基于不同特征层级的SVM-RFE:全淘汰阶段性能与特征追踪问询
实现SVM-RFE分阶段特征淘汰并追踪性能与保留特征
嘿,这个需求其实很常见,用scikit-learn就能轻松搞定,关键是要控制RFE的淘汰节奏,同时把每个阶段的结果都记录下来。我给你捋清楚步骤,附上可运行的代码:
核心思路
- 必须用线性核SVM作为基础模型:因为RFE需要通过模型的
coef_属性评估特征重要性,只有线性核SVM才有这个属性 - 用RFE的
step=0.1参数:让每次迭代自动淘汰当前特征集的10% - 手动迭代追踪结果:默认RFE只会返回最终的特征子集,所以我们需要循环执行RFE,每次记录当前阶段的特征数、准确率和保留特征
完整代码实现
import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.svm import SVC from sklearn.model_selection import cross_val_score from sklearn.feature_selection import RFE from sklearn.datasets import make_classification # ---------------------- 1. 准备数据(替换成你自己的数据集即可) ---------------------- # 模拟生成1000特征的二分类数据集,你可以替换成X = 你的特征矩阵,y = 标签向量 X, y = make_classification(n_samples=2000, n_features=1000, n_informative=100, random_state=42) # ---------------------- 2. 初始化模型与追踪变量 ---------------------- # 初始化线性SVM分类器(必须用linear kernel,否则没有coef_无法进行RFE) svc = SVC(kernel='linear', random_state=42) # 初始化三个列表,分别记录每个阶段的特征数、准确率、保留特征索引 feature_counts = [] accuracy_scores = [] retained_features = [] # 初始特征索引:所有1000个特征都保留 current_features = np.arange(X.shape[1]) # ---------------------- 3. 循环执行SVM-RFE并追踪结果 ---------------------- while len(current_features) > 0: # 记录当前阶段的特征数量 feature_counts.append(len(current_features)) # 用当前特征集训练模型,用5折交叉验证计算平均准确率(避免过拟合,结果更可靠) X_current = X[:, current_features] avg_acc = cross_val_score(svc, X_current, y, cv=5, scoring='accuracy').mean() accuracy_scores.append(avg_acc) # 记录当前阶段保留的特征索引(注意用copy()避免后续修改影响已保存的数据) retained_features.append(current_features.copy()) # 如果只剩1个特征,停止循环(再淘汰就没特征了) if len(current_features) == 1: break # 初始化RFE,每次淘汰当前特征的10% rfe = RFE(estimator=svc, step=0.1, verbose=0) # 用当前特征集拟合RFE rfe.fit(X_current, y) # 更新当前特征集:保留RFE选中的特征 current_features = current_features[rfe.support_] # ---------------------- 4. 结果查看与可视化 ---------------------- # 把结果转成DataFrame,方便查看和分析 results_df = pd.DataFrame({ '特征数量': feature_counts, '5折平均准确率': accuracy_scores, '保留特征索引': retained_features }) # 打印前5个阶段的结果 print("前5个阶段的特征淘汰结果:") print(results_df.head()) # 绘制准确率随特征数量变化的折线图 plt.figure(figsize=(10,6)) plt.plot(feature_counts, accuracy_scores, marker='o', color='#1f77b4', linestyle='-') plt.xlabel('特征数量', fontsize=12) plt.ylabel('5折交叉验证平均准确率', fontsize=12) plt.title('SVM-RFE特征淘汰阶段准确率变化趋势', fontsize=14) plt.grid(True, alpha=0.3) plt.show()
关键细节说明
- 交叉验证的必要性:用
cross_val_score而不是单一训练测试集,是为了避免数据划分带来的偶然性,让准确率更具参考性 - 特征索引的追踪:每次保存
current_features.copy()是因为列表是可变对象,直接赋值会导致后续修改覆盖之前的记录 - 停止条件:当特征数只剩1时停止循环,确保我们能获取到最后一个特征的性能数据
如何获取指定阶段的结果
比如你想查看900个特征阶段的信息:
# 找到特征数量为900的行索引 idx = results_df[results_df['特征数量'] == 900].index[0] # 获取该阶段的准确率和保留特征 acc_900 = results_df.loc[idx, '5折平均准确率'] feats_900 = results_df.loc[idx, '保留特征索引'] print(f"900特征阶段的平均准确率:{acc_900:.4f}") print(f"900特征阶段保留的前10个特征索引:{feats_900[:10]}")
内容的提问来源于stack exchange,提问作者Malik Yousef




