###########################################################################################
当数据预处理完成后,我们需要选择有意义的特征输入机器学习的算法和模型进行训练。通常来说,从两个方面考虑来选择特征:
特征是否发散:如果一个特征不发散,例如方差接近于0,也就是说样本在这个特征上基本上没有差异,这个特征对于样本的区分并没有什么用。
特征与目标的相关性:这点比较显见,与目标相关性高的特征,应当优选选择。除方差法外,本文介绍的其他方法均从相关性考虑。
根据特征选择的形式又可以将特征选择方法分为3种:
Filter:过滤法,按照发散性或者相关性对各个特征进行评分,设定阈值或者待选择阈值的个数,选择特征。
Wrapper:包装法,根据目标函数(通常是预测效果评分),每次选择若干特征,或者排除若干特征。
Embedded:嵌入法,先使用某些机器学习的算法和模型进行训练,得到各个特征的权值系数,根据系数从大到小选择特征。类似于Filter方法,但是是通过训练来确定特征的优劣。
我们使用sklearn中的feature_selection库来进行特征选#########################################################################################
模型原型
class sklearn.feature_selection.VarianceThreshold(threshold=0.0)
参数
属性
方法
例子:
from sklearn.feature_selection import VarianceThreshold
X=[
[100,1,2,3],
[100,4,5,6],
[100,7,8,9],
[101,11,12,13]
]
selector=VarianceThreshold(1)
selector.fit(X)
print('Variances is %s'%selector.variances_)
print('After transform is \n%s'%selector.transform(X))
print('The surport is %s'%selector.get_support(True))#如果为True那么返回的是被选中的特征的下标
print('The surport is %s'%selector.get_support(False))#如果为FALSE那么返回的是布尔类型的列表,反应是否选中这列特征
print('After reverse transform is \n%s'%selector.inverse_transform(selector.transform(X)))
Variances is [ 0.1875 13.6875 13.6875 13.6875]
After transform is
[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[11 12 13]]
The surport is [1 2 3]
The surport is [False True True True]
After reverse transform is
[[ 0 1 2 3]
[ 0 4 5 6]
[ 0 7 8 9]
[ 0 11 12 13]]
单变量特征选择能够对每一个特征进行测试,衡量该特征和响应变量之间的关系,根据得分扔掉不好的特征。对于回归和分类问题可以采用卡方检验等方式对特征进行测试。
方法简单,易于运行,易于理解,通常对于理解数据有较好的效果(但对特征优化、提高泛化能力来说不一定有效);这种方法有许多改进的版本、变种。
卡方检验适用于:分类问题(y离散)
经典的卡方检验(原理及应用)是检验定性自变量对定性因变量的相关性。假设自变量有N种取值,因变量有M种取值,考虑自变量等于i且因变量等于j的样本频数的观察值与期望的差距,构建统计量,其中A为实际数,E为理论值:
模型原型
class sklearn.feature_selection.SelectKBest(score_func=,k=10)
参数
属性
方法
模型原型
class sklearn.feature_selection.SelectPercentile(score_func=,percentile=10)
参数
属性
方法
例子:
from sklearn.feature_selection import SelectKBest,f_classif
X=[
[1,2,3,4,5],
[5,4,3,2,1],
[3,3,3,3,3],
[1,1,1,1,1]
]
y=[0,1,0,1]
print('before transform:\n',X)
selector=SelectKBest(score_func=f_classif,k=3)
selector.fit(X,y)
print('scores_:\n',selector.scores_)
print('pvalues_:',selector.pvalues_)
print('selected index:',selector.get_support(True))
print('after transform:\n',selector.transform(X))
before transform:
[[1, 2, 3, 4, 5], [5, 4, 3, 2, 1], [3, 3, 3, 3, 3], [1, 1, 1, 1, 1]]
scores_:
[0.2 0. 1. 8. 9. ]
pvalues_: [0.69848865 1. 0.42264974 0.10557281 0.09546597]
selected index: [2 3 4]
after transform:
[[3 4 5]
[3 2 1]
[3 3 3]
[1 1 1]]
适用于:回归问题(y连续)
皮尔森相关系数是一种最简单的,能帮助理解特征和响应变量之间关系的方法,该方法衡量的是变量之间的线性相关性,结果的取值区间为[-1,1],-1表示完全的负相关,+1表示完全的正相关,0表示没有线性相关。
Pearson Correlation速度快、易于计算,经常在拿到数据(经过清洗和特征提取之后的)之后第一时间就执行。Scipy的 pearsonr 方法能够同时计算 相关系数 和p-value.
例子:
import numpy as np
from scipy.stats import pearsonr
np.random.seed(0)
size = 300
x = np.random.normal(0, 1, size)
# pearsonr(x, y)的输入为特征矩阵和目标向量
# np.random.normal(0, 1, 100) 创建100个均值为0,方差为1的高斯随机数
print("Lower noise", pearsonr(x, x + np.random.normal(0, 1, size)))
print("Higher noise", pearsonr(x, x + np.random.normal(0, 10, size)))#pearsonr会返回两个值,第一个值是相关性的值,第二个是p-value的值
#相关系越大,p-value的值也就越小。
Pearson相关系数的一个明显缺陷是只对线性关系敏感。如果关系是非线性的,即便两个变量具有一一对应的关系,Pearson相关性也可能会接近0。
例如:
import numpy as np
from scipy.stats import pearsonr
x = np.random.uniform(-1, 1, 100000)
print (pearsonr(x, x**2)[0])
x和x的方不是线性的关系,虽然有相关性,但是他们的相关的=系数很低。
经典的互信息也是评价定性自变量对定性因变量的相关性的,互信息计算公式如下:
为了处理定量数据,最大信息系数法被提出,使用feature_selection
库的SelectKBest
类结合最大信息系数法来选择特征的代码如下:
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)