零、为什么要做特征选择

  • 如前文所述,特征的选择可以提高模型的上限。
  • 并且,可以剔除掉不需要用的特征,以提高训练速度。

一、特征选择

Filter:过滤法

  • 过滤法,按照发散性或者相关性对各个特征进行评分,设定阈值或者待选择阈值的个数,选择特征。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
'''
方差选择法:
计算各个特征的方差,根据阈值,选择方差大于阈值的特征,这样的数据包含更多的信息。使用feature_selection库的VarianceThreshold类来选择特征。
'''
from sklearn.feature_selection import VarianceThreshold

# 方差选择法,返回值是特征筛选后的结果
# 实例化这个工具
xs = VarianceThreshold(threshold = 0.5).fit_transform(x) # 但是阈值设置多少合适呢?见后。
xs

np.var(x,axis = 0) # 计算每一列的方差,验证

'''
卡方检验:
经典卡方检验是检验定性自变量对定性因变量的相关性。假设自变量有N种取值,因变量有M种,考虑自变量等于i且因变量等于j的样本频数的观察值与期望的差距。χ² = ∑((A - E)² / E)。
'''
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2 # 指标

# 选择K个最好的特征,返回的就是选择后的特征

x_non_negative = x - np.min(x) # 非负化,不一定需要

xs = SelectKBest(chi2,k = 2).fit_transform(x,y) # 使用时输入数据必须非负
xs

Wrapper:包装法

  • 根据目标函数(通常是预测效果评分),每次选择若干特征,或者排除若干特征。
1
2
3
4
5
6
7
8
9
10
'''
递归特征消除法:
用一个基模型来进行多轮训练,每轮训练后,消除若干权值系数的特征,再基于新的特征集进行下一轮训练
'''
from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression # 基模型

# 递归消除法,返回值也是选择后的数据
xs = RFE(estimator = LogisticRegression(),n_features_to_select = 2).fit_transform(x,y) # 基模型,保留特征数量
xs

Embedded:嵌入法

  • 先使用某些机器学习的算法和模型进行训练,得到各个特征的权值系数,根据系数从大到小选择特征。类似于Filter方法,但是是通过训练来确定特征的优劣。
  • 嵌入法只有部分模型,比如l1,l2正则化,树模型可以做,包装法什么模型都可以做。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
'''
基于惩罚项的特征选择法:
使用带惩罚项的基模型,也就是l1l2逻辑回归,除了筛选出特征外,同时也进行了降维,筛掉了不需要的维度。
'''
from sklearn.feature_selection import SelectFromModel
from sklearn.linear_model import LogisticRegression

# 使用带L2惩罚项的逻辑回归作为基模型的特征选择
xs = SelectFromModel(LogisticRegression(penalty = 'l2',C = 0.1)).fit_transform(x,y) #l1会报错,需要修改计算方式
xs

# 直接使用我们的带惩罚性的逻辑回归,看看每个特征的权重顺序
clf = LogisticRegression(penalty = 'l2',C = 0.1)
clf.fit(x,y) # 训练模型

# 查看下我们的模型的特征重要性评估
importances = clf.coef_
abs(importances[0]) # 绝对值越大,特征权重越重要

'''
基于树模型的特征选择法:
'''
from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import RandomForestClassifier

# 使用带L2惩罚性的随机森林作为及础模型的特征选择
xs = SelectFromModel(RandomForestClassifier()).fit_transform(x,y)
xs

# 训练随机森林看结果
rfr = RandomForestClassifier()
rfr.fit(x,y)

# 查看下我们的模型的特征重要性评估
importances = rfr.feature_importances_
importances # 加起来会等于1,真正的权重