特征选取之单变量统计、基于模型选择、迭代选择SelectKBest特征选取

目录

单变量统计

方差分析

代码实现

SelectKBest特征选取

递归特征消除(RFE)

皮尔逊系数(相关系数)

基于树模型的特征选择

轻量级的高效梯度树

 随机森林

 迭代选择

每文一语


单变量统计

方差分析

在单变量统计中,我们计算每个特征和目标值之间的关系是否存在统计显著性,然后选择具有最高置信度的特征。对于分类问题,这也被称为方差分析(analysis of variance,ANOVA)。

这些测试的一个关键性质就是它们是单变量的(univariate),即它们只单独考虑每个特征。因此,如果一个特征只有在与另一个特征合并时才具有信息量,那么这个特征将被舍弃。

单变量测试的计算速度通常很快,并且不需要构建模型。另一方面,它们完全独立于你可能想要在特征选择之后应用的模型。

注意:不需要构建模型,利用纯理论的数学思维去构建出来

想要在 scikit-learn 中使用单变量特征选择,你需要选择一项测试——对分类问题通常是 f_classif(默认值),对回归问题通常是 f_regression——然后基于测试中确定的 p 值来选择一种舍弃特征的方法。所有舍弃参数的方法都使用阈值来舍弃所有 p 值过大的特征(意味着它们不可能与目标值相关)。计算阈值的方法各有不同,最简单的是 SelectKBest和 SelectPercentile,前者选择固定数量的 k 个特征,后者选择固定百分比的特征

代码实现

from sklearn.feature_selection import SelectPercentile
select=SelectPercentile(percentile=50)    #选取50%的特征
select.fit(X_train,y_train)
X_train_selected=select.transform(X_train)
print(X_train.shape)
print(X_train_selected.shape)

案例分析

import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.feature_selection import SelectPercentile    #SelectPercentile选择百分比,SelectKBest选择个数
from sklearn.model_selection import train_test_split

#使用sklearn自带的数据集
cancer=load_breast_cancer()

#向数据中添加噪声特征,前30个特征来自原数据集,后50个是噪声
rng=np.random.RandomState(42)
#构造噪声特征
noise=rng.normal(size=(len(cancer.data),50))
X_w_noise=np.hstack([cancer.data,noise])

#分割数据集用于测试和训练
X_train,X_test,y_train,y_test=train_test_split(X_w_noise,cancer.target,random_state=0,test_size=.5)

#特征选取
select=SelectPercentile(percentile=50)    #选取50%的特征
select.fit(X_train,y_train)
X_train_selected=select.transform(X_train)
print(X_train.shape)
print(X_train_selected.shape)

很明显的就发现特征变化了,而且是50%,还可以看看那些特征被选取

#查看哪些特征被选中
mask=select.get_support()
print(mask)
import matplotlib.pyplot as plt
plt.matshow(mask.reshape(1,-1),cmap='gray_r')
plt.xlabel('sample index')
plt.show()

这一类的特征选取方法比较的直接,也就是说直接保留多少占比的特征数量,在某些时候的模型训练中,我们需要根据特征的权重进行自定义的筛选。

SelectKBest特征选取

这类选取方法和相关系数选取比较的相似,可以通过这些对象的得分,选取重要的数据列

import pandas as pd 
import numpy as np
# 分类常用的
from sklearn.feature_selection import SelectKBest,f_classif,chi2,mutual_info_classif
# 分别是卡方检验,计算非负特征和类之间的卡方统计 chi
# 样本方差F值,f_classif
# 离散类别交互信息, mutual_info_classif
# 回归常用的
from sklearn.feature_selection import f_regression,mutual_info_regression
selector= SelectKBest(score_func= chi2,k=len(X.columns))
selector.fit(X,y)
score=-np.log10(selector.pvalues_)
# print(score)
score_index=np.argsort(score)[::-1]
for i in range(len(score)):
    print("%0.2f %s"%(score[score_index[i]],X.columns[score_index[i]]))

上述的数值大小代表着特征的重要性(下面有一个完整的代码实例)

from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
from sklearn.datasets import load_iris
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
from  scipy.stats import chi2_contingency
import numpy as np

 
model = SelectKBest(chi2, k=8)#选择k个最佳特征
X_new = model.fit_transform(X, y)
#feature_data是特征数据,label_data是标签数据,该函数可以选择出k个特征 

print("model shape: ",X_new.shape)

scores = model.scores_
print('model scores:', scores)  # 得分越高,特征越重要

p_values = model.pvalues_
print('model p-values', p_values)  # p-values 越小,置信度越高,特征越重要

# 按重要性排序,选出最重要的 k 个
indices = np.argsort(scores)[::-1]
k_best_features = list(X.columns.values[indices[0:8]])

print('k best features are:n ',k_best_features)

print(k_best_features)

简而言之,使用SelectKBest选取,可以调整里面的参数值,最终确定最重要的几个特征

递归特征消除(RFE)

递归消除特征法使用一个基模型来进行多轮训练,每轮训练后,移除若干权值系数的特征,再基于新的特征集进行下一轮训练

sklearn官方解释:对特征含有权重的预测模型(例如,线性模型对应参数coefficients),RFE通过递归减少考察的特征集规模来选择特征。首先,预测模型在原始特征上训练,每个特征指定一个权重。之后,那些拥有最小绝对值权重的特征被踢出特征集。如此往复递归,直至剩余的特征数量达到所需的特征数量。

RFE 通过交叉验证的方式执行RFE,以此来选择最佳数量的特征:对于一个数量为d的feature的集合,他的所有的子集的个数是2的d次方减1(包含空集)。指定一个外部的学习算法,比如SVM之类的。通过该算法计算所有子集的validation error。选择error最小的那个子集作为所挑选的特征。

