ccc-sklearn-3-特征工程

1.特征工程基本概念

  1. 将原始数据转换为更能代表预测模型的潜在问题的特征的过程。通过挑选最相关的特征,提取特征以及创造特征来实现。其中创造特征常以降维算法的方式实现。
  2. 面对的问题:特征之间有相关性,特征和标签无关,特征太多或太小,或无法表现出应有的数据现象或无法展示数据的真实面貌
  3. 特征工程的目的:降低计算成本, 提升模型上限

2.数据预处理 Preprocessing & Impute

数据无量纲化
将不同规格的数据转换到同一规格,或不同分布的数据转换到某个特定分布的需求,这种需求统称为将数据“无量纲化”。

梯度和矩阵为核心的算法中,逻辑回归,支持向量机,神经网络,无量纲化可以加快求解速度;而在距离类模型,譬如K近邻,K-Means聚类中,无量纲化可以帮我们提升模型精度,避免某一个取值范围特别大的特征对距离计算造成影响。(决策树和树的集成算法不需要无量纲化,决策树可以把任意数据都处理得很好。)

数据的无量纲化可以是线性的,也可以是非线性的。包括中心化(Zero-centered或者Mean-subtraction)处理和缩放处理(Scale)。中心化的本质是让所有记录减去一个固定值,即让数据样本数据平移到某个位置。缩放的本质是通过除以一个固定值,将数据固定在某个范围之中,取对数也算是一种缩放处理

preprocessing.MinMaxScaler
归一化之后的数据服从正态分布,公式如下:
x ∗ = x − m i n ( x ) m a x ( x ) − m i n ( x ) x^*=\frac{x-min(x)}{max(x)-min(x)} x=max(x)min(x)xmin(x)

preprocessing.MinMaxScaler API
步骤一:导入库和数据

from sklearn.preprocessing import MinMaxScaler
data = [[-1, 2], [-0.5, 6], [0, 10], [1, 18]]
import pandas as pd
pd.DataFrame(data)

ccc-sklearn-3-特征工程_第1张图片
步骤二:实例化并训练

scaler = MinMaxScaler()
scaler = scaler.fit(data)
result = scaler.transform(data)

result_ = scaler.fit_transform(data)

ccc-sklearn-3-特征工程_第2张图片
步骤三:还原

scaler.inverse_transform(result)

ccc-sklearn-3-特征工程_第3张图片
步骤四:修改feature_range参数来控制归一范围

data = [[-1, 2], [-0.5, 6], [0, 10], [1, 18]]
scaler = MinMaxScaler(feature_range=[5,10])
result = scaler.fit_transform(data)

ccc-sklearn-3-特征工程_第4张图片
步骤五:numpy中归一化的实现

import numpy as np
X = np.array([[-1, 2], [-0.5, 6], [0, 10], [1, 18]])
x_nor = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0))
x_inverse = x_nor * (X.max(axis=0) - X.min(axis=0)) + X.min(axis=0)

ccc-sklearn-3-特征工程_第5张图片
preprocessing.StandardScaer API
数据按均值(μ)中心化再按标准差(σ)缩放,数据就会服从为均值为0,方差为1的正态分布的过程,为数据标准化,公式如下:
x ∗ = x − u σ x^*=\frac{x-u}{σ} x=σxu

from sklearn.preprocessing import StandardScaler
data = [[-1, 2], [-0.5, 6], [0, 10], [1, 18]]

scaler = StandardScaler()
scaler.fit(data)
scaler.mean_ #均值
scaler.var_ #方差
x_std = scaler.transform(data)
x_std #方差
x_std.mean() #均值
x_std.std() #方差
scaler.fit_transform(data)
scaler.inverse_transform(x_std)

