特征筛选的重要性:
在机器学习和数据科学领域,特征筛选是优化模型性能和提高计算效率的关键步骤。当数据集包含大量特征时,不仅增加了计算成本,还可能引入噪声和冗余信息,影响模型的泛化能力。因此,通过特征筛选,让我们能够从原始特征集中挑选出最具信息量的特征,提高模型的预测准确性和可解释性
特征筛选的方法:
特征筛选方法可以分为三大类:过滤法(Filter)、包装法(Wrapper)、嵌入法(Embedded)。接下来,我们将使用的方差分析属于过滤法,是一种基于统计学原理的特征选择方法
方差分析(ANOVA)的原理:
方差分析是一种用于分析不同组之间是否存在显著性差异的统计方法。在特征选择中,我们使用ANOVA来衡量特征与目标变量之间的关联程度
F统计量 :ANOVA计算的F统计量衡量了特征对目标变量的影响程度。F统计量越大,表示特征与目标变量之间的关系越显著
P值 :P值表示观察到的统计量(如F统计量)的概率。在特征选择中,我们关注的是P值是否小于设定的显著性水平(通常为0.01或0.05)。小于显著性水平的特征被认为对目标变量有显著影响
多重假设校正(BH校正):
在进行大量的假设检验时,由于多次比较可能导致错误的显著性结果。BH校正是一种常用的多重假设校正方法,能够有效控制错误的发生率
排序P值: 将所有特征的P值按升序排列
计算校正后的显著性水平: 通过BH校正,我们根据排序后的P值和特征数量计算每个特征的校正显著性水平
选取显著特征: 选取校正后显著水平小于设定显著性水平的特征
SelectFdr的应用:
在Scikit-learn中,SelectFdr是一种方便的工具,它通过同时应用BH校正和过滤特征,快速选取显著的特征
设定显著性水平: 通过设定alpha参数,指定显著性水平
拟合模型: 使用SelectFdr拟合模型,自动进行BH校正和特征过滤
获取结果: 获取过滤后的特征集,用于训练模型
SelectKBest的应用:
SelectKBest是另一种常用的特征选择方法,它选择评分最高的K个特征,忽略其余
设定K值: 通过设定k参数,选择希望保留的特征数量
拟合模型: 使用SelectKBest拟合模型,选择得分最高的K个特征
获取结果: 获取选择后的特征集,用于训练模
代码实现:
from ucimlrepo import fetch_ucirepo
# fetch dataset
myocardial_infarction_complications = fetch_ucirepo(id=579)
# data (as pandas dataframes)
X = myocardial_infarction_complications.data.features
y = myocardial_infarction_complications.data.targets
# metadata
print(myocardial_infarction_complications.metadata)
# variable information
print(myocardial_infarction_complications.variables)
# 导入Scikit-learn中的特征选择模块
from sklearn.feature_selection import SelectFdr, f_classif, SelectKBest
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
# 导入Scikit-learn中的数据缺失值处理模块
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler
# 预处理,包括填充缺失值和标准化
np.random.seed(42)
y = y['LET_IS']
X = X
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y)
# 打印训练集和测试集的形状
print('X shape = {}'.format(X_train.shape) + '\ny shape = {}'.format(y_train.shape))
print('X shape = {}'.format(X_test.shape) + '\ny shape = {}'.format(y_test.shape))
# 缺失值填充
imp = SimpleImputer(strategy='median').fit(X_train)
X_train = imp.transform(X_train)
X_test = imp.transform(X_test)
# 数据标准化
scaler = StandardScaler().fit(X_train)
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)
# 使用ANOVA计算F统计量和P值
anova_res = f_classif(X_train, y_train)
pvalues = anova_res[1]
# 检查小于0.01显著水平的P值数量
alpha = 0.01
print("ANOVA F统计量(未进行多重假设校正)中的重要特征数量:", sum(anova_res[1] < alpha))
# 打印进行BH校正前认为显著的最大P值
pvalues_taken_before_BH = pvalues[pvalues < alpha]
print("BH校正前认为显著的最大P值是:{:.4f}".format(pvalues_taken_before_BH.max()))
# 实施BH校正
pvalues_sorted = np.sort(anova_res[1])
pvalues_taken_using_BH = pvalues_sorted[pvalues_sorted <= np.arange(1, X_train.shape[1] + 1) * alpha / X_train.shape[1]]
print("ANOVA F统计量(进行BH校正后)中的重要特征数量:", len(pvalues_taken_using_BH))
print("BH校正后认为显著的最大P值是:{:.4f}".format(pvalues_taken_using_BH.max()))
# 使用SelectFdr同时应用BH校正和过滤特征
filter_fdr = SelectFdr(alpha=0.01).fit(X_train, y_train)
print("前20个特征的P值:\n", filter_fdr.pvalues_[0:20])
X_train_filtered_BH = filter_fdr.transform(X_train)
print("ANOVA F统计量(进行BH校正后)中的重要特征数量:", X_train_filtered_BH.shape[1])
X_test_filtered_BH = filter_fdr.transform(X_test)
print("测试集的形状(特征数量应与训练集相匹配):", X_test_filtered_BH.shape)
# 使用SelectKBest
filter_KBest = SelectKBest(k=50).fit(X_train, y_train)
X_train_filtered_KBest = filter_KBest.transform(X_train)
print("ANOVA F统计量(选择50个最佳特征)中的重要特征数量:", X_train_filtered_KBest.shape[1])
X_test_filtered_KBest = filter_KBest.transform(X_test)
print("测试集的形状(特征数量应与训练集相匹配):", X_test_filtered_KBest.shape)
这段代码是一个完整的特征选择过程,使用了方差分析(ANOVA)进行特征选择,并结合了多重假设校正(BH校正)以及Scikit-learn中的SelectFdr和SelectKBest两种工具。以下是简单的阐述:
数据加载:
使用ucimlrepo库中的fetch_ucirepo函数加载了一个心脏梗死并发症的数据集
数据准备:
将数据集拆分为特征(X)和目标变量(y)
对y进行处理,选择目标变量的某一列('LET_IS')
数据预处理:
使用train_test_split将数据集划分为训练集和测试集
使用SimpleImputer填充缺失值,采用中位数作为填充策略
使用StandardScaler对数据进行标准化,确保特征具有相似的尺度
特征选择:
使用ANOVA计算F统计量和P值,度量特征与目标变量之间的关系
设定显著性水平alpha为0.01,检查P值小于alpha的特征数量
打印未进行多重假设校正的ANOVA F统计量中被认为显著的特征数量以及其最大P值
实施BH校正,获取校正后的显著特征数量和最大P值
使用SelectFdr工具:
使用SelectFdr同时应用BH校正和过滤特征,选择显著的特征
打印前20个特征的P值,获取经过BH校正后的训练集和测试集
使用SelectKBest工具:
使用SelectKBest选择ANOVA F统计量中得分最高的50个特征
获取经过选择后的训练集和测试集
代码展示了在处理心脏梗死并发症数据时,如何进行特征选择并应用统计学方法进行显著性检验,以提高模型的预测性能
import matplotlib.pyplot as plt
import seaborn as sns
# 使用ANOVA计算F统计量和P值
anova_res = f_classif(X_train, y_train)
pvalues = anova_res[1]
# 将ANOVA F统计量和P值可视化
plt.figure(figsize=(12, 6))
# 绘制ANOVA F统计量的柱状图
plt.subplot(1, 2, 1)
sns.barplot(x=np.arange(1, len(anova_res[0]) + 1), y=anova_res[0], color='blue')
plt.xticks(rotation=45) # 旋转刻度标签,以防止重叠
plt.title('ANOVA F Statistics for Features')
plt.xlabel('Feature Index')
plt.ylabel('ANOVA F Statistic')
# 设置x轴刻度显示一部分
x_ticks_selected = np.arange(1, len(anova_res[0]) + 1, 5) # 每隔5个特征显示一个
plt.xticks(x_ticks_selected, rotation=45)
# 绘制P值的柱状图
plt.subplot(1, 2, 2)
sns.barplot(x=np.arange(1, len(pvalues) + 1), y=-np.log10(pvalues), color='green')
plt.xticks(rotation=45) # 旋转刻度标签,以防止重叠
plt.title('Negative Log10 P-values for Features')
plt.xlabel('Feature Index')
plt.ylabel('-log10(P-value)')
# 设置x轴刻度显示一部分
x_ticks_selected = np.arange(1, len(pvalues) + 1, 5) # 每隔5个特征显示一个
plt.xticks(x_ticks_selected, rotation=45)
plt.tight_layout()
plt.show()
使用柱状图可视化统计量和P值。左侧图显示了各个特征的ANOVA F统计量,右侧图显示了特征的P值的负对数(-log10)。通过这样的可视化,可以直观地了解每个特征在样本类别之间的方差以及其显著性程度,有助于进行特征选择和理解特征的重要性
如果你对类似于这样的文章感兴趣。
欢迎关注、点赞、转发~