特征工程的第一步:理解业务
如果特征比较少且容易理解,我们可以自行判断特征的取舍,如前面的泰坦尼克号数据集。但是,在真正的数据应用领域,比如金融,医疗,电商,我们的数据不可能像泰坦尼克号数据的特征这样少,这样明显。那如果遇见极端情况,我们无法依赖对业务的理解来选择特征,该怎么办呢?我们有四种方法可以用来选择特征:过滤法,嵌入法,包装法,和降维算法
Filter过滤法
过滤方法通常用作预处理步骤,特征选择完全独立于任何机器学习算法。它是根据各种统计检验中的分数以及相关性的各项指标来选择特征。
- 方差过滤
- VarianceThreshold
比如一个特征本身的方差很小,就表示样本在这个特征上基本没有差异,可能特征中的大多数值都一样,甚至整个特征的取值都相同,那这个特征对于样本区分没有什么作用。
所以无论接下来的特征工程要做什么,都要优先消除方差为0的特征。VarianceThreshold有重要参数threshold,表示方差的阈值,表示舍弃所有方差小于threshold的特征,不填默认为0,即删除所有的记录都相同的特征。
首先导入原函数
import pandas as pd
data = pd.read_csv(r'F:\data\digit recognizor.csv')
原函数的shape为(42000, 784)
然后我们采用方差过滤
from sklearn.feature_selection import VarianceThreshold
selector = VarianceThreshold() #实例化,不填参数默认方差为0
X_var0 = selector.fit_transform(X) #获取删除不合格特征之后的新特征矩阵
# 等同于 X_var0 = selector.fit_transform(VarianceThreshold())
方差过滤后函数的shape为(42000, 708)
至此,方差为0的特征全都删除了。
如果你只想保留一半的特征值,那么可以这样做
import numpy as np
np.median(X.var().values) # 这一步是取中位数
X_fsvar = VarianceThreshold(np.median(X.var().values)).fit_transform(X)
此时的X_fsvar.shape为(42000, 392)
当然,如果你想取前50个,你可以先把values排个序,然后阈值定义为第50的那个方差就可以啦。
此外,当方差是二分类的时候,特征的取值就是伯努利随机变量,这些变量的方差可以计算为Var[X] = p(1-p),p为二分类特征中的一类在这个特征中所占的概率。
可以定义,二分类特征中某种分类占到了80%以上的时候删除特征。
X_bvar = VarianceThreshold(.8 * (1 - .8)).fit_transform(X)
- 方差过滤对模型的影响
我们这样做了以后,对模型效果会有怎样的影响呢?在这里,我为大家准备了KNN和随机森林分别在方差过滤前和方差过滤后运行的效果和运行时间的对比。
#KNN vs 随机森林在不同方差过滤效果下的对比
from sklearn.ensemble import RandomForestClassifier as RFC
from sklearn.neighbors import KNeighborsClassifier as KNN
from sklearn.model_selection import cross_val_score
import numpy as np
X = data.iloc[:,1:]
y = data.iloc[:,0]
X_fsvar = VarianceThreshold(np.median(X.var().values)).fit_transform(X)
#======【TIME WARNING:35mins +】======#
cross_val_score(KNN(),X,y,cv=5).mean()
#python中的魔法命令,可以直接使用%%timeit来计算运行这个cell中的代码所需的时间
#为了计算所需的时间,需要将这个cell中的代码运行很多次(通常是7次)后求平均值,因此运行%%timeit的时间会
远远超过cell中的代码单独运行的时间
#======【TIME WARNING:4 hours】======#
%%timeit
cross_val_score(KNN(),X,y,cv=5).mean()
#======【TIME WARNING:20 mins+】======#
cross_val_score(KNN(),X_fsvar,y,cv=5).mean()
#======【TIME WARNING:2 hours】=&