ccc-sklearn-3-特征工程_第6张图片
StandardScaler和MinMaxScaler的说明

  1. 两者中空值NaN会被当做是缺失值,在fit的时候忽略,在transform的时候保持缺失NaN的状态显示
  2. fit接口中,依然只允许导入至少二维数组,一维数组导入会报错
  3. 大多数机器学习算法中,会选择StandardScaler来进行特征缩放,因为MinMaxScaler对异常值非常敏感
  4. MinMaxScaler在不涉及距离度量、梯度、协方差计算以及数据需要被压缩到特定区间时使用广泛,如数字图像处理中量化像素强度时,都会使用MinMaxScaler将数据压缩于[0,1]区间之中

更多无量纲化的参考表
ccc-sklearn-3-特征工程_第7张图片

3.缺失值的处理

impute.SimpleImputer API
在这里插入图片描述

参数 含义&输入
missing_values 告诉SimpleImputer,数据中的缺失值长什么样,默认np.nan
strategy “mean”使用均值填补,默认;“median"用中值填补;"most_frequent”用众数填补;“constant"表示请参考参数“fill_value"中的值
fill_value 参数startegy为”constant"的时候可用,可输入字符串或数字表示要填充的值,常用0
copy 默认为True,将创建特征矩阵的副本,反之则会将缺失值填补到原本的特征矩阵中去

步骤一:库和数据导入

import pandas as pd
data = pd.read_csv("./data/Narrativedata.csv",index_col=0)
data.head()

ccc-sklearn-3-特征工程_第8张图片
可以看到Age和Embarked都有缺失值

步骤二:取出Age目标并实例化API进行填充

Age = data.loc[:,"Age"].values.reshape(-1,1)

from sklearn.impute import SimpleImputer
imp_mean = SimpleImputer()
imp_median = SimpleImputer(strategy="median")
imp_0 = SimpleImputer(strategy="constant",fill_value=0)

imp_mean = imp_mean.fit_transform(Age)
imp_median = imp_median.fit_transform(Age)
imp_0 = imp_0.fit_transform(Age)

ccc-sklearn-3-特征工程_第9张图片
ccc-sklearn-3-特征工程_第10张图片
步骤三:使用中值进行填充,并同样对Embarked进行众数填充

data.loc[:,"Age"] = imp_median
data.info()

Embarked = data.loc[:,"Embarked"].values.reshape(-1,1)
imp_mode = SimpleImputer(strategy="most_frequent")
data.loc[:,"Embarked"] = imp_mode.fit_transform(Embarked)
data.info()

ccc-sklearn-3-特征工程_第11张图片
用Pandas和Numpy进行填补
步骤一:库和数据导入

import pandas as pd
data = pd.read_csv('./data/Narrativedata.csv',index_col=0)
data.head()

ccc-sklearn-3-特征工程_第12张图片
步骤二:直接取出Age列中空值进行中位数填充

data.loc[:,"Age"] = data.loc[:,"Age"].fillna(data.loc[:,"Age"].median())

ccc-sklearn-3-特征工程_第13张图片
步骤三:由于Embarked样本很少,可以删除

data.dropna(axis=0,inplace=True) #inplace默认false
data.info()

ccc-sklearn-3-特征工程_第14张图片

4.处理分类型特征:编码与哑变量

为让数据适应算法和库,我们必须将数据进行编码,即将文字型数据转换为数值型

preprocessing.LabelEncoder:标签专用,能够将分类转换为分类数值
步骤一:导入库和数据

from sklearn.preprocessing import LabelEncoder
import pandas as pd

data = pd.read_csv('./data/Narrativedata.csv',index_col=0)
data.head()

ccc-sklearn-3-特征工程_第15张图片
步骤二:直接将数据类型转换

 LabelEncoder().fit(data.iloc[:,-1]).classes_
 data.iloc[:,-1] = LabelEncoder().fit_transform(data.iloc[:,-1])
 data.head()

ccc-sklearn-3-特征工程_第16张图片
preprocessing.OrdinalEncoder:特征专用,能够将分类特征转换为分类数值
步骤一:导入库和数据

