前言

在使用GBDT、RF、Xgboost等树类模型建模时,往往可以通过feature_importance 来返回特征重要性,本文以随机森林为例介绍其原理与实现。[ 链接:机器学习的特征重要性究竟是怎么算的]

数据:美国某公司的共享单车数据

数据源:http://archive.ics.uci.edu/ml/machine-learning-databases/00275/

图源:Spark ML 构建回归模型_宝哥大数据的博客-CSDN博客

由于相关的预测变量,单个决策树的特征重要性可能具有较高的方差。考虑使用随机森林分类器来确定特征的重要性。

随机森林计算特征重要性的原理

随机森林中进行特征重要性的评估思想:判断每个特征在随机森林中的每颗树上做了多大的贡献,然后取个平均值,最后比一比特征之间的贡献大小。其中关于贡献的计算方式可以是不纯度袋外数据错误率

  • 基于不纯度

对于每颗树,按照impurity(gini /entropy)给特征排序,然后整个森林取平均。最优条件的选择依据是不纯度,不纯度在分类中通常为gini或entropy,对于回归问题来说是方差mse。

基于不纯度对模型进行排序有几点需要注意: 
    (1)基于不纯度降低的特征选择将会偏向于选择那些具有较多类别的变量。 
    (2)当存在相关特征时,一个特征被选择后,与其相关的其他特征的重要度则会变得很低,因为他们可以减少的不纯度已经被前面的特征移除了。

  • 基于袋外错误率

计算某个特征X的重要性时,具体步骤如下:

1)对每一颗决策树,选择相应的袋外数据(out of bag,OOB)​计算袋外数据误差,记为errOOB1.

所谓袋外数据是指,每次建立决策树时,通过重复抽样得到一个数据用于训练​决策树,这时还有大约1/3的数据没有被利用,没有参与决策树的建立。这部分数据可以用于对决策树的性能进行评估,计算模型的预测错误率,称为袋外数据误差。

​    这已经经过证明是无偏估计的,所以在随机森林算法中不需要再进行交叉验证或者单独的测试集来获取测试集误差的无偏估计。

​    2)随机对袋外数据OOB所有样本的特征X加入噪声干扰(可以随机改变样本在特征X处的值),再次计算袋外数据误差,记为errOOB2。

这里的噪声干扰(指对数据进行打乱的方法)通常有两种:
    一是使用uniform或者gaussian抽取随机值替换原特征;
    二是通过permutation的方式将原来的所有N个样本的第 i 个特征值重新打乱分布(相当于重新洗牌)。

3)​假设森林中有N棵树,则特征X的重要性=∑(errOOB2-errOOB1)/N。这个数值之所以能够说明特征的重要性是因为,如果加入随机噪声后,袋外数据准确率大幅度下降(即errOOB2上升),说明这个特征对于样本的预测结果有很大影响,进而说明重要程度比较高。

超参数

1、n_estimators:它表示建立的树的数量。 一般来说,树的数量越多,性能越好,预测也越稳定,但这也会减慢计算速度。一般来说在实践中选择数百棵树是比较好的选择,因此,一般默认是100。

2、n_jobs:参数表示引擎允许使用处理器的数量。 若值为1,则只能使用一个处理器。 值为-1则表示没有限制。设置n_jobs可以加快模型计算速度。

3、oob_score :它是一种随机森林交叉验证方法,即是否采用袋外样本来评估模型的好坏。默认是False。推荐设置为True,因为袋外分数反应了一个模型拟合后的泛化能力。

#特征重要性
importances = model.feature_importances_# out of bag score
oobs = model.oob_score_

pySpark代码

