注: 很多内容是网上学习而得,感谢大佬们的分享~
本文所有代码,包括一些参数搜索过程等详见:代码
一、特征选择
特征选择的代码请详见:特征选择基本方法
当特征非常多的时候,会导致算法性能的降低,所以我们需要选择有意义的特征输入机器学习的算法和模型进行训练,移除冗余特征。
特征选择的功能是减少特征数量、降维,提高模型性能,使模型泛化能力更强,减少过拟合。
在选择特征的时候,我们主要考虑以下问题:
特征是否发散: 如果一个特征不发散,即方差接近于0,则样本在这个特征上基本上没有差异,这说明这个特征对于样本的区分并没有什么用。
特征与目标的相关性: 特征若与目标强相关,说明这个特征对于预测结果是很重要的。
特征选择方法分类:
- Filter方法
过滤法主要按照特征发散性或相关性对各个特征进行评分,设定阈值或者待选择阈值的个数,选择符合条件的特征。 - Wrapper方法
包装法,根据目标函数(通常是预测效果评分),每次选择若干特征,或者排除若干特征。Wrapper特征选择方法直接把最终将要使用的模型的性能作为特征子集的评价标准,也就是说,Wrapper目的就是为给定的模型选择最有利于其性能的特征子集。 - Embedded方法
集成法,先使用某些机器学习的算法和模型进行训练,得到各个特征的权值系数,根据系数从大到小选择特征。类似于Filter方法,但是是通过训练来确定特征的优劣。
1、Filter方法
包括方差分析、相关系数法、卡方检验、F检验和互信息法。
(1)方差分析
方差较大的特征说明其取值发散,使用方差法,要先计算各个特征的方差,然后根据阈值,选择方差大于阈值的特征。
sklearn中提供了VarianceThreshold函数,可以直接调用:
from sklearn.feature_selection import VarianceThreshold
vt = VarianceThreshold(threshold=var_threshold)
X_all_new = vt.fit_transform(X_all) # X_all是训练数据
print(vt.variances_)
结果分析:
①X_all_new是选择满足var >= threshold之后的特征组成的训练集;
②vt.variances_返回所有特征的方差值
(2)相关系数法
相关系数法可以使用皮尔逊系数,皮尔逊系数只能衡量两个特征的线性相关性,先要计算各个特征对目标值的相关系数以及相关系数的P值。
皮尔逊系数计算公式:
ρ
X
,
Y
=
c
o
v
(
X
,
Y
)
σ
X
σ
Y
\rho_{X,Y} = \frac{cov(X, Y)}{\sigma_X \sigma_Y}
ρX,Y=σXσYcov(X,Y)
其中,
X
X
X和
Y
Y
Y表示两个特征对应的向量。
代码如下:
correlation = data.corr() # data包含特征和标签
上述代码的功能是得出所有(特征+标签),两两变量之间的相关关系。结果的取值区间为[-1,1],-1表示完全的负相关,+1表示完全的正相关,0表示没有线性相关。
注: 在另外一些库中,可以得到p-value的值,相关性越强,p-value越低(p-value表示p检验的显著性结果,p-value越小,表示原假设被拒绝的可能性越大[原假设是两个特征无关],即p-value越小,两个特征相关性越显著,相关性越强。一般
p
<
0.05
p<0.05
p<0.05 我们认为相关性较显著)。
Pearson相关系数的一个明显缺陷是,作为特征排序机制,他只对线性关系敏感。如果关系是非线性的,即便两个变量具有一一对应的关系,Pearson相关性也可能会接近0。
(3)卡方检验
卡方检验和信息增益是feature weight algorithm常用且效果较优的算法。
卡方检验思想:通过观察实际值和理论值的偏差来确定原假设是否成立。首先假设两个变量是无关的(此为原假设),然后观察实际值和理论值之间的偏差程度,若偏差足够小,则认为偏差是很自然的样本误差,接受原假设。若偏差大到一定程度,则否则原假设,接受备择假设。
卡方检验的基本公式:
χ
2
=
∑
(
A
−
E
)
2
E
=
∑
i
=
1
k
(
A
i
−
E
i
)
2
E
i
\chi^2 = \sum \frac{(A-E)^2}{E}=\sum_{i=1}^k \frac{(A_i-E_i)^2}{E_i}
χ2=∑E(A−E)2=i=1∑kEi(Ai−Ei)2
其中,
A
A
A表示观察值,E表示理论期望。
A
−
E
A-E
A−E表示观察值和理论值之间的偏差。
通过上述思想,我们可以得到,卡方检验的值越大,说明越相关。
from sklearn.feature_selection import chi2 # 卡方检验
from sklearn.feature_selection import SelectKBest # 根据 k个最高分选择功能。
k_chi = SelectKBest(chi2, k=15)
X_chi = k_chi.fit_transform(X_all, data['label']) # data[columns]是特征矩阵,data['label']是标签数据
print(X_chi)
print(k_chi.scores_)
print(k_chi.pvalues_)
返回结果分析:
X_chi返回选择的k个特征的矩阵
k_chi.scores_返回每一个特征的得分
k_chi.pvalues_返回每个特征的p-value值,p-value值越小越好。
(4)F检验
F检验和卡方检验都是检验的方法,f_classif用于分类模型,f_regression用于回归模型。
from sklearn.feature_selection import f_classif # F检验
from sklearn.feature_selection import SelectKBest # 根据 k个最高分选择功能。
k_f = SelectKBest(f_classif, k=15)
X_f = k_f.fit_transform(X_all, data['label'])
print(X_f)
print(k_f.scores_)
print(k_f.pvalues_)
F检验和卡方检验类似,都是显著性检验的方式。
(5)互信息法
互信息稀疏反映相关性,互信息越大,说明越相关。
互信息的公式如下:
I
(
X
;
Y
)
=
∑
y
∈
Y
∑
x
∈
X
p
(
x
,
y
)
l
o
g
(
p
(
x
,
y
)
p
(
x
)
p
(
y
)
)
I(X;Y) = \sum_{y \in Y} \sum_{x \in X} p(x, y) log(\frac{p(x, y)} {p(x)p(y)})
I(X;Y)=y∈Y∑x∈X∑p(x,y)log(p(x)p(y)p(x,y))
其中,
p
(
x
,
y
)
p(x,y)
p(x,y)是
X
X
X和
Y
Y
Y的联合概率分布函数,而
p
(
x
)
p(x)
p(x)和
p
(
y
)
p(y)
p(y)分别是
X
X
X和
Y
Y
Y的边缘概率分布。
from sklearn.feature_selection import mutual_info_classif
from sklearn.feature_selection import SelectKBest # 根据 k个最高分选择功能。
k_info = SelectKBest(mutual_info_classif, k=15)
X_info = k_info.fit_transform(X_all, data['label'])
print(X_info)
print(k_info.scores_)
2、Wrapper方法
从模型的性能来看,包裹式特征选择比过滤式特征选择更好,但需要多次训练模型,因此计算开销较大
Wrapper方法主要包括递归特征消除法。
递归特征消除法
递归消除特征法使用一个基模型来进行多轮训练,每轮训练后,消除若干权值系数的特征,再基于新的特征集进行下一轮训练,直到达到指定的特征数为止。
这种方法sklearn.feature_selection提供了RFE、RFECV两种,RFECV使用交叉验证来保留最佳性能的特征。不过这里的交叉验证的数据集切割对象不再是行数据(样本),而是列数据(特征),同时学习器本身不变,最终得到不同特征对于score的重要程度,然后保留最佳的特征组合。
from sklearn.linear_model import LogisticRegression
from sklearn.feature_selection import RFE, RFECV
# RFE
model_lg = RFE(estimator=LogisticRegression(), n_features_to_select=15)
X_lg = model_lg.fit_transform(X_all, data['label'])
print(X_lg)
print(model_lg.n_features_)
print(model_lg.support_)
print(model_lg.ranking_)
# RFECV
model_lg_cv = RFECV(estimator=LogisticRegression(), step=1, cv=StratifiedKFold(n_splits=3), scoring="accuracy")
X_lg_cv = model_lg_cv.fit_transform(X_all, data['label'])
print(X_lg_cv)
print(model_lg_cv.n_features_)
print(model_lg_cv.support_)
print(model_lg_cv.ranking_)
n_features_:表示选择的特征数
support_:每一个特征是否被选择,True表示被选择,False表示没有被选择
ranking_:排名,所有被选择的特征值为1
3、Embedded方法
包括基于树模型的特征选择法、正则化方法等。
(1)基于树模型的特征选择法
树模型中GBDT也可用来作为基模型进行特征选择。
from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import GradientBoostingClassifier
model_gdbc= SelectFromModel(GradientBoostingClassifier())
X_gdbc = model_gdbc.fit_transform(X_all, data['label'])
print(X_gdbc)
print("shape of X_gdbc::", X_gdbc.shape)
(2)基于L1的特征选择法
使用L1范数作为惩罚项的线性模型会得到稀疏解,可以起到特征选择的作用。加入L1正则化之后的目标函数为:
J
=
L
+
λ
Ω
(
w
)
J = L + \lambda \Omega(w)
J=L+λΩ(w)
当最小化目标函数时,会有一些
w
i
=
0
w_i=0
wi=0,起到了特征选择的作用(具体可参考prml第三章内容)。
from sklearn.feature_selection import SelectFromModel
from sklearn.svm import LinearSVC
model_lsvc = SelectFromModel(LinearSVC(C=0.01, penalty="l1", dual=False))
X_lsvc = model_lsvc.fit_transform(X_all, data['label'])
print(X_lsvc)
print("shape of X_lsvc::", X_lsvc.shape)
二、网格搜索
使用网格搜索确定特征选择方法参数的代码请详见:特征选择方法应用
网格搜索类似于暴力搜索,给出参数值列表,遍历每个超参数组合,选择性能最佳的参数组合。在代码中使用了for循环实现这一过程。除此之外,可以使用
sklearn.model_selection.GridSearchCV实现这一功能。
三、不平衡处理
关于不平衡处理的代码和效果请详见:
oversampling:oversampling
undersampling:undersampling
不平衡处理有很多方法,详见之前的论文阅读 – Paper:Learning from Imbalanced Data - by H He et al.,这次主要使用了如下算法:
过采样: 随机过采样、SMOTE、ADASYN
欠采样: 随机欠采样
四、pu-learning
关于使用pu-learning处理问题的代码请详见:pu-learning
训练标准分类器的时候我们需要正例样本和负例样本,而且尽量正负例样本数目平衡。但是如果我们的训练集中有很多正例,但是负例很少或者没有,那应该怎么办呢?pu-learning可以解决这个问题,pu-learning在学术界也一直被研究。
关于pu-learning的主要代码详见:
pu-learning主要有3种,分别是应用标准分类器、pu-bagging和Two-step,下面详细介绍下这3种方法的主要思想。
1、标准分类器
在这种方法中,我们将已知的负例数据和无标签数据都当做负例数据,然后使用正例数据和负例数据训练数据集。这种方法是解决pu-learning最直接也是最简单的方法。
2、pu-bagging
介绍pu-bagging之前先介绍下bagging的思想:
Bagging即套袋法,其算法过程如下:
A)从原始样本集中抽取训练集。每轮从原始样本集中使用Bootstrap的方法抽取n个训练样本(Bootstrap:可重复抽样)。
B)使用抽样得到的训练集训练模型。
C)重复A和B步骤k次,k个训练集共得到k个模型。
D)对分类问题:将上步得到的k个模型采用投票的方式得到分类结果;对回归问题,计算上述模型的均值作为最后的结果。
pu-bagging便是借助了bagging的思想。其具体算法如下:
A)随机采样出和正例数目相同的无标签数据当做负例数据
B)使用A步骤采样的负例数据和正例数据训练分类器,并使用此分类器预测集之外的其他数据。
C)重复k次,最后预测结果取k次的预测平均值。
3、Two-Step
Two-Step的pu-learning不是随机采样数据,其算法思想如下:
A)将无标签数据当做负例,和正例一起训练分类器。识别出无标签数据中可靠的负例。
B)使用正例和A步骤中得到的可靠负例训练分类器,并不断迭代。
参考文献:
[1] 递归式特征消除:Recursive feature elimination
[2] 特征选择 (feature_selection)
[3] 特征选择之卡方检验
[4] Positive-unlabeled learning