from sklearn.preprocessing import OrdinalEncoder
data_ = data.copy() #用的上次处理Suivived的data
data_.head()

ccc-sklearn-3-特征工程_第17张图片
步骤二:处理缺失值,和前面讲的那样

data_.loc[:,"Age"] = data.loc[:,"Age"].fillna(data.loc[:,"Age"].median())
data_.dropna(axis=0,inplace=True)
data_.info()

ccc-sklearn-3-特征工程_第18张图片
步骤三:将第二列到倒数第二列的特征的特征转换成分类数值

OrdinalEncoder().fit(data_.iloc[:,1:-1]).categories_
data_.iloc[:,1:-1] = OrdinalEncoder().fit_transform(data_.iloc[:,1:-1])
data_.head()

ccc-sklearn-3-特征工程_第19张图片
说明:

  • 很明显,数字之间能进行转换,为了忽略数字中自带的数学性质,我们可以采用OneHotEncoder编码

preprocessing.OneHotEncoder API:独热编码,创建哑变量
ccc-sklearn-3-特征工程_第20张图片
返回稀疏矩阵,让三个取值之间相互独立,即哑变量

实际操作:
步骤一:导入库和数据

from sklearn.preprocessing import LabelEncoder
import pandas as pd

data = pd.read_csv('./data/Narrativedata.csv',index_col=0)
data.head()

ccc-sklearn-3-特征工程_第21张图片
步骤二:异常值处理

data.loc[:,"Age"] = data.loc[:,"Age"].fillna(data.loc[:,"Age"].median())
data.dropna(axis=0,inplace=True)

步骤三:取出目标特征列并实例化OneHotEncoder进行编码

from sklearn.preprocessing import OneHotEncoder

X = data.iloc[:,1:-1]
OneHotEncoder(categories='auto').fit_transform(X).toarray()

ccc-sklearn-3-特征工程_第22张图片
enc表示实例化的API(省略代码),这里再探索其他信息
ccc-sklearn-3-特征工程_第23张图片

步骤四:拼接到表中,并删除之前的特征

newdata = pd.concat([data,pd.DataFrame(result)],axis=1)
newdata.head()

newdata.drop(['Sex','Embarked'],axis=1,inplace=True)
newdata.head()

ccc-sklearn-3-特征工程_第24张图片
步骤五:重新为列命名即可

newdata.columns =["Age","Survived","Female","Male","Embarked_C","Embarked_Q","Embarked_S"]
newdata.head()

ccc-sklearn-3-特征工程_第25张图片
ccc-sklearn-3-特征工程_第26张图片

5.处理连续型数据:二值化与分箱

sklearn.preprocessing.Binarizer API
设置阈值,大于阈值为1,其他为0。仅考虑某种现象的存在与否

使用实例:

data_2 = data.copy()

from sklearn.preprocessing import Binarizer
X = data_2.iloc[:,0].values.reshape(-1,1)
transformer = Binarizer(threshold=30).fit_transform(X)
transformer

ccc-sklearn-3-特征工程_第27张图片
preprocessing.KBinsDiscretizer API
将连续型变量划分为分类变量的类,能够将连续性变量排序后按顺序分箱后编码:参数说明如下

参数 含义&输入
n_bins 每个特征中分箱的个数,默认5,一次会被运用到所有导入的特征
encode 编码方式,默认“onehot”
“onehot”:做哑变量,之后返回一个稀疏矩阵,每一列是一个特征中的一个类别,含有该类别的样本表示为1,不含的表示为0 “ordinal”:每个特征的每个箱都被编码为一个整数,返回每一列是一个特征,每个特征下含有不同整数编码的箱的矩阵
“onehot-dense”:做哑变量,之后返回一个密集数组。
strategy 用来定义箱宽的方式,默认"quantile"
“uniform”:表示等宽分箱,即每个特征中的每个箱的最大值之间的差为(特征.max() - 特征.min())/(n_bins)
“quantile”:表示等位分箱,即每个特征中的每个箱内的样本数量都相同
“kmeans”:表示按聚类分箱,每个箱中的值到最近的一维k均值聚类的簇心得距离都相同

