本文目录导读:

我来详细介绍如何使用Scikit-learn进行递归特征消除(RFE):
基本RFE使用示例
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_classification
from sklearn.metrics import accuracy_score, classification_report
# 生成示例数据
X, y = make_classification(
n_samples=1000,
n_features=20,
n_informative=5,
n_redundant=5,
n_repeated=0,
n_classes=2,
random_state=42
)
# 创建特征名称
feature_names = [f'feature_{i}' for i in range(X.shape[1])]
df = pd.DataFrame(X, columns=feature_names)
df['target'] = y
print("原始数据形状:", X.shape)
print("特征数量:", X.shape[1])
基本RFE实现
# 分割数据
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 标准化
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# 使用Logistic Regression作为评估器
estimator = LogisticRegression(max_iter=1000, random_state=42)
# 创建RFE对象,选择10个最佳特征
selector = RFE(estimator, n_features_to_select=10, step=1)
# 拟合数据
selector.fit(X_train_scaled, y_train)
# 查看选择的特征
selected_features = np.where(selector.support_)[0]
print("选择的特征索引:", selected_features)
print("特征排名:", selector.ranking_)
# 转换数据
X_train_selected = selector.transform(X_train_scaled)
X_test_selected = selector.transform(X_test_scaled)
print("\n选择后的特征数量:", X_train_selected.shape[1])
# 训练模型
model = LogisticRegression(max_iter=1000)
model.fit(X_train_selected, y_train)
# 预测
y_pred = model.predict(X_test_selected)
print("准确率:", accuracy_score(y_test, y_pred))
使用交叉验证的RFECV
from sklearn.feature_selection import RFECV
import matplotlib.pyplot as plt
# RFECV:自动选择最优特征数量
estimator = SVC(kernel="linear", C=1)
# 创建RFECV对象
selector_cv = RFECV(
estimator,
step=1,
cv=5, # 5折交叉验证
scoring='accuracy',
min_features_to_select=1,
n_jobs=-1
)
# 拟合数据
selector_cv.fit(X_train_scaled, y_train)
# 结果分析
print("最优特征数量:", selector_cv.n_features_)
print("选择的特征:", np.where(selector_cv.support_)[0])
print("特征排名:", selector_cv.ranking_)
# 可视化交叉验证得分
plt.figure(figsize=(10, 6))
plt.plot(range(1, len(selector_cv.cv_results_['mean_test_score']) + 1),
selector_cv.cv_results_['mean_test_score'])
plt.xlabel('Number of features selected')
plt.ylabel('Cross-validation score (accuracy)')'RFECV - Feature Selection')
plt.grid(True)
plt.show()
完整案例:糖尿病预测
from sklearn.datasets import load_diabetes
# 加载糖尿病数据集
diabetes = load_diabetes()
X_diab = diabetes.data
y_diab = diabetes.target
feature_names_diab = diabetes.feature_names
print("糖尿病数据集特征:", feature_names_diab)
print("数据形状:", X_diab.shape)
# 分割数据
X_train_d, X_test_d, y_train_d, y_test_d = train_test_split(
X_diab, y_diab, test_size=0.2, random_state=42
)
# 使用RFE进行特征选择
estimator = RandomForestClassifier(n_estimators=100, random_state=42)
selector_diab = RFE(estimator, n_features_to_select=5)
# 拟合
selector_diab.fit(X_train_d, y_train_d)
# 显示选择的特征
selected_features_diab = [feature_names_diab[i] for i in range(len(selector_diab.support_))
if selector_diab.support_[i]]
print("选择的特征:", selected_features_diab)
print("所有特征排名:", list(zip(feature_names_diab, selector_diab.ranking_)))
高级用法:不同评估器比较
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
# 定义不同的评估器
estimators = {
'Logistic Regression': LogisticRegression(max_iter=1000),
'Decision Tree': DecisionTreeClassifier(),
'Random Forest': RandomForestClassifier(n_estimators=100),
'SVM': SVC(kernel='linear')
}
results = {}
for name, estimator in estimators.items():
print(f"\n使用 {name} 作为评估器:")
# RFE
selector = RFE(estimator, n_features_to_select=10)
selector.fit(X_train_scaled, y_train)
# 转换数据
X_train_sel = selector.transform(X_train_scaled)
X_test_sel = selector.transform(X_test_scaled)
# 训练模型
model = estimator.__class__(**estimator.get_params())
model.fit(X_train_sel, y_train)
# 评估
score = model.score(X_test_sel, y_test)
results[name] = {
'score': score,
'selected_features': np.where(selector.support_)[0]
}
print(f"准确率: {score:.4f}")
print(f"选择特征: {results[name]['selected_features']}")
# 输出比较结果
print("\n=== 比较结果 ===")
for name, result in results.items():
print(f"{name}: 准确率={result['score']:.4f}, 特征数={len(result['selected_features'])}")
自定义评估函数
from sklearn.metrics import f1_score, make_scorer
from sklearn.model_selection import StratifiedKFold
# 自定义评分函数
def custom_scorer(y_true, y_pred):
return f1_score(y_true, y_pred, average='weighted')
# 创建自定义 scorer
my_scorer = make_scorer(custom_scorer)
# 使用自定义评分
estimator = RandomForestClassifier(n_estimators=100)
selector_custom = RFECV(
estimator,
step=1,
cv=StratifiedKFold(5),
scoring=my_scorer,
min_features_to_select=1
)
selector_custom.fit(X, y)
print("使用自定义评分:")
print("最优特征数量:", selector_custom.n_features_)
print("选择的特征:", np.where(selector_custom.support_)[0])
重要参数说明
# RFE的重要参数
selector = RFE(
estimator, # 使用的评估器
n_features_to_select=None, # 要选择的特征数量,None则选择一半
step=1, # 每次迭代移除的特征数量
verbose=1 # 是否显示详细信息
)
# RFECV的重要参数
selector_cv = RFECV(
estimator, # 使用的评估器
step=1, # 每次迭代移除的特征数量
cv=5, # 交叉验证折数
scoring='accuracy', # 评分标准
min_features_to_select=1, # 最少保留的特征数量
n_jobs=-1, # 并行计算,-1使用所有CPU
verbose=1 # 是否显示详细信息
)
特征重要性分析
# 查看特征重要性排序
feature_importance = pd.DataFrame({
'feature': [f'feature_{i}' for i in range(X.shape[1])],
'ranking': selector_cv.ranking_,
'selected': selector_cv.support_
})
# 按排名排序
feature_importance_sorted = feature_importance.sort_values('ranking')
print("特征重要性排序:")
print(feature_importance_sorted)
# 可视化
plt.figure(figsize=(12, 6))
plt.bar(range(len(selector_cv.ranking_)), selector_cv.ranking_)
plt.xlabel('Feature Index')
plt.ylabel('Ranking (1=Best)')'Feature Rankings from RFE')
plt.show()
使用建议
-
选择合适的评估器:RFE的性能依赖于评估器,线性模型适合线性问题,树模型适合非线性问题
-
调整step参数:对于大量特征,可以设置较大的step值来加速计算
-
使用RFECV:当不确定选择多少特征时,使用交叉验证自动选择最优数量
-
标准化数据:对于基于距离的模型(如SVM、KNN),记得先标准化数据
-
计算成本:RFE计算成本较高,特征数量很大时考虑使用其他方法
这个案例展示了RFE的主要用法,可以根据具体需求调整参数和评估器。