-
2020-07-22 21:50:09
特征筛选的目的:
避免无用的特征(avoid useless features)
避免冗余的特征(avoid redundant features)
使用易于理解的简单特征(good features should easy to understand)
好的特征具有如下的特点:
有区分性(Informative)
特征之间相互独立(Independent)
简单易于理解(Simple)
sklearn中包含feature_select模块,基本都可以实现特征选择的功能。通常复杂模型有 feature_importances_ 参数用于获取特征的重要性;线性回归,SVM等方法特征的参数就代表了特征的重要性。
下面进入正题:(注:本文只做简单的概要整理,详细信息可去参考链接或自行查找)
特征选择常用方法过滤选择,包裹(包装)选择,嵌入选择。过滤和包装是与后续机器学习过程无关,嵌入则与机器学习过程相结合。
1、过滤选择
过滤式方法先对数据集进行特征选择,然后再训练学习器,特征选择过程与后续学习器无关,这相当于先用特征选择过程对初识特征进行“过滤”,然后再用过滤后的特征来训练模型。比如,Relief方法。
此方法有如下包含:
a、绘图判断
b、单特征
方差筛选:去掉方差为0或者小于某阈值的属性。如:
sklearn.feature_selection.VarianceThreshold(threshold=0.0)
c、数值特征与数值特征
协方差:判断两个特征关系,正相关或负相关
pearson系数:标准化后的协方差,因此更重要的特性来了,它消除了两个变量变化幅度的影响,而只是单纯反应两个变量每单位变化时的相似程度。(0.8-1.0 极强相关;0.6-0.8 强相关;0.4-0.6 中等程度相关;0.2-0.4 弱相关;0.0-0.2 极弱相关或无相关。)
距离相关系数:如果距离相关系数是0 ,那么我们就可以说这两个变量是独立的
d、类别特征与类别特征
卡方检验:先假设两个变量确实是独立的(“原假设”),然后观察实际值(观察值)与理论值(这个理论值是指“如果两者确实独立”的情况下应该有的值)的偏差程度。
Fisher得分:在同一个类别中的取值比较相似,而在不同类别之间的取值差异比较大;fisher得分越高,特征在不同类别中的差异性越大,在同一类别中的差异性越小,则特征越重要。
F检验: 用来判断特征与label的相关性的,F 检验只能表示线性相关关系
斯皮尔曼等级相关(分类,类别型与类别型)
Kendall(肯德尔等级)相关系数(分类)
互信息和最大互系数(非参数):互信息:估计特征与label之间的关系。最大信息系数。
距离相关系数
e、数值特征与类别特征
数值特征离散化:将数值特征离散化,然后,使用类别与类别变量相关性分析的方法来分析相关性
箱形图:使用画箱形图的方法,看类别变量取不同值,数值变量的均值与方差及取值分布情况。
Relief(Relevant Features):适用于二分类
Relief-F:适用于多分类
2、包装选择
包裹式选择特征(包装法)不考虑后续学习器不同,包裹式特征选择直接把最终将要使用的学习器的性能作为特征子集的评价准则。换言之,包裹式特征选择的目的就是为给定学习器选择最有利于其性能,量身定做的特征子集。包裹式选择比过滤式特征选择更好,但是另一方面,计算开销却要大得多。比如LVW方法(Las Vegas Wrapper)。
此方法有如下包含:
a、前向搜索
b、后向搜索
c、递归特征消除法
这三种方法的核心思想都是逐个选取(增加、删除)特征,观察对训练结果影响是否达到阈值。
3、嵌入选择
嵌入式特征选择是将特征选择过程与学习器训练过程融为一体,两者在同一个优化过程中优化,即在学习器训练过程中自动进行了特征选择。比如,L1正则化、决策树学习等。
此方法有如下包含:
a、正则化
L1/Lasso:L1正则方法具有稀疏解的特性,因此天然具备特征选择的特性
L2/Ridge
b、基于树模型的特征重要性
RF
ExtraTree
Adaboost
GBDT
XGboost:xgboost的基学习器可以是gbtree也可以是gbliner。当基学习器是gbtree时,可以计算特征重要性。
LightGBM
RF、Xgboost、ExtraTree每个选出topk特征,再进行融合:代码如下。
from sklearn import ensemble from sklearn.model_selection import GridSearchCV import xgboost as xgb def get_top_k_feature(features,model,top_n_features): feature_imp_sorted_rf = pd.DataFrame({'feature':features,'importance':model.best_estimator_.feature_importances_}).sort_values('importance',ascending='False') features_top_n = feature_imp_sorted_rf.head(top_n_features)['feature'] return features_top_n def ensemble_model_feature(X,Y,top_n_features): features = list(X) #随机森林 rf = ensemble.RandomForestRegressor() rf_param_grid = {'n_estimators':[900],'random_state':[2,4,6,8]} rf_grid = GridSearchCV(rf,rf_param_grid,cv=10,verbose=1,n_jobs=25) rf_grid.fit(X,Y) top_n_features_rf = get_top_k_feature(features=features,model=rf_grid,top_n_features=top_n_features) print('RF 选择完毕') #Adaboost abr = ensemble.AdaBoostRegressor() abr_grid = GridSearchCV(abr,rf_param_grid,cv=10,n_jobs=25) abr_grid.fit(X,Y) top_n_features_bgr = get_top_k_feature(features=features,model=abr_grid,top_n_features=top_n_features) print('Adaboost选择完毕') #ExtraTree etr = ensemble.ExtraTreesRegressor() etr_grid = GridSearchCV(etr,rf_param_grid,cv=10,n_jobs=25) etr_grid.fit(X,Y) top_n_features_etr = get_top_k_feature(features=features,model=etr_grid,top_n_features=top_n_features) print('ExtraTree选择完毕') #融合以上3个模型 features_top_n = pd.concat([top_n_features_rf,top_n_features_bgr,top_n_features_etr],ignore_index=True).drop_duplicates() print(features_top_n) print(len(features_top_n)) return features_top_n
sklearn中提供的方法
1、通过方差筛选:sklearn中的VarianceThreshold类可以用来做方差选择
2、卡方检验:sklearn中的chi2类可以用来做卡方检验
3、互信息:sklearn中的mutual_info_classif(分类)和mutual_info_regression(回归)来计算各个输入特征和输出值之间的互信息
4、sklearn的SelectFromModel函数
5、sklearn有一个feature_select模块可以做特征选择。
6、 线性回归模型中的ANOVA方法。 来自sklearn里的
7、 RandomForestClassifier,自带 feature_importances_ 功能。返回特征向量的重要性。可视化可以更直观的查看特征的重要性情况。简单实例如下:
import numpy as np import matplotlib.pyplot as plt from sklearn.datasets import make_classification from sklearn.ensemble import ExtraTreesClassifier # 生成测试数据 X,y = make_classification(n_samples=1000, n_features=10, n_informative=3, n_classes=2) # 选取学习器 forest = ExtraTreesClassifier(n_estimators=250, random_state=0) forest.fit(X,y) # 输出特征重要性 importances = forest.feature_importances_ std = np.std([tree.feature_importances_ for tree in forest.estimators_], axis=0) indices = np.argsort(importances)[::-1] # 打印 print("Feature ranking:") for f in range(X.shape[1]): print("%d. feature %d (%f)" % (f+1, indices[f], importances[indices[f]])) # 绘图 plt.figure() plt.title("Feature importances") plt.bar(range(X.shape[1]), importances[indices], color='r', yerr=std[indices], align='center') plt.xticks(range(X.shape[1]), indices) plt.xlim([-1, X.shape[1]]) plt.show()
python分析重要性的几个工具
Permuation Importance,Partial Dependence Plots,SHAP Values,Summary Plots
对于非深度学习特征重要性评估(筛选),可以在训练预测之前进行数据的清洗,特征筛选;也可以在训练过程中对特征进行筛选,通常为与决策树相关的算法(RF,xgboost等)。回归任务使用特征的系数作为特征重要性的判断依据。
这是暂时整理的方法概要,后续会查阅深度学习方法中相关的特征重要性评估方法。
参考:
https://www.cnblogs.com/nxf-rabbit75/p/11122415.html
https://www.cnblogs.com/nxf-rabbit75/p/11159320.html
https://www.cnblogs.com/nxf-rabbit75/p/11125001.html
https://www.dazhuanlan.com/2020/01/17/5e20e2321c9df/
https://www.dazhuanlan.com/2020/01/17/5e20e2321c9df/
https://www.jianshu.com/p/1c4ec02dd33f
https://blog.csdn.net/qq_38844711/article/details/103518857
https://www.zhihu.com/question/296523764?sort=created
https://www.zhihu.com/question/319953307
更多相关内容 -
机器学习模型可解释性进行到底——特征重要性(四)
2021-04-13 22:13:33文章目录1 四种全局可解释的方法论1.1 过滤法1.1.1 方差过滤方差过滤1.1.2 相关性过滤1.2 嵌入法1.2.1 SelectFromModel - 筛选特征1.2.2 PermutationImportance - 排列重要性1.3 包装法1.4 几种方法对比1.5 额外的...
可参考另外几篇:
1 四种全局可解释的方法论
全局可解释代表着,是判定、选择某个特征的方法,包括:过滤法,嵌入法,包装法,和降维算法。
其中,嵌入法最为熟知,包括了特征重要性。参考文章[2] [7]
1.1 过滤法
过滤法选择特征,其主要思想是:对每一维的特征“打分”,即给每一维的特征赋予权重,这样的权重就代表着该维特征的重要性,然后依据权重排序。
1.1.1 方差过滤方差过滤
文章[11]也提到,特征选择时,主要遵循如下两个原则:
- 波动性
- 相关性
波动性是指该特征取值发生变化的情况,用方差来衡量,如果方差很小,说明该特征的取值很稳定,可以近似理解成该特征的每个值都接近,这样的特征对模型是没有任何效果,是不具备区分度的,比如年龄这个特征,都是20岁左右大小的。反之,方差越大,则特征对模型的区分度越好。
相关性是就是该特征和目标结果的相关性大小,常用皮尔逊相关系数来度量。
过滤法的主要对象是:需要遍历特征或升维的算法们,
而过滤法的主要目的是:在维持算法表现的前提下,帮助算法们降低计算成本。随机森林运行时间与特征数无关(每次都直选几十个特征),决策树与特征数有关(一次建模需要挑选很多特征),其他想svm、KNN等的运行时间更是与特征数量相关
方差过滤不能保证模型效果变好,但能保证运行时间的降低。方差过滤中的超参数threshold可以通过画学习曲线来找到最好的点,但是一般不太这么做,因为计算量太大了。
1.1.2 相关性过滤
1.2 嵌入法
嵌入法选择特征,其主要思想是:在模型既定的情况下学习出对提高模型准确性最好的属性。这句话并不是很好理解,其实是讲在确定模型的过程中,挑选出那些对模型的训练有重要意义的属性。
最常用的是使用L1正则化和L2正则化来选择特征如Ridge Regression。正则化惩罚项越大,那么模型的系数就会越小。
当正则化惩罚项大到一定的程度的时候,部分特征系数会变成0,当正则化惩罚项继续增大到一定程度时,所有的特征系数都会趋于0. 但是我们会发现一部分特征系数会更容易先变成0,这部分系数就是可以筛掉的。
也就是说,我们选择特征系数较大的特征。1.2.1 SelectFromModel - 筛选特征
feature_selection.SelectFromModel从模型选择
sklearn在Feature selection模块中内置了一个SelectFromModel,该模型可以通过Model本身给出的指标对特征进行选择,其作用与其名字高度一致,
select (feature) from model
。
SelectFromModel
是一个通用转换器,其需要的Model只需要带有conef_
或者feature_importances
属性,那么就可以作为SelectFromModel
的Model来使用. 如果相关的coef_
或者featureimportances
属性值低于预先设置的阈值,这些特征将会被认为不重要并且移除掉。
除了指定数值上的阈值之外,还可以通过给定字符串参数来使用内置的启发式方法找到一个合适的阈值。可以使用的启发式方法有 mean 、 median 以及使用浮点数乘以这些(例如,0.1*mean
)。与threshold标准结合使用时,可以使用 max_features参数设置对要选择的要素数量的限制
函数包括(参考文章[3]):
class sklearn.feature_selection.SelectFromModel(estimator, *, threshold=None, prefit=False, norm_order=1, max_features=None)
简单案例:
# https://www.cnblogs.com/cgmcoding/p/13588878.html from sklearn.svm import LinearSVC from sklearn.datasets import load_iris from sklearn.feature_selection import SelectFromModel X, y = load_iris(return_X_y=True) X.shape # (150, 4) lsvc = LinearSVC(C=0.01, penalty="l1", dual=False).fit(X, y) model = SelectFromModel(lsvc, prefit=True) #已经fit过了,所以必须带上参数prefit X_new = model.transform(X) X_new.shape #(150, 3)
可选参数:
- (1)estimator: object,用来构建变压器的基本估算器。既可以是拟合的(如果prefit设置为True),也可以是不拟合的估计量。拟合后,估计量必须具有 feature_importances_或coef_属性
- (2)threshold: str, float, optional default None,用于特征选择的阈值。保留重要性更高或相等的要素,而其他要素则被丢弃。如果为“中位数”(分别为“均值”),则该threshold值为特征重要性的中位数(分别为均值)。也可以使用缩放因子(例如,“ 1.25 *平均值”)。如果为None(无),并且估计器的参数惩罚显式或隐式设置为l1(例如Lasso),则使用的阈值为1e-5。否则,默认情况下使用“平均值”
- (3)prefit: bool, default False,预设模型是否期望直接传递给构造函数。如果为True,transform必须直接调用和SelectFromModel不能使用cross_val_score, GridSearchCV而且克隆估计类似的实用程序。否则,使用训练模型fit,然后transform进行特征选择。
- (4)norm_order: 非零 int, inf, -inf, default 1,在估算器threshold的coef_属性为维度2 的情况下,用于过滤以下系数矢量的范数的顺序 ,正则化
- (5)max_features:int or None, optional,要选择的最大功能数。若要仅基于选择max_features,请设置threshold=-np.inf
属性:
- estimator_:一个估算器,用来建立变压器的基本估计器。只有当一个不适合的估计器传递给SelectFromModel时,才会存储这个值,即当prefit为False时。
- threshold_:float,用于特征选择的阈值
方法:
- fit(X [,y])适合SelectFromModel元变压器。
- fit_transform(X [,y])适合数据,然后对其进行转换。
- get_params([deep])获取此估计量的参数。
- get_support([index])获取所选特征的掩码或整数索引
- inverse_transform(X)反向转换操作
- partial_fit(X [,y])仅将SelectFromModel元变压器安装一次。
- set_params(**参数)设置此估算器的参数。
- transform(X)将X缩小为选定的特征。
1.2.2 PermutationImportance - 排列重要性
文章[12][13]提及了PermutationImportance。
文档对该方法介绍如下:
eli5 provides a way to compute feature importances for any black-box estimator by measuring how score decreases when a feature is not available; the method is also known as “permutation importance” or “Mean Decrease Accuracy (MDA)”.
我的理解是:若将一个特征置为随机数,模型效果下降很多,说明该特征比较重要;反之则不是。
简单来说,就是改变数据表格中某一列的数据的排列,保持其余特征不动,看其对预测精度的影响有多大。
计算步骤:
1、用上全部特征,训练一个模型。
2、验证集预测得到得分。
3、验证集的一个特征列的值进行随机打乱,预测得到得分。
4、将上述得分做差即可得到特征x1对预测的影响。
5、依次将每一列特征按上述方法做,得到每二个特征对预测的影响。结果分析:
- 靠近上方的绿色特征,表示对模型预测较为重要的特征;
- 为了排除随机性,每一次 shuffle 都会进行多次,然后取结果的均值和标准差;
- ±后面的数字表示多次随机重排之间的差异值。
- 这个例子里,最重要的特征是第三个 ‘petal length (cm)’, 和feature_importances_输出结果一致。
在文章[12]中得实验来看,
全部特征、RF前30特征、LightGBM前30特征、LR前30特征。可以看到LightGBM通过PermutationImportance选出来的30个特征的模型的泛化性要好于用全部变量建模。1.3 包装法
包装法选择特征,其主要思想是:将子集的选择看作是一个搜索寻优问题,生成不同的组合,对组合进行评价,再与其他的组合进行比较。这样就将子集的选择看作是一个是一个优化问题,这里有很多的优化算法可以解决,尤其是一些启发式的优化算法,如GA,PSO,DE,ABC等
主要的方式:
- 递归消除特征法(recursive feature elimination,简称RFE ),递归消除特征法的主要过程是,采用一个机器学习模型进行多次的训练,每一次的训练,都会消除若干部分权重系数的特征,然后再采用新的一组训练集进行训练。如条件互信息等。
- 递归过程可以是前向的或者后向的以及前后结合的。
- 常用的特征子集搜索算法还有:完全搜索;基于贪心的启发式搜索(前向/后向搜索等);随机搜索(模拟退火、遗传算法等)。
1.4 几种方法对比
计算成本:
嵌入>包装>过滤
经验来说,过滤法更快速,但更粗糙。
包装法和嵌入法更精确,比较适合具体到算法去调整,但计算量比较大,运行时间长。
当数据量很大的时候,优先使用方差过滤和互信息法调整,再上其他特征选择方法。
使用逻辑回归时,优先使用嵌入法。使用支持向量机时,优先使用包装法。各类特征选择方法的优缺点
1.5 额外的交叉特征筛选模型:AutoFIS
一篇文章里面的特征选择方法:Automatic Feature Interaction Selection(AutoFIS)。
推荐和广告系统中特征交叉非常重要,设计得当通常能获得巨大的提升。
虽然现在已经由一些模型来做部分的自动特征组合交叉,如xDeepFM,DeepCross,PNN,DIN等等,但是出于性能以及简便考虑,通常我们还是手动或者枚举着进行特征选择。
这篇文章的出发点是提出一种方法来进行特征交叉的选择,达到减少冗余交叉降低噪声,使训练更容易,进而提升效果的目的。
文章号称AutoFIS能自动地识别factorization模型中的所有重要的特征交互,而计算量和训练目标模型到收敛差不多。
2 SHAP(SHapley Additive exPlanation)
可参考另外几篇:
文章[13]
来看一下SHAP模型,是比较全能的模型可解释性的方法,既可作用于之前的全局解释,也可以局部解释,即单个样本来看,模型给出的预测值和某些特征可能的关系,这就可以用到SHAP。SHAP 属于模型事后解释的方法,它的核心思想是计算特征对模型输出的边际贡献,再从全局和局部两个层面对“黑盒模型”进行解释。SHAP构建一个加性的解释模型,所有的特征都视为“贡献者”。
对于每个预测样本,模型都产生一个预测值,SHAP value就是该样本中每个特征所分配到的数值。
基本思想:计算一个特征加入到模型时的边际贡献,然后考虑到该特征在所有的特征序列的情况下不同的边际贡献,取均值,即某该特征的SHAPbaseline value2.1 SHAP 与 Permutation importance 的差异
文章[8]提及:
Permutation importance
很不错,因为它用很简单的数字就可以衡量特征对模型的重要性。但是它不能handle这么一种情况:当一个feature有中等的permutation importance的时候,这可能意味着这么两种情况:
1:对少量的预测有很大的影响,但是整体来说影响较小;
2:对所有的预测都有中等程度的影响。SHAP 就可以应用的上,来看一下SHAP呈现的几种图,本轮笔者 是直接拿slundberg/shap中的代码,发现
0.39.0
版本,跟之前的版本差异非常大,很多函数名称都发生了变化。笔者实验下述代码的环境:
anaconda + py3.7 + jupyter notebook + shap==0.39.0
pip install shap or conda install -c conda-forge shap
那就从拆解当下slundberg/shap的案例入手,开始解读SHAP值的各类神图:
2.2 特征归因的一致性
2.2.1 树模型importance的不稳定
在文章[附代码!视频点击预测大赛初赛第二名方案 ]
通过训练模型发现,存在大量的原始特征,特征的重要性为0,然后对这些特征重要性为0的数据进行了删除。
在训练模型的时候发现,lightgbm和XGBoost的特征重要性差别非常大,所以我们对这两个模型的特征重要性进行了求和。
同时,获取特征重要性的不同方式,也会对特征重要性有所影响。在某种方式下重要性较低,另一种方式下可能会比较高,所以我们同样考虑到使用多种不同的特征重要性的获取方式。
2.2.2 SHAP值是唯一一致的个性化特征归因方法
文章:SHAP知识点全汇总
一致性:每当我们更改模型以使其更依赖于某个特征时,该特征的归因重要性不应该降低。
如果一致性不成立,意味着当一个模型被更改为某个特征对模型输出的影响更大时,反而会降低该特征的重要性,那么我们不能比较任意两个模型之间的归因重要性,因为具有较高分配归因的特征并不意味着模型实际上更依赖该特征。下面举两个模型的例子对归因方法的一致性进行比较,假设模型的输出是基于人的症状的风险评分,对于二元特征发烧(Fever)和咳嗽(Cough),模型A只是一个简单的"和"函数,模型B是相同的函数,但是当为咳嗽时预测值会增加(加10分),使得模型更依赖于咳嗽,这时因咳嗽更重要,导致在模型B中咳嗽先分裂。
比较A、B模型在下面六种归因方法上的差别:
- Tree SHAP,本文提出的一种新的个性化方法。(个性化特征归因方法,为单个预测计算)
- Saabas,个性化的启发式特征归因方法。(个性化特征归因方法,为单个预测计算)
- mean(|Tree SHAP |),基于个性化Tree SHAP归因的平均幅度的全局归因方法(全局特征归因方法,为整个数据集计算,实际为所有样本的Tree SHAP值按照特征计算均值)
- 增益(全局特征归因方法,为整个数据集计算)
- 分裂数(全局特征归因方法,为整个数据集计算)
- 置换(全局特征归因方法,为整个数据集计算)
个性化特征归因方法:Tree SHAP、Sabbas,只有SHAP值能够保证反映特征的重要性,而Saabas值可能会给出错误的结果,比如模型B中认为更大的原因是发烧,而不是咳嗽,这是不一致的表现。
全局特征归因方法:mean(|Tree SHAP |)、增益、分裂数和特征置换,只有mean(|Tree SHAP |)和置换认为模型B咳嗽比发烧更重要,这意味着在一致性上增益和分裂数不是全局特性重要性的可靠度量。
所以gain、split count和Saabas方法中的特征重要度都不一致(使B模型更加依赖咳嗽时,却认为发烧更重要),这意味着模型改变为更多地依赖于给定的特性时,分配给该特征的重要性却降低了。
通常我们期望树根附近的特征比在叶子附近分裂的特征更重要(因为树是贪婪地构造的),然而增益方法偏向于更重视较低的分裂,这种偏差会导致不一致,当咳嗽变得更加重要时(因此在根部分裂),其归因重要性实际上下降。
个性化的Saabas方法在我们下降树时计算预测的差异,因此它也会受到与树中较低分割相同的偏差,随着树木越来越深,这种偏差只会增长。
相比之下,Tree SHAP方法在数学上等效于平均所有可能的特征排序的预测差异,而不仅仅是它们在树中的位置指定的排序。
所以在我们考虑的方法中,只有SHAP值和置换的方法是具有一致性的,而其中又只有SHAP值是个性化的,所以SHAP值是唯一一致的个性化特征归因方法。
3 工业案例
3.1 ML平台中 特征重要性
文章[干货 | 用户画像在携程商旅的实践] 提到,用户画像标签体系的数据监控中,会把特征重要性也作为监控指标,
在特征计算阶段,需要监控各数值特征的统计值(最大值、最小值、均值、标准差等)是否在合理区间内、
类别特征是否不在枚举范围内、特征重要性(方差、卡方、信息增益)监控。
如一个指标在前三个月属于重要性的指标,随着业务变化,该指标的重要性已经降低了,
以此来指导模型迭代(特征选择、超参数调整)。3.2 一些比赛经验
文章[消费金融场景下的用户购买预测【冠军方案】分享]提到,
特征选择:
基于XGB的特征重要性
先训练一个XGBoost模型,输出其特征重要性,然后将重要性为0的特征删除,即完成了特征选择。
基于wrapper的方式
基于贪心算法,寻找最优特征子集,如上图所示。
参考文献
1 数据科学竞赛:你从未见过的究极进化秘笈
2 sklearn之特征工程
3 sklearn.feature_selection.SelectFromModel 特征重要性选择(嵌入法的一种)
4 官方 1.13.4. Feature selection using SelectFromModel
5 干货 | 用户画像在携程商旅的实践
6 消费金融场景下的用户购买预测【冠军方案】分享
7 笔记:机器学习中的特征选择 一
8 kaggle | Machine Learning for Insights Challenge
9 特征选择怎么做?这篇文章告诉你
10 AutoML:mljar-supervised
11 机器学习中的特征选择
12 利用PermutationImportance挑选变量
13 可解释性机器学习_Feature Importance、Permutation Importance、SHAP -
如何用Python计算特征重要性?
2020-07-07 16:10:07特征重要性有许多类型和来源,尽管有许多比较常见,比如说统计相关性得分,线性模型的部分系数,基于决策树的特征重要性和经过随机排序得到重要性得分。 特征重要性在预测建模项目中起着重要作用,包括提供对数据、...特征重要性评分是一种为输入特征评分的手段,其依据是输入特征在预测目标变量过程中的有用程度。
特征重要性有许多类型和来源,尽管有许多比较常见,比如说统计相关性得分,线性模型的部分系数,基于决策树的特征重要性和经过随机排序得到重要性得分。
特征重要性在预测建模项目中起着重要作用,包括提供对数据、模型的见解,以及如何降维和选择特征,从而提高预测模型的的效率和有效性。
在本教程中,我将会阐述用于python机器学习的特征重要性。完成本教程后,你将会知道:
- 特征重要性在预测建模中的作用
- 如何计算和查看来自线性模型和决策树的特征重要性
- 如何计算和查看随机排序重要性得分
现在让我们开始吧.
教程概述
本教程分为五部分,分别是:
1.特征重要性
2.准备
2.1. 检查Scikit-Learn版本
2.2. 创建测试数据集
3.特征重要性系数
3.1. 基于线性回归系数的特征重要性
3.2. 基于Logistic回归的特征重要性
4.基于决策树的特征重要性
4.1. 基于CART的特征重要性
4.2. 基于随机森林的特征重要性
4.3. 基于XGBoost的特征重要性
5.随机排序特征重要性
5.1. 随机排序(回归)中的特征重要性
5.2. 随机排序(分类)中的特征重要性
1.特征重要性
特征重要性是一种为预测模型的输入特征评分的方法,该方法揭示了进行预测时每个特征的相对重要性。
可以为涉及预测数值的问题(称为回归)和涉及预测类别标签的问题(称为分类)计算特征重要性得分。
这些得分非常有用,可用于预测建模问题中的多种情况,例如:
- 更好地理解数据
- 更好地理解模型
- 减少输入特征的数量
特征重要性得分可以帮助了解数据集
相对得分可以突出显示哪些特征可能与目标最相关,反之则突出哪些特征最不相关。这可以由一个领域专家解释,并且可以用作收集更多的或不同的数据的基础。
特征重要性得分可以帮助了解模型
大多数重要性得分是通过数据集拟合出的预测模型计算的。查看重要性得分可以洞悉该特定模型,以及知道在进行预测时哪些特征最重要和哪些最不重要。这是一种模型解释,适用于那些支持它的模型。
特征重要性可用于改进预测模型
可以使用的重要性得分来选择要删除的特征(最低得分)或要保留的特征(最高得分)。这是一种特征选择,可以简化正在建模的问题,加快建模过程(删除特征称为降维),在某些情况下,还可以改善模型的性能。
特征重要性得分可以被输入到包装器模型,如SelectFromModel或SelectKBest,以进行特征选择。
有许多方法和模型可以计算特征重要性得分。
也许最简单的方法是计算每个特征和目标变量之间的统计学相关系数。
在本教程中,我们将研究三种比较高级的特征重要性,即:
- 从模型系数得知的特征重要性。
- 决策树中的特征重要性。
- 随机排序检验中的特征重要性。
现在让我们深入了解这三个!
2.准备
在深入学习之前,我们先确认我们的环境并准备一些测试数据集。
检查Scikit-Learn版本
首先,确认你已安装最新版本的scikit-learn库。这非常重要,因为在本教程中,我们我们研究的一些模型需要最新版的库。
您可以使用以下示例代码来查看已安装的库的版本:
- # check scikit-learn version
- import sklearn
- print(sklearn.__version__)
运行示例代码将会打印出库的版本。在撰写本文时,大概是version 0.22。你需要使用此版本或更高版本的scikit-learn。
- 0.22.1
生成测试数据集
接下来,让我们生成一些测试数据集,这些数据集可以作为基础来证明和探索特征重要性得分。每个测试问题有五个重要特征和五不重要的特征,看看哪种方法可以根据其重要性找到或区分特征可能会比较有意思。
分类数据集
我们将使用make_classification()函数创建一个用于测试的二进制分类数据集。
数据集将包含1000个实例,且包含10个输入特征,其中五个将会提供信息,其余五个是多余的。
为了确保每次运行代码时都得到相同的实例,我们将使用假随机数种子。下面列出了创建数据集的示例。
- # test classification dataset
- from sklearn.datasets import make_classification
- # define dataset
- X, y = make_classification(n_samples=1000, n_features=10, n_informative=5, n_redundant=5, random_state=1)
- # summarize the dataset
- print(X.shape, y.shape)
运行示例,创建数据集,并确保所需的样本和特征数量。
- (1000, 10) (1000,)
回归数据集
我们将使用make_regression()函数创建一个用于测试的回归数据集。
像分类数据集一样,回归数据集将包含1000个实例,且包含10个输入特征,其中五个将会提供信息,其余五个是多余的。
- # test regression dataset
- from sklearn.datasets import make_regression
- # define dataset
- X, y = make_regression(n_samples=1000, n_features=10, n_informative=5, random_state=1)
- # summarize the dataset
- print(X.shape, y.shape)
运行示例,创建数据集,并确保所需的样本和特征数量。
- (1000, 10) (1000,)
接下来,我们仔细看一下特征重要性系数。
3.特征重要性系数
线性的机器学习能够拟合出预测是输入值的加权和的模型。
案例包括线性回归,逻辑回归,和正则化的扩展案例,如岭回归和弹性网络。
所有这些算法都是找到一组要在加权求和中使用的系数,以便进行预测。这些系数可以直接用作粗略类型的特征重要性得分。
我们来仔细研究一下分类和回归中的特征重要性系数。我们将在数据集中拟合出一个模型以找到系数,然后计算每个输入特征的重要性得分,最终创建一个条形图来了解特征的相对重要性。
3.1线性回归特征重要性
我们可以在回归数据集中拟合出一个LinearRegression模型,并检索coeff_属性,该属性包含为每个输入变量(特征)找到的系数。这些系数可以为粗略特征重要性评分提供依据。该模型假设输入变量具有相同的比例或者在拟合模型之前已被按比例缩放。
下面列出了针对特征重要性的线性回归系数的完整示例。
- # linear regression feature importance
- from sklearn.datasets import make_regression
- from sklearn.linear_model import LinearRegression
- from matplotlib import pyplot
- # define dataset
- X, y = make_regression(n_samples=1000, n_features=10, n_informative=5, random_state=1)
- # define the model
- model = LinearRegression()
- # fit the model
- model.fit(X, y)
- # get importance
- importance = model.coef_
- # summarize feature importance
- for i,v in enumerate(importance):
- print('Feature: %0d, Score: %.5f' % (i,v))
- # plot feature importance
- pyplot.bar([x for x in range(len(importance))], importance)
- pyplot.show()
运行示例,拟合模型,然后输出每个特征的系数值。
得分表明,模型找到了五个重要特征,并用零标记了剩下的特征,实际上,将他们从模型中去除了。
- Feature: 0, Score: 0.00000
- Feature: 1, Score: 12.44483
- Feature: 2, Score: -0.00000
- Feature: 3, Score: -0.00000
- Feature: 4, Score: 93.32225
- Feature: 5, Score: 86.50811
- Feature: 6, Score: 26.74607
- Feature: 7, Score: 3.28535
- Feature: 8, Score: -0.00000
- Feature: 9, Score: 0.00000
然后为特征重要性得分创建条形图。
这种方法也可以用于岭回归和弹性网络模型。
3.2 Logistic回归特征重要性
就像线性回归模型一样,我们也可以在回归数据集中拟合出一个LogisticRegression模型,并检索coeff_属性。这些系数可以为粗略特征重要性评分提供依据。该模型假设输入变量具有相同的比例或者在拟合模型之前已被按比例缩放。
下面列出了针对特征重要性的Logistic回归系数的完整示例。
- # logistic regression for feature importance
- from sklearn.datasets import make_classification
- from sklearn.linear_model import LogisticRegression
- from matplotlib import pyplot
- # define dataset
- X, y = make_classification(n_samples=1000, n_features=10, n_informative=5, n_redundant=5, random_state=1)
- # define the model
- model = LogisticRegression()
- # fit the model
- model.fit(X, y)
- # get importance
- importance = model.coef_[0]
- # summarize feature importance
- for i,v in enumerate(importance):
- print('Feature: %0d, Score: %.5f' % (i,v))
- # plot feature importance
- pyplot.bar([x for x in range(len(importance))], importance)
- pyplot.show()
运行示例,拟合模型,然后输出每个特征的系数值。
回想一下,这是有关0和1的分类问题。请注意系数既可以为正,也可以为负。正数表示预测类别1的特征,而负数表示预测类别0的特征。
从这些结果,至少从我所知道的结果中,无法清晰的确定出重要和不重要特征。
- Feature: 0, Score: 0.16320
- Feature: 1, Score: -0.64301
- Feature: 2, Score: 0.48497
- Feature: 3, Score: -0.46190
- Feature: 4, Score: 0.18432
- Feature: 5, Score: -0.11978
- Feature: 6, Score: -0.40602
- Feature: 7, Score: 0.03772
- Feature: 8, Score: -0.51785
- Feature: 9, Score: 0.26540
然后为特征重要性得分创建条形图。
现在我们已经看到了将系数用作重要性得分的示例,接下来让我们看向基于决策树的重要性得分的常见示例
4.基于决策树的特征重要性
决策树算法,比如说classification and regression trees(CART)根据Gini系数或熵的减少来提供重要性得分。这个方法也可用于随机森林和梯度提升算法。
OK.现在让我们看看相应的运行示例。
4.1基于CART的特征重要性
对于在scikit-learn中实现的特征重要性,我们可以将CART算法用于DecisionTreeRegressor和DecisionTreeClassifier类
拟合后,模型提供feature_importances_属性,可以访问该属性以检索每个输入特征的相对重要性得分。
让我们看一个用于回归和分类的示例。
基于CART(回归)的特征重要性
下面列出了拟合DecisionTreeRegressor和计算特征重要性得分的完整示例。
- # decision tree for feature importance on a regression problem
- from sklearn.datasets import make_regression
- from sklearn.tree import DecisionTreeRegressor
- from matplotlib import pyplot
- # define dataset
- X, y = make_regression(n_samples=1000, n_features=10, n_informative=5, random_state=1)
- # define the model
- model = DecisionTreeRegressor()
- # fit the model
- model.fit(X, y)
- # get importance
- importance = model.feature_importances_
- # summarize feature importance
- for i,v in enumerate(importance):
- print('Feature: %0d, Score: %.5f' % (i,v))
- # plot feature importance
- pyplot.bar([x for x in range(len(importance))], importance)
- pyplot.show()
运行示例,拟合模型,然后输出每个特征的系数值。
结果表明,这十个特征中的三个可能对预测很重要。
- Feature: 0, Score: 0.00294
- Feature: 1, Score: 0.00502
- Feature: 2, Score: 0.00318
- Feature: 3, Score: 0.00151
- Feature: 4, Score: 0.51648
- Feature: 5, Score: 0.43814
- Feature: 6, Score: 0.02723
- Feature: 7, Score: 0.00200
- Feature: 8, Score: 0.00244
- Feature: 9, Score: 0.00106
然后为特征重要性得分创建条形图。
基于CART(分类)的特征重要性
下面列出了拟合DecisionTreeClassifier和计算特征重要性得分的完整示例
- # decision tree for feature importance on a classification problem
- from sklearn.datasets import make_classification
- from sklearn.tree import DecisionTreeClassifier
- from matplotlib import pyplot
- # define dataset
- X, y = make_classification(n_samples=1000, n_features=10, n_informative=5, n_redundant=5, random_state=1)
- # define the model
- model = DecisionTreeClassifier()
- # fit the model
- model.fit(X, y)
- # get importance
- importance = model.feature_importances_
- # summarize feature importance
- for i,v in enumerate(importance):
- print('Feature: %0d, Score: %.5f' % (i,v))
- # plot feature importance
- pyplot.bar([x for x in range(len(importance))], importance)
- pyplot.show()
运行示例,拟合模型,然后输出每个特征的系数值。
结果表明,这十个特征中的四个可能对预测很重要。
- Feature: 0, Score: 0.01486
- Feature: 1, Score: 0.01029
- Feature: 2, Score: 0.18347
- Feature: 3, Score: 0.30295
- Feature: 4, Score: 0.08124
- Feature: 5, Score: 0.00600
- Feature: 6, Score: 0.19646
- Feature: 7, Score: 0.02908
- Feature: 8, Score: 0.12820
- Feature: 9, Score: 0.04745
然后为特征重要性得分创建条形图。
4.2随机森林中的特征重要性
对于在scikit-learn中实现的特征重要性,我们可以将Random Forest算法用于DecisionTreeRegressor和DecisionTreeClassifier类。
拟合后,模型提供feature_importances_属性,可以访问该属性以检索每个输入特征的相对重要性得分。
这种方法也可以与装袋和极端随机树(extraTree)算法一起使用。
让我们看一个用于回归和分类的示例。
随机森林(回归)中的特征重要性
下面列出了拟合RandomForestRegressor和计算特征重要性得分的完整示例
- # random forest for feature importance on a regression problem
- from sklearn.datasets import make_regression
- from sklearn.ensemble import RandomForestRegressor
- from matplotlib import pyplot
- # define dataset
- X, y = make_regression(n_samples=1000, n_features=10, n_informative=5, random_state=1)
- # define the model
- model = RandomForestRegressor()
- # fit the model
- model.fit(X, y)
- # get importance
- importance = model.feature_importances_
- # summarize feature importance
- for i,v in enumerate(importance):
- print('Feature: %0d, Score: %.5f' % (i,v))
- # plot feature importance
- pyplot.bar([x for x in range(len(importance))], importance)
- pyplot.show()
运行示例,拟合模型,然后输出每个特征的系数值。
结果表明,这十个特征中的两个或三个可能对预测很重要。
- Feature: 0, Score: 0.00280
- Feature: 1, Score: 0.00545
- Feature: 2, Score: 0.00294
- Feature: 3, Score: 0.00289
- Feature: 4, Score: 0.52992
- Feature: 5, Score: 0.42046
- Feature: 6, Score: 0.02663
- Feature: 7, Score: 0.00304
- Feature: 8, Score: 0.00304
- Feature: 9, Score: 0.00283
然后为特征重要性得分创建条形图。
随机森林(分类)中的特征重要性
下面列出了拟合RandomForestClassifier和计算特征重要性得分的完整示例
- # random forest for feature importance on a classification problem
- from sklearn.datasets import make_classification
- from sklearn.ensemble import RandomForestClassifier
- from matplotlib import pyplot
- # define dataset
- X, y = make_classification(n_samples=1000, n_features=10, n_informative=5, n_redundant=5, random_state=1)
- # define the model
- model = RandomForestClassifier()
- # fit the model
- model.fit(X, y)
- # get importance
- importance = model.feature_importances_
- # summarize feature importance
- for i,v in enumerate(importance):
- print('Feature: %0d, Score: %.5f' % (i,v))
- # plot feature importance
- pyplot.bar([x for x in range(len(importance))], importance)
- pyplot.show()
运行示例,拟合模型,然后输出每个特征的系数值。
结果表明,这十个特征中的两个或三个可能对预测很重要。
- Feature: 0, Score: 0.06523
- Feature: 1, Score: 0.10737
- Feature: 2, Score: 0.15779
- Feature: 3, Score: 0.20422
- Feature: 4, Score: 0.08709
- Feature: 5, Score: 0.09948
- Feature: 6, Score: 0.10009
- Feature: 7, Score: 0.04551
- Feature: 8, Score: 0.08830
- Feature: 9, Score: 0.04493
然后为特征重要性得分创建条形图。
4.3基于XGBoost的特征重要性
XGBoost是一个库,它提供了随机梯度提升算法的高效实现。可以通过XGBRegressor和XGBClassifier类将此算法与scikit-learn一起使用。
拟合后,模型提供feature_importances_属性,可以访问该属性以检索每个输入特征的相对重要性得分。
scikit-learn还通过GradientBoostingClassifier和GradientBoostingRegressor提供了该算法,并且可以使用相同的特征选择方法
首先,安装XGBoost库,例如:
- sudo pip install xgboost
然后,通过检查版本号来确认该库已正确安装并且可以正常工作。
- # check xgboost version
- import xgboost
- print(xgboost.__version__)
运行该示例,你应该看到以下版本号或者更高版本。
- 0.90
有关XGBoost库的更多信息,请看:
- XGBoost with Python
让我们看一个用于回归和分类问题的示例。
基于XGBoost(回归)的特征重要性
下面列出了拟合XGBRegressor并且计算特征重要性得分的完整示例
- # xgboost for feature importance on a regression problem
- from sklearn.datasets import make_regression
- from xgboost import XGBRegressor
- from matplotlib import pyplot
- # define dataset
- X, y = make_regression(n_samples=1000, n_features=10, n_informative=5, random_state=1)
- # define the model
- model = XGBRegressor()
- # fit the model
- model.fit(X, y)
- # get importance
- importance = model.feature_importances_
- # summarize feature importance
- for i,v in enumerate(importance):
- print('Feature: %0d, Score: %.5f' % (i,v))
- # plot feature importance
- pyplot.bar([x for x in range(len(importance))], importance)
- pyplot.show()
运行示例,拟合模型,然后输出每个特征的系数值。
结果表明,这十个特征中的两个或三个可能对预测很重要。
- Feature: 0, Score: 0.00060
- Feature: 1, Score: 0.01917
- Feature: 2, Score: 0.00091
- Feature: 3, Score: 0.00118
- Feature: 4, Score: 0.49380
- Feature: 5, Score: 0.42342
- Feature: 6, Score: 0.05057
- Feature: 7, Score: 0.00419
- Feature: 8, Score: 0.00124
- Feature: 9, Score: 0.00491
然后为特征重要性得分创建条形图。
基于XGBoost(分类)的特征重要性
下面列出了拟合XGBClassifier并且计算特征重要性得分的完整示例
- # xgboost for feature importance on a classification problem
- from sklearn.datasets import make_classification
- from xgboost import XGBClassifier
- from matplotlib import pyplot
- # define dataset
- X, y = make_classification(n_samples=1000, n_features=10, n_informative=5, n_redundant=5, random_state=1)
- # define the model
- model = XGBClassifier()
- # fit the model
- model.fit(X, y)
- # get importance
- importance = model.feature_importances_
- # summarize feature importance
- for i,v in enumerate(importance):
- print('Feature: %0d, Score: %.5f' % (i,v))
- # plot feature importance
- pyplot.bar([x for x in range(len(importance))], importance)
- pyplot.show()
运行示例,拟合模型,然后输出每个特征的系数值。
结果表明,这十个特征中有七个可能对预测很重要。
- Feature: 0, Score: 0.02464
- Feature: 1, Score: 0.08153
- Feature: 2, Score: 0.12516
- Feature: 3, Score: 0.28400
- Feature: 4, Score: 0.12694
- Feature: 5, Score: 0.10752
- Feature: 6, Score: 0.08624
- Feature: 7, Score: 0.04820
- Feature: 8, Score: 0.09357
- Feature: 9, Score: 0.02220
然后为特征重要性得分创建条形图。
5.基于随机排序的特征重要性
随机排序特征重要性(Permutation feature importance)可以计算相对重要性,与所使用的模型无关。
首先,在数据集中拟合出一个模型,比如说一个不支持本地特征重要性评分的模型。然后,尽管对数据集中的特征值进行了干扰,但仍可以使用该模型进行预测。对数据集中的每个特征进行此操作。然后,再将整个流程重新操作3、5、10或更多次。我们得到每个输入特征的平均重要性得分(以及在重复的情况下得分的分布)。
此方法可以用于回归或分类,要求选择性能指标作为重要性得分的基础,例如回归中的均方误差和分类中的准确性。
可以通过permutation_importance()函数(以模型和数据集为参数)和评分函数进行随机排序特性选择。
让我们看下这个特征选择方法,其算法并不支持特征选择,尤其是k近邻算法( k-nearest neighbors)。
5.1随机排序(回归)特征重要性
下面列出了拟合KNeighborsRegressor并且计算特征重要性得分的完整示例。
- # permutation feature importance with knn for regression
- from sklearn.datasets import make_regression
- from sklearn.neighbors import KNeighborsRegressor
- from sklearn.inspection import permutation_importance
- from matplotlib import pyplot
- # define dataset
- X, y = make_regression(n_samples=1000, n_features=10, n_informative=5, random_state=1)
- # define the model
- model = KNeighborsRegressor()
- # fit the model
- model.fit(X, y)
- # perform permutation importance
- results = permutation_importance(model, X, y, scoring='neg_mean_squared_error')
- # get importance
- importance = results.importances_mean
- # summarize feature importance
- for i,v in enumerate(importance):
- print('Feature: %0d, Score: %.5f' % (i,v))
- # plot feature importance
- pyplot.bar([x for x in range(len(importance))], importance)
- pyplot.show()
运行示例,拟合模型,然后输出每个特征的系数值。
结果表明,这十个特征中的两个或三个可能对预测很重要。
- Feature: 0, Score: 175.52007
- Feature: 1, Score: 345.80170
- Feature: 2, Score: 126.60578
- Feature: 3, Score: 95.90081
- Feature: 4, Score: 9666.16446
- Feature: 5, Score: 8036.79033
- Feature: 6, Score: 929.58517
- Feature: 7, Score: 139.67416
- Feature: 8, Score: 132.06246
- Feature: 9, Score: 84.94768
然后为特征重要性得分创建条形图。
5.2随机排序(分类)特征重要性
下面列出了拟合KNeighborsClassifier并且计算特征重要性得分的完整示例。
- # permutation feature importance with knn for classification
- from sklearn.datasets import make_classification
- from sklearn.neighbors import KNeighborsClassifier
- from sklearn.inspection import permutation_importance
- from matplotlib import pyplot
- # define dataset
- X, y = make_classification(n_samples=1000, n_features=10, n_informative=5, n_redundant=5, random_state=1)
- # define the model
- model = KNeighborsClassifier()
- # fit the model
- model.fit(X, y)
- # perform permutation importance
- results = permutation_importance(model, X, y, scoring='accuracy')
- # get importance
- importance = results.importances_mean
- # summarize feature importance
- for i,v in enumerate(importance):
- print('Feature: %0d, Score: %.5f' % (i,v))
- # plot feature importance
- pyplot.bar([x for x in range(len(importance))], importance)
- pyplot.show()
运行示例,拟合模型,然后输出每个特征的系数值。
结果表明,这十个特征中的两个或三个可能对预测很重要。
- Feature: 0, Score: 0.04760
- Feature: 1, Score: 0.06680
- Feature: 2, Score: 0.05240
- Feature: 3, Score: 0.09300
- Feature: 4, Score: 0.05140
- Feature: 5, Score: 0.05520
- Feature: 6, Score: 0.07920
- Feature: 7, Score: 0.05560
- Feature: 8, Score: 0.05620
- Feature: 9, Score: 0.03080
然后为特征重要性得分创建条形图。
总结
在本教程中,您知道了在Python机器学习中的特征重要性得分。
具体来说,您了解到:
- 特征重要性在预测建模问题中的作用
- 如何从线性模型和决策树中计算和查看特征重要性
- 如何计算和查看随机排序特征重要性得分
-
用 XGBoost 在 Python 中进行特征重要性分析和特征选择
2021-04-18 00:05:51使用诸如梯度增强之类的决策树方法的集成的好处是,它们可以从训练有素的预测模型中自动提供特征重要性的估计。在本文中,您将发现如何使用Python中的XGBoost库来估计特征对于预测性建模问...使用诸如梯度增强之类的决策树方法的集成的好处是,它们可以从训练有素的预测模型中自动提供特征重要性的估计。
在本文中,您将发现如何使用Python中的XGBoost库来估计特征对于预测性建模问题的重要性,阅读这篇文章后,您将知道:
如何使用梯度提升算法计算特征重要性。
如何绘制由XGBoost模型计算的Python中的特征重要性。
如何使用XGBoost计算的特征重要性来执行特征选择。
梯度提升中的特征重要性
使用梯度增强的好处是,在构建增强后的树之后,检索每个属性的重要性得分相对简单。通常,重要性提供了一个分数,该分数指示每个特征在模型中构建增强决策树时的有用性或价值。用于决策树的关键决策使用的属性越多,其相对重要性就越高。
此重要性是针对数据集中的每个属性明确计算得出的,从而可以对属性进行排名并进行相互比较。单个决策树的重要性是通过每个属性拆分点提高性能指标的数量来计算的,并由节点负责的观察次数来加权。性能度量可以是用于选择拆分点的纯度(基尼系数),也可以是其他更特定的误差函数。然后,将特征重要性在模型中所有决策树之间平均。有关如何在增强型决策树中计算特征重要性的更多技术信息,请参见《统计学习的要素:数据挖掘,推理和预测》(第367页)第10.13.1节“预测变量的相对重要性”。另外,请参见Matthew Drury对StackOverflow问题“ Boosting的相对变量重要性”的回答,在此他提供了非常详细和实用的答案。
手动绘制特征重要性
训练有素的XGBoost模型会自动计算出您的预测建模问题中的特征重要性。这些重要性分数可在训练模型的feature_importances_成员变量中获得。例如,可以按如下所示直接打印它们:
print(model.feature_importances_)
我们可以将这些得分直接绘制在条形图上,以直观表示数据集中每个特征的相对重要性。例如:
# plot pyplot.bar(range(len(model.feature_importances_)), model.feature_importances_) pyplot.show()
我们可以通过在皮马印第安人发病的糖尿病数据集上训练XGBoost模型并根据计算出的特征重要性创建条形图来证明这一点。
下载数据集并将其放置在当前工作目录中。
数据集文件:
https://raw.githubusercontent.com/jbrownlee/Datasets/master/pima-indians-diabetes.csv
数据集详细信息:
https://raw.githubusercontent.com/jbrownlee/Datasets/master/pima-indians-diabetes.names
# plot feature importance manually from numpy import loadtxt from xgboost import XGBClassifier from matplotlib import pyplot # load data dataset = loadtxt('pima-indians-diabetes.csv', delimiter=",") # split data into X and y X = dataset[:,0:8] y = dataset[:,8] # fit model no training data model = XGBClassifier() model.fit(X, y) # feature importance print(model.feature_importances_) # plot pyplot.bar(range(len(model.feature_importances_)), model.feature_importances_) pyplot.show()
注意:由于算法或评估程序的随机性,或者数值精度的差异,您的结果可能会有所不同。考虑运行该示例几次并比较平均结果。
首先运行此示例将输出重要性分数。
[ 0.089701 0.17109634 0.08139535 0.04651163 0.10465116 0.2026578 0.1627907 0.14119601]
我们还获得了相对重要性的条形图。
该图的缺点是要素按其输入索引而不是其重要性排序。我们可以在绘制之前对特征进行排序。
值得庆幸的是,有一个内置的绘图函数可以帮助我们。
使用内置XGBoost特征重要性图XGBoost库提供了一个内置函数,可以按重要性顺序绘制要素。该函数称为
plot_importance()
,可以按以下方式使用:# plot feature importance plot_importance(model) pyplot.show()
例如,以下是完整的代码清单,其中使用内置的
plot_importance()
函数绘制了Pima Indians数据集的特征重要性。# plot feature importance using built-in function from numpy import loadtxt from xgboost import XGBClassifier from xgboost import plot_importance from matplotlib import pyplot # load data dataset = loadtxt('pima-indians-diabetes.csv', delimiter=",") # split data into X and y X = dataset[:,0:8] y = dataset[:,8] # fit model no training data model = XGBClassifier() model.fit(X, y) # plot feature importance plot_importance(model) pyplot.show()
注意:由于算法或评估程序的随机性,或者数值精度的差异,您的结果可能会有所不同。考虑运行该示例几次并比较平均结果。
运行该示例将为我们提供更有用的条形图。
您可以看到,要素是根据它们在F0至F7的输入数组(X)中的索引自动命名的。手动将这些索引映射到问题描述中的名称,可以看到该图显示F5(体重指数)具有最高的重要性,而F3(皮肤褶皱厚度)具有最低的重要性。
XGBoost特征重要性评分的特征选择
特征重要性评分可用于scikit-learn中的特征选择。这是通过使用
SelectFromModel
类完成的,该类采用一个模型,并且可以将数据集转换为具有选定要素的子集。此类可以采用预训练的模型,例如在整个训练数据集上进行训练的模型。然后,它可以使用阈值来确定要选择的特征。当您在SelectFromModel
实例上调用transform()
方法以一致地选择训练数据集和测试数据集上的相同要素时,将使用此阈值。在下面的示例中,我们首先训练,然后分别在整个训练数据集和测试数据集上评估XGBoost模型。使用从训练数据集计算出的特征重要性,然后将模型包装在
SelectFromModel
实例中。我们使用它来选择训练数据集上的特征,从选定的特征子集中训练模型,然后在测试集上评估模型,并遵循相同的特征选择方案。例如:
# select features using threshold selection = SelectFromModel(model, threshold=thresh, prefit=True) select_X_train = selection.transform(X_train) # train model selection_model = XGBClassifier() selection_model.fit(select_X_train, y_train) # eval model select_X_test = selection.transform(X_test) y_pred = selection_model.predict(select_X_test)
出于兴趣,我们可以测试多个阈值,以根据特征重要性选择特征。具体来说,每个输入变量的特征重要性,从本质上讲,使我们能够按重要性测试每个特征子集,从所有特征开始,到具有最重要特征的子集结束。
下面提供了完整的代码清单:
# use feature importance for feature selection from numpy import loadtxt from numpy import sort from xgboost import XGBClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score from sklearn.feature_selection import SelectFromModel # load data dataset = loadtxt('pima-indians-diabetes.csv', delimiter=",") # split data into X and y X = dataset[:,0:8] Y = dataset[:,8] # split data into train and test sets X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.33, random_state=7) # fit model on all training data model = XGBClassifier() model.fit(X_train, y_train) # make predictions for test data and evaluate y_pred = model.predict(X_test) predictions = [round(value) for value in y_pred] accuracy = accuracy_score(y_test, predictions) print("Accuracy: %.2f%%" % (accuracy * 100.0)) # Fit model using each importance as a threshold thresholds = sort(model.feature_importances_) for thresh in thresholds: # select features using threshold selection = SelectFromModel(model, threshold=thresh, prefit=True) select_X_train = selection.transform(X_train) # train model selection_model = XGBClassifier() selection_model.fit(select_X_train, y_train) # eval model select_X_test = selection.transform(X_test) y_pred = selection_model.predict(select_X_test) predictions = [round(value) for value in y_pred] accuracy = accuracy_score(y_test, predictions) print("Thresh=%.3f, n=%d, Accuracy: %.2f%%" % (thresh, select_X_train.shape[1], accuracy*100.0))
请注意,如果您使用的是XGBoost 1.0.2(可能还有其他版本),则XGBClassifier类中存在一个错误,该错误会导致错误:
KeyError: 'weight'
这可以通过使用自定义
XGBClassifier
类来解决,该类为coef_
属性返回None
。下面列出了完整的示例。# use feature importance for feature selection, with fix for xgboost 1.0.2 from numpy import loadtxt from numpy import sort from xgboost import XGBClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score from sklearn.feature_selection import SelectFromModel # define custom class to fix bug in xgboost 1.0.2 class MyXGBClassifier(XGBClassifier): @property def coef_(self): return None # load data dataset = loadtxt('pima-indians-diabetes.csv', delimiter=",") # split data into X and y X = dataset[:,0:8] Y = dataset[:,8] # split data into train and test sets X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.33, random_state=7) # fit model on all training data model = MyXGBClassifier() model.fit(X_train, y_train) # make predictions for test data and evaluate predictions = model.predict(X_test) accuracy = accuracy_score(y_test, predictions) print("Accuracy: %.2f%%" % (accuracy * 100.0)) # Fit model using each importance as a threshold thresholds = sort(model.feature_importances_) for thresh in thresholds: # select features using threshold selection = SelectFromModel(model, threshold=thresh, prefit=True) select_X_train = selection.transform(X_train) # train model selection_model = XGBClassifier() selection_model.fit(select_X_train, y_train) # eval model select_X_test = selection.transform(X_test) predictions = selection_model.predict(select_X_test) accuracy = accuracy_score(y_test, predictions) print("Thresh=%.3f, n=%d, Accuracy: %.2f%%" % (thresh, select_X_train.shape[1], accuracy*100.0))
注意:由于算法或评估程序的随机性,或者数值精度的差异,您的结果可能会有所不同。考虑运行该示例几次并比较平均结果。
运行此示例将打印以下输出。
Accuracy: 77.95% Thresh=0.071, n=8, Accuracy: 77.95% Thresh=0.073, n=7, Accuracy: 76.38% Thresh=0.084, n=6, Accuracy: 77.56% Thresh=0.090, n=5, Accuracy: 76.38% Thresh=0.128, n=4, Accuracy: 76.38% Thresh=0.160, n=3, Accuracy: 74.80% Thresh=0.186, n=2, Accuracy: 71.65% Thresh=0.208, n=1, Accuracy: 63.78%
我们可以看到,模型的性能通常随所选特征的数量而降低。
在此问题上,需要权衡测试集精度的特征,我们可以决定采用较不复杂的模型(较少的属性,例如n = 4),并接受估计精度的适度降低,从77.95%降至76.38%。
这可能是对这么小的数据集的洗礼,但是对于更大的数据集并使用交叉验证作为模型评估方案可能是更有用的策略。
作者:沂水寒城,CSDN博客专家,个人研究方向:机器学习、深度学习、NLP、CV
Blog: http://yishuihancheng.blog.csdn.net
赞 赏 作 者
更多阅读
特别推荐
点击下方阅读原文加入社区会员
-
有哪些让程序员受益终生的建议
2019-10-28 07:11:59在大学期间,有很多的算法竞赛、ACM竞赛,尽量参加全国性的,有含金量的比赛,这才能眼前一亮。 2、参加实习 去大公司实习,相比校招进入大公司,那是简单很多,二本学校的学生,也能进得去实习。而且在大公司... -
论计算机基础的重要性
2016-12-04 22:59:21因为我阅历有限,有什么说的不对的,大家轻喷! 一、程序员应该打好基础 1. 现在开发工具众多、语言泛滥,经常听人说“不学C,C++神马都是浮云”、“C,C++才是万王之王”,C,C++就真比PHP、Lua、AS、JAVA牛吗... -
背英语单词词根词缀的重要性
2018-03-06 10:07:46原文地址:https://www.zhihu.com/question/2289615918 个...有时候,抄着抄着就会开始产生“我真的认识这个字吗”、“怎么这个字这么奇怪呢”的想法。不过也有相反的时候。写着写着,突然发现,“啊,原来这个字是... -
江小白,将简单做到极致的包装是品牌传播的先行军
2020-12-23 01:15:13作为一款有态度的品牌,你来,我欢迎;你走,我不挽留。因为江小白并不是想要获得所有人的喜爱,这就是江小白的态度,也是其个性化一面。说起江小白的个性化特征,就不得不说一下它的包装。自诞生日起,江小白的包装... -
对计算机专业来说学历真的重要吗?
2019-09-27 09:21:37我本科学校是渣渣二本,研究生...先说结论,无论赞不赞同,它本质就是这样:对于技术类工作而言,学历五年以内非常重要,但有办法弥补。五年以后,不重要。 目录: 张雪峰讲述的事实 我看到的事实 为什么会这样 ... -
茶叶包装技术及方法分析
2019-08-01 10:09:34作为世界性3大无醇饮料之一的茶叶,被誉为是21世纪的饮料,并以其天然、营养、保健的品质特点而备受世人青睐。茶叶作为一类特殊商品,不完善的包装往往会使茶叶的形、色、香、味受到损坏,为了实现长时间的贮存和... -
面试常见问题:有了基本类型为什么还要有包装类?
2019-02-11 17:51:05这个问题的重心不仅仅在于考察对包装类存在合理性的认识,也在考察对基本数据类型存在意义的理解。 我们都知道在Java语言中,new一个对象存储在堆里,我们通过栈中的引用来使用这些对象。但是对于经常用到的一系列类... -
用户体验的重要性
2016-06-08 13:51:45互联网的时代,说是一个体验为王的时代,一点也不为过。在互联网时代,产品是否能够做成功,用户体验成为一个关键...有一个叫Scott McKain的美国人遇到这样一件事:他要到美国一个城市给一群商业领袖做演讲,但很不幸, -
程序人生 - 农夫山泉、恒大冰泉、怡宝等矿泉水品牌的产品有哪些区别?
2020-08-12 17:01:49水的重要性,不光是满足人体机能正常运转,如果长期错误饮水,也会对身体有或多或少的影响。 水这么重要,但是很多人真的不懂水。 蒸馏水、纯净水、矿泉水、天然水……一溜儿看起来水至清的瓶装水,到底差别在哪?... -
如何包装简历上的项目?
2019-04-24 15:11:37这篇文章我们来聊一聊,在系统设计和项目经验这两块,应该如何充分的准备,才能拿出有技术含量的项目经验战胜跟你同台竞技的其他工程师,征服你的面试官,收获各种心仪的offer。 (1)高级工程师必备:系统设计能力 ... -
特征选择(过滤法、包装法、嵌入法)
2020-04-29 20:33:16这个数值之所以能够说明特征的重要性是因为,如果加入随机噪声后,袋外数据准确率大幅度下降(即errOOB2上升),说明这个特征对于样本的预测结果有很大影响,进而说明重要程度比较高。 特征选择 在特征重要性的基础... -
【商品架构day10】一个商品系统的需求有哪些 - 从产品层面说起
2020-02-21 11:31:53所以,原来的单个实体商品,也会分为实物商品,虚拟商品,比如,电影票,火车票,兑换券,服务券,跑腿单等等,商品的多样性已经远远超越的具体的实物,所以伴随着商品系统,也有涉及的不同,但是商品系统的意义和... -
【软件测试系列】关于软件测试的重要性
2018-07-15 19:24:45软件测试的重要性(待续……) -
中科院发布《2019人工智能发展白皮书》,强调人工智能开放平台重要性(结尾附下载)...
2020-02-23 12:45:18而且同时强调人工智能开放平台的重要性,并列举百度Apollo开放平台、阿里云城市大脑、腾讯觅影AI辅诊开放平台、科大讯飞智能语音开放创新平台、商汤智能视觉开放创新平台、松鼠AI智适应教育开放平台、京东人工智能... -
浅谈网站首页的重要性
2012-12-29 09:01:40下边我们来谈一谈网站首页的重要性。 在做网站优化推广时,希望能让客户多点击几个页面,这样就可以最大程度吸引住客户。 一个网站的最大访问量一般都集中在首页,推广的页面也都集中在首页。想要抓住客户停留时间... -
常见Linux发行版本有哪些?
2019-10-29 20:29:10有人这样评价 Gentoo:快速、设计干净而有弹性,它的出名是因为其高度的自定制性(基于源代码的发行版)。尽管安装时可以选择预先编译好的软件包,但是大部分使用 Gentoo 的用户都选择自己手动编译。这也是为什么 ... -
java面对对象(中.2)(多态性,终极父类,instanceof,包装类等)
2022-03-21 07:01:27深入浅出,全方面理解java多态性,终极父类,instanceof,包装类等,还有一些踩坑点,不容错过 -
特征选择—过滤法(Filter)、嵌入法(Embedded)和包装法(Wrapper)
2020-06-14 20:22:15最近邻算法KNN,支持向量机SVM,决策树,神经网络,回归算法等遍历特征或升维运算,本身的运算量很大,需要的时间很长,因此特征选择很重要。随机森林不需要遍历特征,每次选的特征就很随机,并非用到所有的特征,... -
Java的主要特性有哪些?
2018-12-28 23:33:42通常有两种方法来创建线程:其一,使用型构为Thread(Runnable)的构造子将一个实现了Runnable接口的对象包装成一个线程,其二,从Thread类派生出子类并重写run方法,使用该子类创建的对象即为线程。值得注意的是... -
MySQL需要掌握的技能有哪些?超细长文带你掌握MySQL
2021-09-02 21:41:393.3 正则表达式搜索 随着过滤条件的复杂性的增加,WHERE子句本身的复杂性也有必要增加。这个时候,就需要用到正则表达式了。 正则表达式的作用是匹配文本,将一个模式(正则表达式)与一个文本串进行比较。MySQL用... -
物联网应用技术有哪些?
2019-09-06 09:21:23物联网应用技术有哪些? 物联网作为一项前沿技术,已经逐步融入生产生活的多个应用场景。近年来,物联网开始广泛应用于在交通、物流、环保、电力等领域,人们在潜移默化中受到了物联网的影响。与此同时,共享单车、... -
区块链项目如何包装?点击查看详细流程
2020-09-01 14:53:21区块链包装的重要性,比起普通商品,更为重要,要想在层出不穷的区块链项目中呈现出万绿丛中一点红,没有独特的包装是做不到的。 1、白皮书 作为一个官方团队,你的区块链项目白皮书要怎么写才能打动投资人呢?怎样... -
板式家具打包新方法,终于知道怎么打包了
2021-01-17 16:39:41当前,中国的办公家具和其他家具产品一样,普遍采用...PE缠绕膜是工业用装膜制品,具有拉伸强度高,延伸率大、自粘性好,透明度高等物点。用于手工缠绕膜,也可用于机用缠绕膜,可广泛应用于各种货物的集中包装。为... -
项目经验不多时如何在简历中包装自己
2019-02-12 15:09:51项目经验不多时如何在简历中包装自己 -
有哪些比较好用的安卓模拟器(电脑端)
2020-09-23 18:03:22Bluestacks的原理是把Android底层API接口翻译成Windows API,对PC硬件本身没有要求,在硬件兼容性方面有一定的优势。但Bluestacks需要翻译的Android接口数量巨大,很难面面俱到,而且存在软件翻译的开销,在性能 -
妥协的重要性 有感触的 共勉之吧!
2013-07-05 20:10:10做开发快6年了,慢慢的领悟到了妥协的重要性,虽然有时候不是真心的,但是你必须这样去做! 三四年前还常会因技术上的问题,不管对方资历多老,经验多丰富,我都会坚持自己认为对的观点,除非对方用真实的实例来说服我!对...