使用实例:

from sklearn.preprocessing import KBinsDiscretizer
X = data.iloc[:,0].values.reshape(-1,1)
est = KBinsDiscretizer(n_bins=3, encode='ordinal',strategy='uniform')
est.fit_transform(X)

ccc-sklearn-3-特征工程_第28张图片
查看分箱-三箱

set(est.fit_transform(X).ravel())

在这里插入图片描述

查看分箱-哑变量

est = KBinsDiscretizer(n_bins=3,encode='onehot',strategy='uniform')
est.fit_transform(X).toarray()

ccc-sklearn-3-特征工程_第29张图片

6.特征选择 feature_selection

这里用泰坦尼克的数据来当作例子
ccc-sklearn-3-特征工程_第30张图片
其中是否存活是我们的标签。很明显,以判断“是否存活”为目的,票号,登船的舱门,乘客编号明显是无关特征,可以直接删除。姓名,舱位等级,船舱编号,也基本可以判断是相关性比较低的特征。性别,年龄,船上的亲人数量,这些应该是相关性比较高的特征

6.1.1方差过滤:消除方差为0的特征
VarianceThreshold API
ccc-sklearn-3-特征工程_第31张图片
本次数据量很大,尤其是它的特征数量很多,如果直接使用支持向量机或者神经网络来处理会极其消耗资源,所以需要我们进行特征处理,下图是处理的基本步骤
在这里插入图片描述

from sklearn.feature_selection import VarianceThreshold
selector = VarianceThreshold()
X_var0 = selector.fit_transform(x)

ccc-sklearn-3-特征工程_第32张图片
删除差异值为0的特征后任然剩下708个特征,所以还需要进一步的选择。可以直接提高VarianceThreshold中threshold参数提高阈值

6.1.2使用特征方差的中位数作为参数

import numpy as np
np.median(x.var().values)
x_fsvar = VarianceThreshold(np.median(x.var().values)).fit_transform(x)
x_fsvar.shape

ccc-sklearn-3-特征工程_第33张图片
这样可以消除一般的特征

6.1.3使用伯努利随机变量删除某种分类占比80%以上的特征

#二分类问题,所以可以这样算
x_bar = VarianceThreshold(.8 * (1- .8)).fit_transform(x)
x_bar.shape

ccc-sklearn-3-特征工程_第34张图片

6.2方差过滤对于模型的影响

这里比较KNN和随机森林分别在方差过滤前和方差过滤后运行的效果和运行时间

步骤一:导入模块并准备数据

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)

步骤二:KNN方差-过滤前

#======【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()

ccc-sklearn-3-特征工程_第35张图片
步骤三:KNN方差-过滤后

#======【TIME WARNING:20 mins+】======#
cross_val_score(KNN(),X_fsvar,y,cv=5).mean()
 
#======【TIME WARNING:2 hours】======#
%%timeit
cross_val_score(KNN(),X,y,cv=5).mean()

ccc-sklearn-3-特征工程_第36张图片
KNN过滤后的效果十分明显:准确率稍有提升,平均运行时间减少了10分钟,特征选择过后算法的效率上升了1/3

步骤四:随机森林方差-过滤前与过滤后

cross_val_score(RFC(n_estimators=10,random_state=0),X,y,cv=5).mean()
cross_val_score(RFC(n_estimators=10,random_state=0),X_fsvar,y,cv=5).mean()

ccc-sklearn-3-特征工程_第37张图片

说明:
  • 无论过滤法如何降低特征的数量,随机森林只会选取固定数量的特征来建模
  • 过滤法的主要目的是在维持算法表现的前提下,帮助算法降低计算成本
  • KNN邻算法中,特征越少,距离计算的维度就越少,模型明显会随着特征的减少变得轻量
  • 决策树在建模过程中随机抽取的特征数目却远远超过随机森林当中每棵树随机抽取的特征数目,因此,过滤法对随机森林无用,却对决策树有用