from pyspark.sql import SparkSession
from pyspark.ml.regression import LinearRegression
from pyspark.ml.feature import OneHotEncoder
from pyspark.ml.feature import VectorAssembler,StandardScaler
from pyspark.ml.evaluation import RegressionEvaluator
from pyspark.ml import Pipelinespark = SparkSession.builder.master('local').appName('LinearRegression').getOrCreate()data = spark.read.format('csv').option("header",True).load(u"D:\Data\day.csv")# ''' 特征选择并转换类型 '''
data1 = data.select(data["season"].cast("Double"), # 季节 (类别字段)data["yr"].cast("Double"), # 年份 (类别字段)data["mnth"].cast("Double"), # 月份 (类别字段)data["holiday"].cast("Double"), # 是否为假期 (类别字段)data["weekday"].cast("Double"), # 是否为周末 (类别字段)data["workingday"].cast("Double"), # 是否为工作日 (类别字段)data["weathersit"].cast("Double"), # 天气 (类别字段)data["temp"].cast("Double"), # 气温 (数值字段)data["atemp"].cast("Double"), # 体感温度 (数值字段)data["hum"].cast("Double"), # 湿度 (数值字段)data["windspeed"].cast("Double"), # 风速 (数值字段)data["cnt"].cast("Double").alias("label")) # 单车租用量 (数值字段)
#data1.show(10)''' 特征重要性 '''
from pyspark.ml.regression import RandomForestRegressorfeatureArray = ["season", "yr", "mnth", "holiday", "weekday", "workingday", "weathersit", "temp", "hum", "windspeed","atemp"]
assembler_lr = VectorAssembler().setInputCols(featureArray).setOutputCol("features")
pipeline_lr = Pipeline().setStages([assembler_lr])
data_M = pipeline_lr.fit(data1).transform(data1)scaler = StandardScaler().setInputCol("features").setOutputCol("scaledFeatures").setWithStd(True).setWithMean(False)
data_M = scaler.fit(data_M).transform(data_M)RF = RandomForestRegressor().setLabelCol("label").setFeaturesCol("scaledFeatures").setMaxBins(64).setMaxDepth(16)
model = RF.fit(data_M)
print(model.featureImportances)

Python.sklearn代码

    class sklearn.ensemble.RandomForestRegressor(n_estimators=10, criterion=’mse’, max_depth=None, min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=’auto’, max_leaf_nodes=None,min_impurity_decrease=0.0, min_impurity_split=None, bootstrap=True, oob_score=False, n_jobs=1, random_state=None,verbose=0, warm_start=False)

  • 原理:基于mse
from sklearn import ensemble
import pandas as pddata = pd.read_csv(u"D:\Data\day.csv")
featureArray = ["season", "yr", "mnth", "holiday", "weekday", "workingday", "weathersit", "temp", "hum", "windspeed","atemp"]
x = data[featureArray]
y = data["cnt"]rf = ensemble.RandomForestRegressor(n_estimators=35)
rf.fit(x,y)
print("特征重要性:"+str(rf.feature_importances_))
  • 原理:基于袋外错误率

class sklearn.model_selection.ShuffleSplit(n_splits=10, test_size=’default’, train_size=None, random_state=None)

from sklearn.model_selection import ShuffleSplit
from sklearn.metrics import mean_absolute_error
from collections import defaultdict
from sklearn.datasets import load_boston
from sklearn.ensemble import RandomForestRegressor
import numpy as npboston = load_boston()
X = boston["data"]
Y = boston["target"]
names = boston["feature_names"]rf = RandomForestRegressor()
scores = defaultdict(list)rs = ShuffleSplit(n_splits=100, test_size=0.3,random_state=0)for train_idx, test_idx in rs.split(X):X_train, X_test = X[train_idx], X[test_idx]Y_train, Y_test = Y[train_idx], Y[test_idx]r = rf.fit(X_train, Y_train)acc = mean_absolute_error(Y_test, rf.predict(X_test)).round(3)for i in range(X.shape[1]):X_t = X_test.copy()np.random.shuffle(X_t[:, i])shuff_acc = mean_absolute_error(Y_test, rf.predict(X_t)).round(3)scores[names[i]].append(abs(acc-shuff_acc))print("Features sorted by their score:")
print(sorted([(round(np.mean(score), 4), feat) forfeat, score in scores.items()], reverse=True))

结果

season

yr

mnth

holiday

weekday

workingday

weathersit

temp

hum

windspeed

atemp

pySpark 0.104771 0.263050 0.043331 0.002871 0.016073 0.006742 0.027944 0.246312 0.069891 0.038229 0.1807837
sklearn 0.062571 0.287863 0.029111 0.003221 0.014817 0.003823 0.020559 0.369785 0.068229 0.031225 0.108790

绘图

import matplotlib as mpl
import matplotlib.pyplot as pltFI = pd.Series(model.featureImportances, index = featureArray) # pySpark
# FI = pd.Series(rf.feature_importances_,index = featureArray) # sklearn
FI = FI.sort_values(ascending = False)
fig = plt.figure(figsize=(12,5))
plt.bar(FI.index,FI.values,color="blue")
plt.xlabel('features')
plt.ylabel('importances')
plt.show()

pySpark结果(图表无关,由于数据随机性,每次结果会有不同)

sklearn结果(图表无关,由于数据随机性,每次结果会有不同)

说明

随机森林进行特征选择和特征重要性排序的时候结果不一样,因为bagging抽取子集的时候,可能具有一定的随机性。

参考

随机森林如何评估特征重要性

随机森林对特征重要性排序(有代码示例)

Scikit-learn的K-fold交叉验证类ShuffleSplit、GroupShuffleSplit用法介绍

python实现随机森林random forest的原理及方法

随机森林算法OOB_SCORE最佳特征选择

Random Forest算法参数解释及调优

回归预测的评价指标

实战:用Python实现随机森林

随机之美——机器学习中的随机森林模型

python实现RF.feature_importances的条形图

Python随机森林算法入门和性能评估


Spark 和 Python.sklearn:使用随机森林计算 feature_importance 特征重要性相关推荐

  1. python随机森林变量重要性_随机森林如何评估特征重要性【机器学习面试题详解】...

    今天爱分享给大家带来随机森林如何评估特征重要性[机器学习面试题详解],希望能够帮助到大家. 解析: 衡量变量重要性的方法有两种,Decrease GINI 和 Decrease Accuracy: 1 ...

  2. 随机森林如何评估特征重要性

    序 集成学习模型的一大特点是可以输出特征重要性,特征重要性能够在一定程度上辅助我们对特征进行筛选,从而使得模型的鲁棒性更好. 随机森林中进行特征重要性的评估思想为: 判断每个特征在随机森林中的每颗树上 ...

  3. python随机森林特征重要性_Python中随机森林回归的特征重要性

    当涉及到决策树时,特征重要性不是一个黑匣子.来自DecisionTreeRegressor的文档:The importance of a feature is computed as the (nor ...

  4. 随机森林,随机森林中进行特征重要性

    随机森林(RF)简介 只要了解决策树的算法,那么随机森林是相当容易理解的.随机森林的算法可以用如下几个步骤概括: 用有抽样放回的方法(bootstrap)从样本集中选取n个样本作为一个训练集 用抽样得 ...

  5. 随机森林计算特征重要性_随机森林中计算特征重要性的3种方法

    随机森林计算特征重要性 The feature importance describes which features are relevant. It can help with a better ...

  6. 预处理--python实现用随机森林评估特征的重要性

    python实现用随机森林评估特征的重要性 随机森林根据森林中所有决策树计算平均不纯度的减少来测量特征的重要性,而不作任何数据是线性可分或不可分的假设. import numpy as np impo ...

  7. Python 中的随机森林

    什么是随机森林 众所周知,树模型是高方差.低偏差的模型.因此,它们容易过度拟合训练数据.如果我们不修剪树模型或引入早期停止标准(例如每个叶节点的最小实例数),我们可以概括一下树模型的作用,这很吸引人. ...

  8. sklearn实现随机森林(分类算法)

    阿喽哈~小伙伴们,今天我们来唠一唠随机森林 ♣ ♣ ♣ 随机森林应该是很多小伙伴们在学机器学习算法时最先接触到的集成算法,我们先简单介绍一下集成学习的大家族吧: Bagging:个体评估器之间不存在强 ...

  9. python机器学习-建立随机森林预测模型并特征分析(完整代码+实现效果)

    实现功能: python机器学习-建立随机森林预测模型并特征分析. 实现效果: # 导入需要的库 from warnings import simplefilter simplefilter(acti ...

最新文章

  1. Python matplotlib可视化:自定义轴标签格式化函数(在轴刻度上添加自定义的数值以及符号形式)、使用自定义函数在Matplotlib中为坐标轴刻度添加自定义符号(例如,货币符号¥$等)
  2. PHP date()函数警告: It is not safe to rely on the system解决方法
  3. 增量式爬虫与分布式爬虫
  4. 投影串口测试程序_串口测试方法和步骤
  5. mvc 404错误 php,java - springmvc 请求无法到达controller,出现404错误
  6. 多线程的那点儿事(之数据同步)
  7. 算法:平衡二叉树110. Balanced Binary Tree
  8. 【leetcode 简单】 第六十六题 用栈实现队列
  9. 双子星tv源码_双子星IPTV电视直播管理系统源码安装教程
  10. 手机APP开发常用工具有哪些
  11. 私有云盘的搭建(owncloud、seafile)
  12. 想要避免After Effects渲染失败的问题,5个小技巧必看
  13. android-759b1c是什么,[原创]hooker + jadx 动静结合内存漫游窥视某社交软件视频号功能的数据...
  14. Python-matplotlib:调整坐标轴位置、标签位置和标签方向,以及X轴刻度标签位置
  15. 当人工智能遇上伦理道德
  16. ogg如何转换成mp3格式?
  17. 免疫算法求解多元函数论文
  18. 什么是BOS? BOS 与 ERP 是什么关系?
  19. 数控系统锁住了怎么解锁解密
  20. 购买的wemall 6.0商城系统源码分享

热门文章

  1. 政府民航行业双获嘉奖,永洪科技做好行业数字化转型伙伴
  2. 【LVGL(6)】显示中文设置,制作中文字库
  3. 网络安全进阶篇之免杀(十四章-9)MSF加密壳免杀过360
  4. C# 汉字转拼音 拼音转汉字 简体繁体互转
  5. APP上短信验证码如何验证?
  6. Debain8 Tomcat8 JDK8 实现SSL双向验证
  7. 我自己对英语学习的心得与体会
  8. Currency Exchange (SPFA)
  9. python 爬取整部漫画(简单的图片爬取)
  10. PhpSpreadsheet读取excel