在特征工程部分,我们构建了一系列位置信息相关的特征、组合特征、成交时间特征、 排序特征、类别稀疏特征等,这么多维特征一方面可能会导致维数灾难,另一方面很容易导致过拟合,需要做降维处理,降维方法常用的有如 PCA,t-SNE 等,这类方法的计算复杂度比较高。并且根据以往工作经验,PCA 或 t-SNE 效果不是特别好。
除了采用降维算法之外,也可以通过特征选择来降低特征维度。
特征选择的方法很多: 最大信息系数(MIC)、皮尔森相关系数(衡量变量间的线性相关性)、正则化方法(L1, L2)、基于模型的特征排序方法。
用正则化来做特征选择,L1,L2,对于特征维度很大的情况,作L1, 对于特征维度很小的情况,作L2。
比较高效的是最后一种,即基于学习模型的特征排序方法, 这种方法有一个好处:模型学习的过程和特征选择的过程是同时进行的,因此我们采用这种 方法,基于 xgboost 来做特征选择,xgboost 模型训练完成后可以输出特征的重要性,据此我们可以保留 Top N 个特征,从而达到特征选择的目的。
还有其他的总结。
特征选择,就是从多个特征中,挑选出一些对结果预测最有用的特征。因为原始的特征中可能会有冗余和噪声。
特征选择和降维有什么区别呢?前者只踢掉原本特征里和结果预测关系不大的, 后者做特征的计算组合构成新特征。
3.1 过滤型
方法: 评估单个特征和结果值之间的相关程度, 排序留下Top相关的特征部分。
-评价方式:通过方差选择法、Pearson相关系数,相关系数法、卡方检验法、互信息法来对特征进行评分,设定阈值或者待选择的阈值的个数来选择 。
-缺点:只评估了单个特征对结果的影响,没有考虑到特征之间的关联作用, 可能把有用的关联特征误踢掉。比如多项式组合特征,pearson相关系数不是很大,因为是非线性,所以相关系数也不一定大,但如果用这个方法有可能会被去掉,因此工业界使用比较少。
还有方差计算其实可以放在特征处理。计算各个特征的方差,剔除小于设定的阈值的特征,剔除特征值 波动较小的特征,例如一个特征的所有值都为1,那这个特征对于预测目标变量就没什么作用;方法很简单,但实际应用中只有少数变量才会存在只取某个值的情况,对特征选择作用比较小,可以当做数据预处理部分,之后再用其他方法进行特征选择。
3.2 包裹型
-方法:把特征选择看做一个特征子集搜索问题, 筛选各种特 征子集, 用模型评估效果。
-典型算法:“递归特征删除算法”。
-应用在逻辑回归的过程:用全量特征跑一个模型;根据线性模型的系数(体现相关性),删掉5-10%的弱特征,观察准确率/auc的变化;逐步进行, 直至准确率/auc出现大的下滑停止。
3.3 嵌入型
-方法:根据模型来分析特征的重要性,最常见的方式为用正则化方式来做特征选择。
-举例:最早在电商用LR做CTR预估, 在3-5亿维的系数特征上用L1正则化的LR模型。上一篇介绍了L1正则化有截断作用,剩余2-3千万的feature, 意味着其他的feature重要度不够。
正则化主要包括L1正则化和L2正则化:
L1正则化将系数W的L1范数作为惩罚项加到损失函数中,L1正则方法具有稀疏解的特性,因此天然具有特征选择的特性,但是不代表没被选到的特征就不重要,有可能是因为两个高度相关的特征最后只保留了一个;另外L1正则化和非正则化模型一样是不稳定的,如果特征集合中具有相关联的特征,当数据发生细微变化时也有可能导致很大的模型差异。
L2正则化将系数向量的L2范数添加到损失函数中,由于L2惩罚项中的系数是二次方的,会让系数的取值变得平均,对于有相关性的变量,会得到相近的系数;L2正则化也较L1稳。L1会令特征权重变成0,L2会使特征权重趋向于零。
"""1.过滤型"""
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
iris=load_iris()
X,y=iris.data,iris.target
print X.shape
X_new=SelectKBest(chi2,k=2).fit_transform(X,y)
print X_new.shape
"""输出:
(150L, 4L)
(150L, 2L)
"""
"""2.包裹型"""
from sklearn.feature_selection import RFE
from sklearn.linear_model import LinearRegression
from sklearn.datasets import load_boston
boston=load_boston()
X=boston["data"]
Y=boston["target"]
names=boston["feature_names"]
lr=LinearRegression()
rfe=RFE(lr,n_features_to_select=1)#选择剔除1个
rfe.fit(X,Y)
print "features sorted by their rank:"
print sorted(zip(map(lambda x:round(x,4), rfe.ranking_),names))
"""输出:按剔除后AUC排名给出
features sorted by their rank:
[(1.0, 'NOX'), (2.0, 'RM'), (3.0, 'CHAS'), (4.0, 'PTRATIO'), (5.0, 'DIS'), (6.0, 'LSTAT'), (7.0, 'RAD'), (8.0, 'CRIM'), (9.0, 'INDUS'), (10.0, 'ZN'), (11.0, 'TAX')
, (12.0, 'B'), (13.0, 'AGE')]"""
"""3.嵌入型 ,老的版本没有SelectFromModel"""
from sklearn.svm import LinearSVC
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectFromModel
iris=load_iris()
X,y=iris.data,iris.target
print X.shape
lsvc=LinearSVC(C=0.01,penalty='l1',dual=False).fit(X,y)
model=SelectFromModel(lsvc,prefit=True)
X_new=model.transform(X)
print X_new.shape
"""输出:
(150,4)
(150,3)
"""
还可以用逻辑回归。
from sklearn.linear_model import LogisticRegression
LogisticRegression 里的参数有penalty,可以调用来做特征选择