方差过滤影响总结:

阈值很小被
过滤掉得特征比较少
阈值比较大
被过滤掉的特征有很多
模型表现 不会有太大影响 可能变好,代表被滤掉的特征大部分是噪音
也可能变糟糕,代表被滤掉的特征中很多都是有效特征
运行时间 可能降低模型的运行时间
基于方差很小的特征有多少
当方差很小的特征不多时对模型没有太大影响
降低模型的运行时间
算法在遍历特征时的计算越复杂,运行时间下降得越多
6.3卡方过滤

针对离散型标签(分类问题)的相关性过滤
基本流程可以概括为:先通过feature_selection.chi2计算每个非负特征和标签之间的卡方统计量,并依照统计量大小的高低通过feature_selection.SelectKBest来进行选择前K个分数最高的类,从而除去最可能独立于标签的特征。

实际操作:先方差过滤(如果模型表现增加)再卡方过滤

from sklearn.ensemble import  RandomForestClassifier as RFC
from sklearn.model_selection import cross_val_score
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2

y = data.iloc[:,0]
X_fchi = SelectKBest(chi2, k=300).fit_transform(x_fsvar,y)

cross_val_score(RFC(n_estimators=10,random_state=0),X_fchi,y,cv=5).mean()

ccc-sklearn-3-特征工程_第38张图片
结果模型效果降低,说明K=300时删除了与模型相关的特征,需要提升K值

超参数K值的学习曲线

#======【TIME WARNING: 5 mins】======#
 
%matplotlib inline
import matplotlib.pyplot as plt
 
score = []
for i in range(390,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)
plt.plot(range(390,200,-10),score)
plt.show()

ccc-sklearn-3-特征工程_第39张图片
可以观察K值增大,模型的表现也上升,即数据中所有的特征都与标签相关。为了节约时间,我们一般根据P值来选择K,具体规则如下表:

P值 <=0.05或0.01 >0.05或0.01
数据差异 差异不是自然形成 差异是自然的样本误差
相关性 差异不是自然形成的 两组数据相互独立
原假设 拒绝原假设,接收备择假设 接受原假设

特征工程中,一般选择卡方值很大,p值小于0.05的特征,即和标签相关联的特征。而调用SelectKBest之前,可以直接从chi实例化后的模型中获得各个特征所对应的卡方值和P值

根据P值来选择K

chivalue, pvalues_chi = chi2(x_fsvar,y)
k = chivalue.shape[0] - (pvalues_chi > 0.05).sum()

ccc-sklearn-3-特征工程_第40张图片
该结果说明经过方差过滤后,数据集本身已经不含与标签无关的特征,可以全部用与模型

6.4F检验-ANOVA,方差齐性检验

捕捉每个特征与标签之间的线性关系的过滤方法,包括feature_selection.f_classif(F检验分类)与feature_selection.f_regression(F检验回归)

from sklearn.feature_selection import f_classif
F, pvalues_f = f_classif(X_fsvar,y)
k = F.shape[0] - (pvalues_f > 0.05).sum()

ccc-sklearn-3-特征工程_第41张图片
得到的结论与之前相同,即所有标签都相关
F检验在数据服从正态分布时效果非常稳定,所以一般先将数据转换成正态分布再进行F过滤

6.5互信息法

用来捕捉每个特征与标签之间的任意关系的过滤方法。
包括feature_selection.mutual_info_classif(互信息分类)和
feature_selection.mutual_info_regression(互信息回归),可以找出任意关系,而F检验只能找出线性关系。返回“每个特征与目标之间的互信息量的估计”,为0表示两者独立

from sklearn.feature_selection import mutual_info_classif as MIC
result = MIC(x_fsvar,y)
k = result.shape[0] - sum(result <= 0)

