特征工程feature_selection
特征提取,特征创造,特征选择
- 特征选择
-过滤法,嵌入法,包装法,和降维算法。
import pandas as pd
import numpy as np
from sklearn.ensemble import RandomForestClassifier as rfc
from sklearn.model_selection import cross_val_score
data=pd.read_csv("digit recognizor.csv")
data.head()
label | pixel0 | pixel1 | pixel2 | pixel3 | pixel4 | pixel5 | pixel6 | pixel7 | pixel8 | ... | pixel774 | pixel775 | pixel776 | pixel777 | pixel778 | pixel779 | pixel780 | pixel781 | pixel782 | pixel783 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
3 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
5 rows × 785 columns
y=data.label
x=data.iloc[:,1:]
x.shape
(42000, 784)
3.1 filter 过滤法
-过滤方法通常用作预处理步骤,特征选择完全独立于任何机器学习算法。它是根据各种统计检验中的分数以及相关
性的各项指标来选择特征。
3.1.1 方差过滤, VarianceThreshold
- 比如一个特征本身的方差很小,就表示样本在这个特征上基本没有差
异,可能特征中的大多数值都一样,甚至整个特征的取值都相同,那这个特征对于样本区分没有什么作用。所以无
论接下来的特征工程要做什么,都要优先消除方差为0的特征。VarianceThreshold有重要参数threshold,表示方
差的阈值,表示舍弃所有方差小于threshold的特征,不填默认为0,即删除所有的记录都相同的特征
from sklearn.feature_selection import VarianceThreshold
d:\python3.7\lib\site-packages\sklearn\utils\deprecation.py:144: FutureWarning: The sklearn.feature_selection.variance_threshold module is deprecated in version 0.22 and will be removed in version 0.24. The corresponding classes / functions should instead be imported from sklearn.feature_selection. Anything that cannot be imported from sklearn.feature_selection is now part of the private API.
warnings.warn(message, FutureWarning)
selector=VarianceThreshold()
x_var0=selector.fit_transform(x)
x_var0.shape
(42000, 708)
x_fsvar=VarianceThreshold(np.median(x.var().values)).fit_transform(x)
np.median(x.var().values)
1352.2867031801309
x_fsvar.shape
import time
a=time.time()
reshult1=cross_val_score(rfc(n_estimators=10,random_state=23),x,y,cv=10).mean()
b=time.time()
print(b-a)
24.49618887901306
reshult1
0.9403095238095238
a
reshult2=cross_val_score(rfc(n_estimators=10,random_state=23),x_fsvar,y,cv=10).mean()
b
print(b-a)
reshult2
0.9412142857142858
3.2相关性过滤
- 在sklearn当中,我们有三种常用的方法来评判特征与标签之间的相关性:卡方,F检验,互信息
卡方过滤
- 卡方过滤是专门针对离散型标签(即分类问题)的相关性过滤。卡方检验类feature_selection.chi2计算每个非负
特征和标签之间的卡方统计量,并依照卡方统计量由高到低为特征排名。再结合feature_selection.SelectKBest
这个可以输入”评分标准“来选出前K个分数最高的特征的类,我们可以借此除去最可能独立于标签,与我们分类目
的无关的特征。
另外,如果卡方检验检测到某个特征中所有的值都相同,会提示我们使用方差先进行方差过滤。并且,刚才我们已
经验证过,当我们使用方差过滤筛选掉一半的特征后,模型的表现时提升的。因此在这里,我们使用threshold=中
位数时完成的方差过滤的数据来做卡方检验(如果方差过滤后模型的表现反而降低了,那我们就不会使用方差过滤
后的数据,而是使用原数据):
from sklearn.feature_selection import SelectKBest,chi2
x_fschi=SelectKBest(chi2,k=300).fit_transform(x_fsvar,y)
x_fschi.shape
(42000, 300)
cross_val_score(rfc(n_estimators=10,random_state=23),x_fschi,y,cv=10).mean()
0.9359523809523809
- 可以看出,模型的效果降低了,这说明我们在设定k=300的时候删除了与模型相关且有效的特征,我们的K值设置
得太小,要么我们需要调整K值,要么我们必须放弃相关性过滤。当然,如果模型的表现提升,则说明我们的相关
性过滤是有效的,是过滤掉了模型的噪音的,这时候我们就保留相关性过滤的结果
### 3.2.1 选取超参数k
import matplotlib.pyplot as plt
score=[]
for i in range(350,200,-10):
x_fschi=SelectKBest(chi2,k=i).fit_transform(x_fsvar,y)
once = cross_val_score(rfc(n_estimators=10,random_state=0),x_fschi,y,cv=5).mean()
score.append(once)
-
通过这条曲线,我们可以观察到,随着K值的不断增加,模型的表现不断上升,这说明,K越大越好,数据中所有的
特征都是与标签相关的。但是运行这条曲线的时间同样也是非常地长,接下来我们就来介绍一种更好的选择k的方
法:看p值选择k。 -
卡方检验的本质是推测两组数据之间的差异,其检验的原假设是”两组数据是相互独立的”。卡方检验返回卡方值和
P值两个统计量,其中卡方值很难界定有效的范围,而p值,我们一般使用0.01或0.05作为显著性水平,即p值判断
的边界,具体我们可以这样来看从特征工程的角度,我们希望选取卡方值很大,p值小于0.05的特征,即和标签是相关联的特征。而调用
SelectKBest之前,我们可以直接从chi2实例化后的模型中获得各个特征所对应的卡方值和P值
score
[0.9386428571428571,
0.9380714285714287,
0.9384047619047617,
0.9343809523809524,
0.9351428571428573,
0.9344761904761905,
0.933642857142857,
0.9325714285714286,
0.9305,
0.9288095238095238,
0.9287142857142857,
0.9245238095238095,
0.9235714285714286,
0.9207142857142857,
0.9193571428571428]
plt.plot(range(350,200,-10),score)
[<matplotlib.lines.Line2D at 0x1f13d4d55c8>]
- 通过这条曲线,我们可以观察到,随着K值的不断增加,模型的表现不断上升,这说明,K越大越好,数据中所有的
特征都是与标签相关的。但是运行这条曲线的时间同样也是非常地长,接下来我们就来介绍一种更好的选择k的方
法:看p值选择k。 - 卡方检验的本质是推测两组数据之间的差异,其检验的原假设是”两组数据是相互独立的”。卡方检验返回卡方值和
P值两个统计量,其中卡方值很难界定有效的范围,而p值,我们一般使用0.01或0.05作为显著性水平,即p值判断
的边界,具体我们可以这样来看
-从特征工程的角度,我们希望选取卡方值很大,p值小于0.05的特征,即和标签是相关联的特征。而调用
SelectKBest之前,我们可以直接从chi2实例化后的模型中获得各个特征所对应的卡方值和P值。
chivalue,pavalue_chi=chi2(x_fschi,y)
chivalue.shape
(210,)
pavalue_chi
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0.])
k=chivalue.shape[0]-(pavalue_chi>0.05).sum()
k
210
X_fschi = SelectKBest(chi2, k=210).fit_transform(x_fsvar, y)
cross_val_score(rfc(n_estimators=10,random_state=0),X_fschi,y,cv=5).mean()
0.9193571428571428
- 可以观察到,所有特征的p值都是0,这说明对于digit recognizor这个数据集来说,方差验证已经把所有和标签无
关的特征都剔除了,或者这个数据集本身就不含与标签无关的特征。在这种情况下,舍弃任何一个特征,都会舍弃
对模型有用的信息,而使模型表现下降,因此在我们对计算速度感到满意时,我们不需要使用相关性过滤来过滤我
们的数据。
3.2 F检验