通常从两个方面考虑来选择特征:
- 特征是否发散:如果说一个特征不发散(比如方差接近于0),样本在这个特征上基本没有差异,那么这个特征对于样本的区分并没有什么作用
- 特征与目标的相关性
根据特征选择的形式,可以将特征选择方法分为3种:
1)Filter过滤法:先进行特征选择,再训练学习器,特征选择过程与后续学习器无关。
- 方差选择法:先计算各特征方差,设置方差阈值筛选
- 相关系数法:先计算各特征目标值的相关系数以及相关系数的P值(pearson系数)
sklearn的feature_selection库提供了结合相关系数来选择特征的工具(SelectKBest):
from sklearn.feature_selection import SelectKBest
from scipy.stats import pearsonr
#选择K个最好的特征,返回选择特征后的数据
#第一个参数为计算评估特征是否好的函数,该函数输入特征矩阵和目标向量,输出二元组(评分,P值)的数组,数组第i项为第i个特征的评分和P值。在此定义为计算相关系数
#参数k为选择的特征个数
SelectKBest(lambda X, Y: array(map(lambda x:pearsonr(x, Y), X.T)).T, k=2).fit_transform(iris.data, iris.target)
- 卡方检验法:经典的卡方检验是检验定性自变量对定性因变量的相关性,考虑样本频数的观察值与期望的差距,构建统计量:
用sklearn的feature_selection库的SelectKBest类结合卡方检验来选择特征的代码如下:
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
#选择K个最好的特征,返回选择特征后的数据
SelectKBest(chi2, k=2).fit_transform(iris.data, iris.target)
- 互信息法:经典的互信息也是评价定性自变量对定性因变量的相关性的,互信息的计算公式如下:
同样,用sklearn的feature_selection库的SelectKBest类结合最大信息系数法来选择特征的代码如下:
#由于MINE的设计不是函数式的,定义mic方法将其为函数式的,返回一个二元组,二元组的第2项设置成固定的P值0.5
def mic(x, y):
m = MINE()
m.compute_score(x, y)
return (m.mic(), 0.5)
#选择K个最好的特征,返回特征选择后的数据
SelectKBest(lambda X, Y: array(map(lambda x:mic(x, Y), X.T)).T, k=2).fit_transform(iris.data, iris.target)
2)Wrapper包装法:包裹式特征选择直接把最终将要使用的学习器性能作为特征子集的评价准则。也就是给学习器选择最有利于其性能、量身定做的特征子集。
- 优点:由于直接针对特定学习器进行优化,从最终学习器性能来看,效果比过滤式特征选择更好
- 缺点:需要多次训练学习器,因为计算开销通常比过滤式特征选择要大得多
3)Embedded嵌入法:
- 基于惩罚项的特征选择法
- 基于树模型的特征选择法