显然所有值都大于0,与之前的结论相同

常用过滤法总结:

说明 超参数的选择
VarianceThreshold 方差过滤,可输入方差阈值,返回方差大于阈值的新特征矩阵 看具体数据究竟是含有更多噪声还是更多有效特征
一般使用0或1来筛选也可以画学习曲线或取中位数跑模型来帮助确认
SelectKBest 用来选取K个统计量结果最佳的特征,生成符合统计量要求的新特征矩阵 看配合使用的统计量
chi2 卡方检验,专用于分类算法,捕捉相关性 追求p小于显著性水平的特征
f_classif F检验分类,只能捕捉线性相关性要求数据服从正态分布 追求p小于显著性水平的特征
f_regression F检验回归,只能捕捉线性相关性要求数据服从正态分布 追求p小于显著性水平的特征
mutual_info_classif 互信息分类,可以捕捉任何相关性不能用于稀疏矩阵 追求互信息估计大于0的特征
mutual_info_regression 互信息回归,可以捕捉任何相关性不能用于稀疏矩阵 追求互信息估计大于0的特征

7.Embedded嵌入法

  • 算法自己决定使用哪些特征的方法,即特征选择和算法训练同时进行。
  • 使用某些机器学习的算法和模型进行训练,得到各个特征的权值系数,根据权值系数从大到小选择特征
  • 权值系数往往代表了特征对于模型的某种贡献或某种重要性,比如决策树和树的集成模型中的feature_importances_属性,可以列出各个特征对树的建立的贡献,我们就可以基于这种贡献的评估,找出对模型建立最有用的特征
  • 嵌入法的结果会更加精确到模型的效用本身,对于提高模型效力有更好的效果。由于考虑特征对模型的贡献,无关的特征和无区分度的特征都会因为缺乏对模型的贡献而被删除掉

ccc-sklearn-3-特征工程_第42张图片
嵌入法引入了算法来挑选特征,因此其计算速度也会和应用的算法有很大的关系。如果采用计算量很大,计算缓慢的算法,嵌入法本身也会非常耗时耗力。并且,在选择完毕之后,我们还是需要自己来评估模型

feature_selection.SelectFromModel API

  • 一个元变换器,可以与任何在拟合后具有coef_,feature_importances_属性或参数中可选惩罚项的评估器一起使用
  • 对于使用惩罚项的模型来说,正则化惩罚项越大,特征在模型中对应的系数就会越小。当正则化惩罚项大到一定的程度的时候,部分特征系数会变成0,当正则化惩罚项继续增大到一定程度时,所有的特征系数都会趋于0

在这里插入图片描述

参数 说明
estimator 只要是带feature_importances_或者coef_属性,或带有l1和l2惩罚项的模型都可以使用
threshold 重要性低于这个阈值的特征都将被删除
prefit 默认False,判断是否将实例化后的模型直接传递给构造函数。为True,则必须直接调用fit和transform,不能使用fit_transform,并且SelectFromModel不能与cross_val_score,GridSearchCV和克隆估计器的类似实用程序一起使用。
norm_order k可输入非零整数,正无穷,负无穷,默认值为1
在评估器的coef_属性高于一维的情况下,用于过滤低于阈值的系数的向量的范数的阶数
max_features 在阈值设定下,要选择的最大特征数。要禁用阈值并仅根据max_features选择,请设置threshold = -np.inf

随机森林学习曲线找到最佳特征值

