特征选择的定义:
来自维基百科定义: 特征选择(feature selection)也被称为变量选择、属性选择或属性子集选择。它是为了构建模型而选择相关特征子集的过程。 特征选择是指从原始特征中挑选出一组最有代表性、分类性能好的特征。 没有确定的步骤,更多是工程上的经验和权衡,一般需要耗费较多的时间和精力,掌握常用的经验和权衡方法,可以极大提高挖掘建模的效率和效果。 给定不同的挖掘任务,需要的特征组合可能不同。
为什么要进行特征选择:
现实中大数据挖掘任务,往往特征属性过多,而一个普遍存在的事实是,大数据集带来的关键信息只聚集在部分或少数特征上,因此需要: 从中选择出重要的特征使得后续的建模过程只在一部分的特征上构建,减少维数灾难出现的可能。 去除不相关的特征,留下关键因素,降低学习任务难度,更容易挖掘数据本身带有的规律;同时在特征选择的过程中,会对数据特征的理解更加充分。
特征选择的原则:
当数据预处理完成后,需要选择有意义的特征进行模型训练。通常来说,从三个方面考虑:
特征是否发散:如果一个特征不发散,例如方差接近于0,也就是说样本在这个特征上基本上没有差异,这个特征对于样本的区分作用不明显,区分度不高。
特征之间的相关性:特征与特征之间的线性相关性,去除相关性比较高的特征。
特征与目标的相关性:与目标相关性高的特征,应当优先选择。
常见的特征选择的方法:
特征选择方法有很多,主要包含特征减少和特征扩增。
特征减少
单变量特征选择方法
Filter(过滤法)
基于模型的特征选择方法
Wrapper(包装法) Embedded(嵌入法)
其他方法:
如交叉验证配合Embeded方法
特征扩增
在原有基础上构造新的特征
常见方法的介绍:
Filter:
过滤法(飞刀法),这是一种启发式方法,基本思想是:制定一个准则,用来衡量每个特征对目标属性的重要性,以此来对所有特征进行排序,或者优先操作,特征选择的过程和后续学习器无关(其他两个方法均与学习器有关)。
过滤法是一类单变量特征选择的方法,独立地衡量每个特征与响应变量之间的关系,根据某一准 则来判断哪些指标重要,
这种方法比较简单,易于运行,易于理解,通常对于理解数据有较好的结果,是特征选择最初会使用的方法,但对特征优化、提高泛化能力来说效果不能保证
Wrapper:包装法,根据目标函数(通常是预测效果评分),每次选择若干特征,或者排除若干特征。
Embedded:嵌入法,先使用某些机器学习的算法和模型进行训练,得到各个特征的权值系数,根据系数从大到小选择特征。类似于Filter方法,但是是通过训练来确定特征的优劣。
Filter方法:
一.方差选择法 :
方差选择法是一种最简单的选择技术,基本思想是:方差越大的特征,对于分析目标影响越大,就越有用。如果方差较小,比如小于1,那么这个特征可能对算法作用比较小。最极端的,如果某个特征方差为0,即所有的样本该特征的取值都是一样的,那么对模型训练没有任何作用,可以直接舍弃。
只适用于连续变量。
在实际应用中指定一个方差的阈值,当方差小于这个阈值的特征会被去除。
使用工具:sklearn中的VarianceThreshold类。
from sklearn.datasets import load_iris
iris = load_iris()
df = pd.DataFrame(iris['data'],columns=iris['feature_names'])
from sklearn.feature_selection import VarianceThreshold
vt = VarianceThreshold(threshold=0.5) # 设置阈值方差为0.5,小于0.5的全部删除
arr = vt.fit_transform(df) # 返回的是一个二维的数组
print(arr)
# 输出每列的方差
print(vt.variances_)
# 最后我们将处理后的数据写回原数据
new_df = pd.DataFrame(arr,columns=df.columns[vt.get_support()])
print(new_df)
二.相关系数法:
相关系数法(皮尔逊相关系数)适用于特征类型均为数值特征的情况。 也称为Pearson相关系数,是一种最简单的,能帮助理解特征和响应变量之间关系的方法,该方法衡量的是变量之间的线性相关性,结果的取值区间为[-1,1],-1表示完全的负相关,+1表示完全的正相关,0表示没有线性相关。
该方法的明显缺陷是只对线性关系敏感,如果特征与响应变量的关系是非线性的,即便两个变量具有一 一对应的关系,相关系数也可能会接近0。建议最好把数据可视化出来,以免得出错误的结论。
Scipy的pearsonr方法能够同时计算相关系数r值和p-value(简称p值), p值越小,表示相关系数越显著。
需要注意:如果仅仅根据相关系数这个值来判断的话,有时候会具有很强的误导性。
p值粗略地表示不相关系统产生具有Pearson相关性的数据集的概率至少与从这些数据集计算的数据集一样极端。
p值并不完全可靠,但对于大于500左右的数据集可能是合理的。
Scipy的pearsonr详细说明可见英文官网 https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.pearsonr.html
from sklearn.datasets import load_iris
iris = load_iris()
X = iris['data']
y = iris['target']
from scipy import stats
X_pear = []
for i in range(X.shape[1]):
X_pear.append(stats.pearsonr(X[:,i],y))
print(X_pear)
result = [x[0] for x in X_pear]
print(result) # 可以通过这串代码取出所有的相关系数
[PearsonRResult(statistic=0.7825612318100813, pvalue=2.890478352614223e-32), PearsonRResult(statistic=-0.4266575607811245, pvalue=5.201563255177237e-08), PearsonRResult(statistic=0.9490346990083887, pvalue=4.201873152962088e-76), PearsonRResult(statistic=0.9565473328764029, pvalue=4.155311015318125e-81)]
# 运行结果第一个代表相关系数,第二个代表p值
这种方法相对简单,不经常用,常用计算相关系数矩阵,然后通过绘制热力图来进行选择
from sklearn.datasets import load_iris
iris = load_iris()
df = pd.DataFrame(iris['data'],columns=iris['feature_names'])
df['target'] = iris['target']
corr = df.corr() # 方式最常用的有两种一种是pearson(皮尔逊)spearman(斯皮尔曼)
import seaborn as sns
import matplotlib.pyplot as plt
sns.heatmap(corr,annot=True,fmt='.2g')
# annot 设置是否显示相关系数 fmt 保留几位小数 cmap用于指定绘图时使用的颜色映射
plt.show()
三.卡方检验:
卡方检验,也叫作χ^2(不是英语X哈)检验,它可以检验某个特征分布和输出值分布之间的相关性,通常比粗暴的方差选择法好用。(通常用于分类型数据,特征列是连续数据也可以用,他会之间进行卡方分箱,但是这个的前提是标签列必须是分类型数据)
χ^2值描述了自变量与因变量之间的相关程度:χ^2值越大,相关程度也越大。在特征选择时,保留相关程度大的特征,另外还可以利用χ^2检验做异常检测等。
可以总结:卡方值描述了自变量与因变量之间的相关程度:卡方值越大,相关程度也越大,所以很自然的可以利用卡方值来做特征选择,保留相关程度大的变量。
from sklearn.datasets import load_wine # 红酒的数据
from sklearn.datasets import load_boston # 波士顿房价预测数据
wine = load_wine()
boston = load_boston() # 标签列必须是分类数据,波士顿的标签列不是分类型数据,大家可以代进去,会报错的
from sklearn.feature_selection import SelectKBest,chi2
sk = SelectKBest(score_func=chi2,k=5) # 设置评分函数为卡方检验(chi2),并选择最重要的5个特征。
arr = sk.fit_transform(wine['data'],wine['target'])
print(arr)
四.互信息法:
互信息法的理解与使用 从信息熵的角度分析特征和输出值之间的关系评分。互信息值越大,说明该特征和输出值之间的相关性越大,越需要保留。
互信息方法使用缺陷:
它不属于度量方式,也没有办法归一化,在不同数据集上的结果无法做比较。
对于连续变量通常需要先离散化,而互信息的结果对离散化的方式敏感。
sklearn使用mutual_info_classif(分类)和mutual_info_regression (回归)来计算各个输入特征和输出值之间的互信息。
from sklearn.datasets import load_wine
from sklearn.datasets import load_boston
wine = load_wine()
boston = load_boston()
from sklearn.feature_selection import mutual_info_classif,mutual_info_regression
# regression 回归问题 标签列 连续
# classif 分类问题 标签列 分类
mi = mutual_info_classif(wine['data'],wine['target'])
print(mi)
lst = list(zip(wine['feature_names'],mi))
lst.sort(key=lambda x:x[1],reverse=True)
print(list(map(lambda x:x[0],lst[:5:])))
Filter小结:
Filter方法总结起来就是利用不同的打分规则,如卡方检验、相关系数、互信息等规则对每个特征进行打分,即相当于给每个特征赋予一个权重,按照权重排序,对不达标的特征进行过滤
对于理解数据、数据结构、数据分布而言,单变量特征选择是非常好的选择。该方法是通过对特征进行排序来优化模型,但缺点是它不能发现冗余:
若特征之间具有强关联,且非线性时,Filter方法不能避免选择的最优特征组合冗余。
Filter方法中的具体技术有许多改进的版本或变种。
按不同的特征属性类型,可将上述方法做如下划分:
评价自变量的信息量或离散情况:方差选择法;
评价自变量与自变量(或应变量)的相关性:相关系数法;
评价自变量与应变量(或自变量)的相关性:卡方检验方法、互信息法。
上述方法均可以通过python库sklearn中的feature_selection子模块来进行调用