常见的特征筛选算法
- 方差筛选
- 皮尔逊相关系数筛选
- lasso筛选
- 树模型重要性
- shap重要性
- 递归特征消除REF
1.数据预处理
# 导入必要的库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.cluster import KMeans, DBSCAN, AgglomerativeClustering
from sklearn.preprocessing import StandardScaler, MinMaxScaler
from sklearn.decomposition import PCA
# 读取数据
data = pd.read_csv(r'heart.csv')
# 定义离散变量与连续变量
discrete_features = ['sex', 'cp', 'fbs', 'restecg', 'exang', 'slope', 'thal']
continuous_features = ['age', 'trestbps', 'chol', 'thalach', 'oldpeak']
print('离散变量:', discrete_features)
print('连续变量:', continuous_features)
# 对没有顺序的离散变量进行独热编码
data = pd.get_dummies(data, columns=discrete_features)
data2 = pd.read_csv("heart.csv")
list_final = [] # 新建一个空列表,用于存放独热编码后新增的特征名
for i in data.columns:
if i not in data2.columns:
list_final.append(i) # 这里打印出来的就是独热编码后的特征名
list_final
for i in list_final:
data[i] = data[i].astype(int) # 这里的 i 就是独热编码后的特征名
# 对连续变量进行归一化
min_max_scaler = MinMaxScaler()
data[continuous_features] = min_max_scaler.fit_transform(data[continuous_features])
# 提取特征列(去掉目标列 'target')
X = data.drop(columns=['target'])
# 标准化数据(聚类前通常需要标准化)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 导入必要的库
from sklearn.model_selection import train_test_split # 添加这一行
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, accuracy_score
from sklearn.metrics import classification_report, confusion_matrix #用于生成分类报告和混淆矩阵
# 划分数据集
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) # 80%训练集,20%测试集
# 初始化随机森林分类器
rf_clf = RandomForestClassifier(n_estimators=100, random_state=42)
# 训练模型
rf_clf.fit(X_train, y_train)
# 预测
y_pred = rf_clf.predict(X_test)
# 输出结果
print("随机森林分类器的准确率:", accuracy_score(y_test, y_pred))
print("\n分类报告:\n", classification_report(y_test, y_pred))
print("默认随机森林 在测试集上的混淆矩阵:")
print(confusion_matrix(y_test, rf_pred_var))
2.特征降维
特征降维一般有2种策略:
1. 特征筛选:从n个特征中筛选出m个特征,比如方差筛选,剔除方差过小的特征;利用皮尔逊相关系数筛选;lasso筛选(lasso自带的系数可以理解为重要性)、利用树模型自带的重要性、shap重要性等筛选;特征递归方法
2. 特征组合:从n个特征中组合出m个特征,如pca等
方差筛选
方差筛选是一种简单而有效的特征筛选方法。它的核心逻辑是:特征的方差反映了数据的变化程度,方差很小的特征几乎没有变化,对模型的预测帮助不大。比如,一个特征的值在所有样本中几乎都一样(方差接近0),那么它对区分不同类别或预测结果几乎没有贡献。因此,方差筛选会设定一个方差阈值,剔除方差低于这个阈值的特征,保留那些变化较大的特征,从而减少特征数量,提高模型效率。
# 打印标题,表明这是方差筛选的部分
print("--- 方差筛选 (Variance Threshold) ---")
# 导入需要的工具库
from sklearn.feature_selection import VarianceThreshold # 方差筛选工具,用于剔除方差小的特征
import time # 用于记录代码运行时间,方便比较效率
# 记录开始时间,后面会计算整个过程耗时
start_time = time.time()
# 创建方差筛选器,设置方差阈值为0.01
# 阈值是指方差的最小值,低于这个值的特征会被删除(可以根据数据情况调整阈值)
selector = VarianceThreshold(threshold=0.01)
# 对训练数据进行方差筛选,fit_transform会计算每个特征的方差并剔除不满足阈值的特征
# X_train是原始训练数据,X_train_var是筛选后的训练数据
X_train_var = selector.fit_transform(X_train)
# 对测试数据应用同样的筛选规则,transform会直接用训练数据的筛选结果处理测试数据
# X_test是原始测试数据,X_test_var是筛选后的测试数据
X_test_var = selector.transform(X_test)
# 获取被保留下来的特征名称
# selector.get_support()返回一个布尔值列表,表示哪些特征被保留,这个是selector这个实例化的类的一个方法
# X_train.columns是特征的名称,结合布尔值列表可以提取保留特征的名字
selected_features_var = X_train.columns[selector.get_support()].tolist()
# 打印筛选后保留的特征数量和具体特征名称,方便查看结果
print(f"方差筛选后保留的特征数量: {len(selected_features_var)}")
print(f"保留的特征: {selected_features_var}")
# 创建一个随机森林分类模型,用于在筛选后的数据上进行训练和预测
# random_state=42是为了保证每次运行结果一致,方便教学和对比
rf_model_var = RandomForestClassifier(random_state=42)
# 在筛选后的训练数据上训练模型
# X_train_var是筛选后的特征数据,y_train是对应的目标标签
rf_model_var.fit(X_train_var, y_train)
# 使用训练好的模型对筛选后的测试数据进行预测
# X_test_var是筛选后的测试特征数据,rf_pred_var是预测结果
rf_pred_var = rf_model_var.predict(X_test_var)
# 记录结束时间,计算整个训练和预测过程的耗时
end_time = time.time()
print(f"训练与预测耗时: {end_time - start_time:.4f} 秒")
# 打印模型在测试集上的分类报告,展示模型的性能
# 分类报告包括精确率、召回率、F1分数等指标,帮助评估模型好坏
print("\n方差筛选后随机森林在测试集上的分类报告:")
print(classification_report(y_test, rf_pred_var))
# 打印混淆矩阵,展示模型预测的详细结果
# 混淆矩阵显示了真实标签和预测标签的对应情况,比如多少样本被正确分类,多少被错分
print("方差筛选后随机森林在测试集上的混淆矩阵:")
print(confusion_matrix(y_test, rf_pred_var))
皮尔逊相关系数筛选
皮尔逊相关系数筛选是一种基于特征与目标变量之间相关性的特征选择方法。它的核心逻辑是:计算每个特征与目标变量之间的相关系数(范围在-1到1之间,值越大表示正相关越强,值越小表示负相关越强,接近0表示几乎无关),然后根据相关系数的绝对值大小,选择与目标变量相关性较高的特征,剔除相关性较低的特征。这种方法适用于目标变量是连续型的情况(如果是分类问题,可以先对目标变量编码)。通过皮尔逊相关系数筛选,我们可以保留那些对预测目标最有帮助的特征,减少无关或冗余特征的干扰。
皮尔逊相关系数筛选法是一种基于变量相关性的经典特征选择技术,常用于处理目标变量为连续型的场景。若面对分类问题,通常需要先对目标变量进行编码处理,将其转化为数值型数据后再开展分析。
print("--- 皮尔逊相关系数筛选 ---")
from sklearn.feature_selection import SelectKBest, f_classif
import time
start_time = time.time()
# 计算特征与目标变量的相关性,选择前k个特征(这里设为15个,可调整)
# 注意:皮尔逊相关系数通常用于回归问题(连续型目标变量),但如果目标是分类问题,可以用f_classif
k = 15
selector = SelectKBest(score_func=f_classif, k=k)
X_train_corr = selector.fit_transform(X_train, y_train)
X_test_corr = selector.transform(X_test)
# 获取筛选后的特征名
selected_features_corr = X_train.columns[selector.get_support()].tolist()
print(f"皮尔逊相关系数筛选后保留的特征数量: {len(selected_features_corr)}")
print(f"保留的特征: {selected_features_corr}")
# 训练随机森林模型
rf_model_corr = RandomForestClassifier(random_state=42)
rf_model_corr.fit(X_train_corr, y_train)
rf_pred_corr = rf_model_corr.predict(X_test_corr)
end_time = time.time()
print("随机森林分类器的准确率:", accuracy_score(y_test, y_pred))
print("\n分类报告:\n", classification_report(y_test, y_pred))
print(f"训练与预测耗时: {end_time - start_time:.4f} 秒")
print("皮尔逊相关系数筛选后随机森林在测试集上的混淆矩阵:")
print(confusion_matrix(y_test, rf_pred_corr))
lasso筛选(基于L1正则化)
Lasso回归(Least Absolute Shrinkage and Selection Operator)是一种结合特征选择和模型训练的方法。它的核心逻辑是:在进行线性回归的同时,通过引入L1正则化项(即惩罚项),强制将一些不重要特征的回归系数压缩到0,从而实现特征筛选。换句话说,Lasso会自动“挑选”对预测目标有贡献的特征(系数不为0),而剔除无关或冗余的特征(系数为0)。这种方法特别适合处理高维数据,可以减少特征数量,提高模型的解释性和计算效率。
print("--- Lasso筛选 (L1正则化) ---")
from sklearn.linear_model import Lasso
from sklearn.feature_selection import SelectFromModel
import time
start_time = time.time()
# 使用Lasso回归进行特征筛选
lasso = Lasso(alpha=0.01, random_state=42) # alpha值可调整
selector = SelectFromModel(lasso)
selector.fit(X_train, y_train)
X_train_lasso = selector.transform(X_train)
X_test_lasso = selector.transform(X_test)
# 获取筛选后的特征名
selected_features_lasso = X_train.columns[selector.get_support()].tolist()
print(f"Lasso筛选后保留的特征数量: {len(selected_features_lasso)}")
print(f"保留的特征: {selected_features_lasso}")
# 训练随机森林模型
rf_model_lasso = RandomForestClassifier(random_state=42)
rf_model_lasso.fit(X_train_lasso, y_train)
rf_pred_lasso = rf_model_lasso.predict(X_test_lasso)
end_time = time.time()
print(f"训练与预测耗时: {end_time - start_time:.4f} 秒")
print("随机森林分类器的准确率:", accuracy_score(y_test, y_pred))
print("\n分类报告:\n", classification_report(y_test, y_pred))
print("Lasso筛选后随机森林在测试集上的混淆矩阵:")
print(confusion_matrix(y_test, rf_pred_lasso))
1万+

被折叠的 条评论
为什么被折叠?