from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import RandomForestClassifier as RFC
RFC_ = RFC(n_estimators =10,random_state=0)
X_embedded = SelectFromModel(RFC_,threshold=0.005).fit_transform(X,y) 
#0.005这个阈值对于有780个特征的数据来说,是非常高的阈值,因为平均每个特征只能够分到大约0.001feature_importances_
X_embedded.shape
#模型的维度明显被降低了
#同样的,我们也可以画学习曲线来找最佳阈值
#======【TIME WARNING:10 mins】======#
import numpy as np
import matplotlib.pyplot as plt
RFC_.fit(X,y).feature_importances_
threshold = np.linspace(0,(RFC_.fit(X,y).feature_importances_).max(),20)
score = []
for i in threshold:
    X_embedded = SelectFromModel(RFC_,threshold=i).fit_transform(X,y)
    once = cross_val_score(RFC_,X_embedded,y,cv=5).mean()
    score.append(once)
plt.plot(threshold,score)
plt.show()

ccc-sklearn-3-特征工程_第43张图片
随着阈值越来越高,模型效果变差,删除特征变多,信息损失变大

在0.00134之前寻找最加特征值

#======【TIME WARNING:10 mins】======#
score2 = []
for i in np.linspace(0,0.00134,20):
    X_embedded = SelectFromModel(RFC_,threshold=i).fit_transform(X,y)
    once = cross_val_score(RFC_,X_embedded,y,cv=5).mean()
    score2.append(once)
plt.figure(figsize=[20,5])
plt.plot(np.linspace(0,0.00134,20),score2)
plt.xticks(np.linspace(0,0.00134,20))
plt.show()

ccc-sklearn-3-特征工程_第44张图片

使用找到的0.000564跑模型:

X_embedded = SelectFromModel(RFC_,threshold=0.000564).fit_transform(X,y)
X_embedded.shape
 
cross_val_score(RFC_,X_embedded,y,cv=5).mean()
 
#=====【TIME WARNING:2 min】=====#
#我们可能已经找到了现有模型下的最佳结果,如果我们调整一下随机森林的参数呢?
cross_val_score(RFC(n_estimators=100,random_state=0),X_embedded,y,cv=5).mean()

ccc-sklearn-3-特征工程_第45张图片
结果已经接近需要计算2个小时的KNN,如果继续调参可以再提高,所以对于需要思考很多统计量的过滤法来说,嵌入法是更加有效的方法

8.Wrapper包装法

  1. 计算成本在过滤法和嵌入法之间
  2. 依赖于算法自身的选择,比如coef_属性或feature_importances_属性来完成特征选择
  3. 使用一个目标函数作为黑盒来选取特征,不需输入某个评估指标或统计量的阈值
  4. 最能保证模型效果的特征选择方法

ccc-sklearn-3-特征工程_第46张图片
feature_selection.RFE API

  1. 贪婪的优化算法,旨在找到性能最佳的特征子集
  2. 反复创建模型,在每次迭代时保留最佳特征或剔除最差特征,下一次迭代时,使用上一次建模中没有被选中的特征来构建下一个模型,直到所有特征都耗尽为止
from sklearn.feature_selection import RFE
RFC_ = RFC(n_estimators =10,random_state=0)
selector = RFE(RFC_, n_features_to_select=340, step=50).fit(X, y)
 
selector.support_.sum()#340
selector.ranking_
X_wrapper = selector.transform(X)
 
cross_val_score(RFC_,X_wrapper,y,cv=5).mean()

ccc-sklearn-3-特征工程_第47张图片
学习曲线:

#======【TIME WARNING: 15 mins】======#
 
score = []
for i in range(1,751,50):
    X_wrapper = RFE(RFC_,n_features_to_select=i, step=50).fit_transform(X,y)
    once = cross_val_score(RFC_,X_wrapper,y,cv=5).mean()
    score.append(once)
plt.figure(figsize=[20,5])
plt.plot(range(1,751,50),score)
plt.xticks(range(1,751,50))
plt.show()

ccc-sklearn-3-特征工程_第48张图片
应用50个特征时,模型的表现就已经达到了90%以上,比嵌入法和过滤法都高效很多

特征选择总结:

多读多看多试多想!
多读多看多试多想!!
多读多看多试多想!!!

你可能感兴趣的:(sklearn,sklearn,python)