选择特征总是让人头大,究竟应该怎么做呢?
01
为什么要进行特征选择
- 我们在现实任务中经常会遇到维数灾难的问题,这是由于属性过多而造成的,若能从中选择出重要的特征,使得后续学习过程仅需在一部分特征上构建模型,则维数灾难问题会大为减轻。
- 去除不相关特征往往会降低学习任务的难度,我们把复杂的问题变得简单化,往往也能使得效率变高,结果变的更准确。
02
过滤式(Filter)
过滤式是过滤式的方法先对数据集进行特征选择,然后再训练学习器,特征选择过程与后续学习器无关,也就是说我们先用特征选择过程对初始特征进行“过滤”,再用过滤后的特征来训练模型。
方差选择法
设置一个阈值,然后计算各个特征的方差,根据阈值,选择方差大于阈值的特征。
该方法的代码使用方式如下:
代码语言:javascript复制from sklearn.feature_selection import VarianceThreshold
# 方差选择法,返回值为特征选择后的数据
# 参数threshold为方差的阈值
VarianceThreshold(threshold=3).fit_transform(iris.data)
相关系数法
计算各个特征x对目标值y的Pearson相关系数,Pearson相关系数的计算方式如下:
Pearson 反应的是两个变量间的线性相关性,它的取值区间为[-1,1],其中1表示完全正相关,0表示完全没有线性关系,-1表示完全的负相关。相关系数越接近于0,相关性越弱,通常在0.8-1.0之间极强相关,0.6-0.8强相关,0.4-0.6中等强度相关,0.2-0.4弱相关,0-0.2极弱相关或者不相关。
该方法的代码使用方式如下:
代码语言:javascript复制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)
卡方检验法
对于卡方检验,我们需要检验的是定性自变量对定性因变量的相关性,假设自变量有N种取值,因变量有M种取值,考虑自变量等于i且因变量等于j的样本频数的观察值与期望的差距,构建如下的统计量(这里的A表示观察值,E表示理论值):
我们可以看出,这个统计量的含义简而言之就是自变量对因变量的相关性。
该方法的代码使用方式如下:
代码语言:javascript复制from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
# 选择K个最好的特征,返回选择特征后的数据
SelectKBest(chi2, k=2).fit_transform(iris.data, iris.target)
互信息法
互信息可以看成是一个随机变量中包含的关于另一个随机变量的信息量,或者说是一个随机变量由于已知另一个随机变量而减少的不肯定性,互信息是联合分布与边缘分布的相对熵,互信息计算公式如下: 该方法的代码使用方式如下:
代码语言:javascript复制from sklearn.feature_selection import SelectKBest
from minepy import MINE
# 由于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)
03
包裹式(Wrapper)
与过滤式特征选择不考虑后续学习器不同,包裹式特征选择直接把最终将要使用的学习器性能作为特征子集的评价准则。因此从最终学习器性能来看,包裹式特征选择比过滤式特征选择更好,但是其计算开销也要比过滤式特征选择大得多。
递归特征消除法
递归特征消除法使用一个基模型来进行多轮训练,每轮训练后,移除若干权值系数的特征,再基于新的特征集进行下一轮训练。
该方法的代码使用方式如下:
代码语言:javascript复制from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression
# 递归特征消除法,返回特征选择后的数据
# 参数estimator为基模型
# 参数n_features_to_select为选择的特征个数
RFE(estimator=LogisticRegression(), n_features_to_select=2).fit_transform(iris.data, iris.target)
04
嵌入式(Embedding)
在过滤式和包裹式特征选择方法中,特征选择过程与学习器训练过程有明显的分别;与此不同的是,嵌入式特征选择是将特征选择过程与学习器训练过程融为一体,两者在同一个优化过程中完成,即在学习器训练过程中自动的进行了特征选择。
基于惩罚项的方法
我们使用带有惩罚项的基模型(例如LR、SVM),不仅可以筛选出特征,同时也进行了降维,下面的例子尝试使用LR L1正则来进行特征选择:
代码语言:javascript复制from sklearn.feature_selection import SelectFromModel
from sklearn.linear_model import LogisticRegression
# 带L1惩罚项的逻辑回归作为基模型的特征选择
SelectFromModel(LogisticRegression(penalty="l1", C=0.1)).fit_transform(iris.data, iris.target)
基于树模型的方法
同样我们也可以使用树模型进行特征的选择,树模型中的GBDT就是一个很好的例子,代码的实现方式如下:
代码语言:javascript复制from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import GradientBoostingClassifier
# GBDT作为基模型的特征选择
SelectFromModel(GradientBoostingClassifier()).fit_transform(iris.data, iris.target)