"""
使用RFE进行特征选择:RFE是常见的特征选择方法,也叫递归特征消除。它的工作原理是递归删除特征,
并在剩余的特征上构建模型。它使用模型准确率来判断哪些特征(或特征组合)对预测结果贡献较大。
"""
from sklearn import datasets
from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression

model = LogisticRegression()
rfe = RFE(model, 3)
rfe = rfe.fit(X, y)
print(X.columns[rfe.support_])
print(rfe.support_)
print(rfe.ranking_)

RFE的稳定性很大程度上取决于迭代时,底层用的哪种模型。比如RFE采用的是普通的回归(LR),没有经过正则化的回归是不稳定的,那么RFE就是不稳定的。假如采用的Lasso/Ridge,正则化的回归是稳定的,那么RFE就是稳定的。 

皮尔逊系数(相关系数)

皮尔逊相关也称为积差相关(或者积矩相关)。我们假设有两个变量X,Y,那么两变量间的皮尔逊相关系数计算如下:

 

# 查看其他指标和income的相关性,并对其相关性系数排序
# 正相关与负相关,越接近1说明该变量值越大目标标签的值越容易分类为1
df.corr()[["n23"]].sort_values(by="n23",ascending=False)
# 可以根据相关性的值进行取值带入模型(特征选取与筛选)第一次选取
corr=df.corr()[["n23"]].sort_values(by="n23",ascending=False).iloc[1:10].index.values.astype("U")
corr_name=corr.tolist()
corr_name

 利用该方法还可以绘制热力图:sns.clustermap(df.corr())

 

 Pearson相关系数的一个明显缺陷是,作为特征排序机制,他只对线性关系敏感。如果关系是非线性的,即便两个变量具有一一对应的关系,Pearson相关性也可能会接近0。

基于树模型的特征选择

一般基于模型所做出的特征选择,效果比单变量的要好,但是不管是所有的特征选取的方法都需要结合实际的经验,来辨别特征的有效性。

轻量级的高效梯度树

from sklearn.model_selection import train_test_split,cross_val_score #拆分训练集和测试集
import lightgbm as lgbm #轻量级的高效梯度提升树
X_name=df.corr()[["n23"]].sort_values(by="n23",ascending=False).iloc[1:].index.values.astype("U")
X=df.loc[:,X_name.tolist()]
y=df.loc[:,['n23']]
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2,stratify=y,random_state=1)
lgbm_reg = lgbm.LGBMRegressor(objective='regression',max_depth=6,num_leaves=25,learning_rate=0.005,n_estimators=1000,min_child_samples=80, subsample=0.8,colsample_bytree=1,reg_alpha=0,reg_lambda=0)
lgbm_reg.fit(X_train, y_train)
#选择最重要的20个特征,绘制他们的重要性排序图
lgbm.plot_importance(lgbm_reg, max_num_features=20)

##也可以不使用自带的plot_importance函数,手动获取特征重要性和特征名,然后绘图
feature_weight = lgbm_reg.feature_importances_
feature_name = lgbm_reg.feature_name_
feature_sort = pd.Series(data = feature_weight ,index = feature_name)
feature_sort = feature_sort.sort_values(ascending = False)
# plt.figure(figsize=(10,8))
# sns.barplot(feature_sort.values,feature_sort.index, orient='h')
lgbm_name=feature_sort.index[:15].tolist()
lgbm_name

 随机森林

from sklearn import metrics
import warnings
warnings.filterwarnings("ignore")

from sklearn.ensemble import RandomForestClassifier
import matplotlib.pyplot as plt

selected_feat_names=set()
for i in range(10):                           #这里我们进行十次循环取交集
    tmp = set()
    rfc = RandomForestClassifier(n_jobs=-1)
    rfc.fit(X, y)

    #print("training finished")

    importances = rfc.feature_importances_
    indices = np.argsort(importances)[::-1]   # 降序排列
    S={}
    for f in range(X.shape[1]):
        if  importances[indices[f]] >=0.0001:
            tmp.add(X.columns[indices[f]])
            S[X.columns[indices[f]]]=importances[indices[f]]
            #print("%2d) %-*s %f" % (f + 1, 30, X.columns[indices[f]], importances[indices[f]]))
    selected_feat_names |= tmp
    imp_fea=pd.Series(S)
    
plt.figure(figsize=(10,8))

sns.barplot(imp_fea.values,imp_fea.index, orient='h')
print(imp_fea)
print(len(selected_feat_names), "features are selected")

其实还有很多,比如在回归问题中,基于惩罚项的特征选取;L1、L2模型也是可以的

 迭代选择

在迭代特征选择中,将会构建一系列模型,每个模型都使用不同数量的特征。有两种基本方法:开始时没有特征,然后逐个添加特征,直到满足某个终止条件;或者从所有特征开始,然后逐个删除特征,直到满足某个终止条件。由于构建了一系列模型,所以这些方法的计算成本要比前面讨论过的方法更高。

其中一种特殊方法是递归特征消除(recursive feature elimination, RFE),在前面也介绍了,它从所有特征开始构建模型,并根据模型舍弃最不重要的特征,然后使用除被舍弃特征之外的所有特征来构建一个新模型,如此继续,直到仅剩下预设数量的特征。为了让这种方法能够运行,用于选择的模型需要提供某种确定特征重要性的方法,正如基于模型的选择所做的那样。
 

每文一语

坚持走好每一步,探寻机遇才能不慌不乱!加油!

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>