随机森林及scikit-learn实战

随机森林

我们知道集成学习有两个流派,

  • 一个是boosting流派,它的特点是产生的个体学习器之间存在强依赖关系,一系列个体学习器基本都需要串行生成
  • 另一种是bagging流派,它的特点是产生的个体学习器之间不存在强依赖关系,一系列个体学习器可以并行生成

而随机森林(Random Forest)是非常具有代表性的Bagging集成算法,是集成学习中可以和梯度提升树GBDT分庭抗礼的算法,尤其是它可以很方便的并行训练,在如今大数据大样本的的时代很有诱惑力。

随机森林它是Bagging算法的特别进化版,也就是说,它的思想仍然是bagging,但是进行了独有的改进。我们现在就来看看RF算法改进了什么。

  • 首先,RF使用了CART决策树作为弱学习器,这让我们想到了梯度提升树GBDT。
  • 第二,在使用决策树的基础上,RF对决策树的建立做了改进,对于普通的决策树,我们会在节点上所有的d个样本特征中选择一个最优的特征来做决策树的左右子树划分,但是RF通过随机选择节点上的一部分样本特征,这个数字小于d,假设为k,然后在这些随机选择的k个样本特征中,选择一个最优的特征来做决策树的左右子树划分。这样进一步增强了模型的泛化能力。k控制了随机性的引入程度,推荐值\(k = log_2 d\)   

除了上面两点,RF和普通的bagging算法没有什么不同, 下面简单总结下RF的算法步骤。

输入为样本集\(D=\{(x_,y_1),(x_2,y_2), ...(x_m,y_m)\}\),弱分类器迭代次数T。
输出为最终的强分类器f(x)

  • 对于t=1,2...,T:

    • a)对训练集进行第t次有放回随机采样,共采集m次,得到包含m个样本的采样集\(D_t\)
    • b)用采样集\(D_t\)训练第t个CART决策树模型\(G_{t}(x)\),在训练CART决策树模型的节点的时候, 在节点上所有的样本特征中随机选择一部分样本特征,在这些随机选择的部分样本特征中选择一个最优的特征来做决策树的左右子树划分
  • 如果是分类算法预测,则T个弱学习器投出最多票数的类别或者类别之一为最终类别。如果是回归算法,T个弱学习器得到的回归结果进行算术平均得到的值为最终的模型输出。

这里稍微提一下上面的采样算法。Bagging里使用的随机采样算法叫自助采样法(bootstrap),就是从我们的训练集里面采集固定个数的样本,但是每采集一个样本后,都将样本放回。也就是说,之前采集到的样本在放回后有可能继续被采集到。对于我们的Bagging算法,一般会随机采集和训练集样本数m一样个数的样本。这样得到的采样集和训练集样本的个数相同,但是样本内容不同。如果我们对有m个样本训练集做T次的随机采样,则由于随机性,T个采样集各不相同。

对于一个样本,它在某一次含m个样本的训练集的随机采样中,每次被采集到的概率是\(\frac{1}{m}\)。不被采集到的概率为\(1−\frac{1}{m}\)。如果m次采样都没有被采集中的概率是\((1−\frac{1}{m})^m\)。当\(m→∞\)时,\((1-\frac{1}{m})^m \to \frac{1}{e} \simeq 0.368\)。也就是说,在bagging的每轮随机采样中,训练集中大约有36.8%的数据没有被采样集采集中。

对于这部分大约36.8%的没有被采样到的数据,我们常常称之为袋外数据(Out Of Bag, 简称OOB)。这些数据没有参与训练集模型的拟合,因此可以用来检测模型的泛化能力。

随机森林的推广

由于随机森林在实际应用中的良好特性基于随机森林,有很多变种算法,应用也很广泛,不光可以用于分类回归,还可以用于特征转换异常点检测等。下面对这些随机森林家族中的有代表性的算法做一个总结。

extra trees

extra trees是随机森林的一个变种, 原理几乎和随机森林一模一样,仅有区别有:

  • 对于每个决策树的训练集,随机森林采用的是随机采样bootstrap来选择采样集作为每个决策树的训练集,而extra trees一般不采用随机采样,即每个决策树采用原始训练集。

  • 在选定了划分特征后,随机森林的决策树会基于基尼系数,均方差之类的原则,选择一个最优的特征值划分点,这和传统的决策树相同。但是extra trees比较的激进,他会随机的选择一个特征值来划分决策树。

从第二点可以看出,由于随机选择了特征值的划分点位,而不是最优点位,这样会导致生成的决策树的规模一般会大于随机森林所生成的决策树。也就是说,模型的方差相对于随机森林进一步减少,但是偏倚相对于随机森林进一步增大。在某些时候,extra trees的泛化能力比随机森林更好。

Totally Random Trees Embedding

Totally Random Trees Embedding(以下简称 TRTE)是一种非监督学习的数据转化方法

  • 它将低维的数据集映射到高维,
  • 从而让映射到高维的数据更好的运用于分类回归模型。

我们知道,在支持向量机中运用了核方法来将低维的数据集映射到高维,此处TRTE提供了另外一种方法。

TRTE在数据转化的过程也使用了类似于随机森林的方法,建立T个决策树来拟合数据。当决策树建立完毕以后,数据集里的每个数据在T个决策树中叶子节点的位置也定下来了。比如我们有3颗决策树,每个决策树有5个叶子节点,某个数据特征x划分到第一个决策树的第2个叶子节点,第二个决策树的第3个叶子节点,第三个决策树的第5个叶子节点。则x映射后的特征编码为(0,1,0,0,0, 0,0,1,0,0, 0,0,0,0,1), 有15维的高维特征。这里特征维度之间加上空格是为了强调三颗决策树各自的子编码。

映射到高维特征后,可以继续使用监督学习的各种分类回归算法了。

Isolation Forest

Isolation Forest(以下简称IForest)是一种异常点检测的方法。它也使用了类似于随机森林的方法来检测异常点。

  • 对于在T个决策树的样本集,IForest也会对训练集进行随机采样,但是采样个数不需要和随机森林一样,对于随机森林,需要采样到的采样集样本个数等于训练集个数。但是IForest不需要采样这么多,一般来说,采样个数要远远小于训练集个数?为什么呢?因为我们的目的是异常点检测,一般只需要部分的样本,我们就可以将异常点区别出来了。

  • 对于每一个决策树的建立, IForest采用随机选择一个划分特征,对划分特征随机选择一个划分阈值。这点也和随机森林不同。

  • 另外,IForest一般会选择一个比较小的最大决策树深度max_depth,原因同样本采集,用少量的异常点检测,一般不需要这么大规模的决策树。

  • 对于异常点的判断,则是将测试样本点x拟合到T颗决策树.计算在每颗决策树上该样本的叶子节点的深度\(h_{t(x)}\)。从而可以计算出平均高度h(x)。此时我们用下面的公式计算样本点x的异常概率:
    \(s(x,m) = 2^{-\frac{h(x)}{c(m)}}\)
    其中,m为样本个数。c(m)的表达式为:\(c(m) =2\ln(m-1) + \xi - 2\frac{m-1}{m}, \; \xi为欧拉常数\)
    s(x,m)的取值范围是[0,1],取值越接近于1,则是异常点的概率也越大。

小结

作为一个可以高度并行化的算法,随机森林在大数据时候大有可为。 这里也对常规的随机森林算法的优缺点做一个总结。
随机森林的主要优点有

  • 训练时,由于树与树之间是相互独立的,所以可以高度并行化,对于大数据时代的大样本训练速度有优势。个人觉得这是的最主要的优点。

  • 由于可以随机选择决策树节点的划分特征,所以在样本特征维度很高的时候,仍然能高效的训练模型。

  • 在训练后,可以给出各个特征对于输出的重要性

  • 由于采用了随机采样,训练出的模型的方差小,泛化能力强。

  • 相对于Boosting系列的Adaboost和GBDT, RF实现比较简单。

  • 对部分特征缺失不敏感。

  • 随机森林有袋外数据obb,不需要单独划分交叉验证集。

随机森林的主要缺点有

  • 在某些噪音比较大的样本集上,RF模型容易陷入过拟合。

  • 取值划分比较多的特征容易对RF的决策产生更大的影响,从而影响拟合的模型的效果。

sklearn随机森林实战

在sklearn中,随机森林的分类类是RandomForestClassifier回归类是RandomForestRegressor。随机森林需要调参的参数也包括两部分,

  • 第一部分是Bagging框架的参数,
  • 第二部分是CART决策树的参数。

下面我们就对这些参数做一个介绍。
首先看一下类的定义:

from sklearn.ensemble import RandomForestClassifier
RandomForestClassifier(n_estimators=100, *, 
                       criterion='gini', 
                       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=None, 
                       random_state=None, 
                       verbose=0, 
                       warm_start=False, 
                       class_weight=None, 
                       ccp_alpha=0.0, 
                       max_samples=None)

随机森林的bagging框架参数:

由于RandomForestClassifier和RandomForestRegressor参数绝大部分相同,这里会将它们一起讲,不同点会指出。

  • n_estimators: 也就是最大的弱学习器的个数。一般来说n_estimators太小,容易欠拟合,n_estimators太大,计算量会太大,并且n_estimators到一定的数量后,再增大n_estimators获得的模型提升会很小,所以一般选择一个适中的数值。默认是100。

  • oob_score:即是否采用袋外样本来评估模型的好坏。默认是False。个人推荐设置为True,因为袋外分数反应了一个模型拟合后的泛化能力。

  • criterion: 即CART树做划分时对特征的评价标准。分类模型和回归模型的损失函数是不一样的。分类随机森林对应的CART分类树默认是基尼系数gini,另一个可选择的标准是信息增益回归随机森林对应的CART回归树默认是均方差mse,另一个可以选择的标准是绝对值差mae。一般来说选择默认的标准就已经很好的。

从上面可以看出,随机森林重要的框架参数比较少,主要需要关注的是 n_estimators,即随机森林最大的决策树个数。

随机森林决策树参数
下面我们再来看看随机森林的决策树参数,如下:

  • 随机森林划分时考虑的最大特征数max_features: 可以使用很多种类型的值,默认是"auto",意味着划分时最多考虑\(\sqrt N\)个特征;如果是"log2"意味着划分时最多考虑\(log_2N\)个特征;如果是"sqrt"或者"auto"意味着划分时最多考虑\(\sqrt N\)个特征。如果是整数,代表考虑的特征绝对数。如果是浮点数,代表考虑特征百分比,即考虑(百分比xN)取整后的特征数。其中N为样本总特征数。一般我们用默认的"auto"就可以了,如果特征数非常多,我们可以灵活使用刚才描述的其他取值来控制划分时考虑的最大特征数,以控制决策树的生成时间。

  • 决策树最大深度max_depth: 默认可以不输入,如果不输入的话,决策树在建立子树的时候不会限制子树的深度。一般来说,数据少或者特征少的时候可以不管这个值。如果模型样本量多,特征也多的情况下,推荐限制这个最大深度,具体的取值取决于数据的分布。常用的可以取值10-100之间

  • 内部节点再划分所需最小样本数min_samples_split: 这个值限制了子树继续划分的条件,如果某节点的样本数少于min_samples_split,则不会继续再尝试选择最优特征来进行划分。 默认是2.如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。

  • 叶子节点最少样本数min_samples_leaf: 这个值限制了叶子节点最少的样本数,如果某叶子节点数目小于样本数,则会和兄弟节点一起被剪枝。 默认是1,可以输入最少的样本数的整数,或者最少样本数占样本总数的百分比。如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。

  • 叶子节点最小的样本权重和min_weight_fraction_leaf:这个值限制了叶子节点所有样本权重和的最小值,如果小于这个值,则会和兄弟节点一起被剪枝。 默认是0,就是不考虑权重问题。一般来说,如果我们有较多样本有缺失值,或者分类树样本的分布类别偏差很大,就会引入样本权重,这时我们就要注意这个值了。

  • 最大叶子节点数max_leaf_nodes: 通过限制最大叶子节点数,可以防止过拟合,默认是"None”,即不限制最大的叶子节点数。如果加了限制,算法会建立在最大叶子节点数内最优的决策树。如果特征不多,可以不考虑这个值,但是如果特征分成多的话,可以加以限制,具体的值可以通过交叉验证得到。

  • 节点划分最小不纯度min_impurity_split: 这个值限制了决策树的增长,如果某节点的不纯度(基于基尼系数,均方差)小于这个阈值,则该节点不再生成子节点。即为叶子节点 。一般不推荐改动默认值1e-7。

上面决策树参数中最重要的包括最大特征数max_features, 最大深度max_depth, 内部节点再划分所需最小样本数min_samples_split和叶子节点最少样本数min_samples_leaf。

sklearn随机森林网格调参

import pandas as pd
import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.grid_search import GridSearchCV
from sklearn import cross_validation, metrics

import matplotlib.pylab as plt
%matplotlib inline

rf0 = RandomForestClassifier(oob_score=True, random_state=10)
rf0.fit(X,y)
print rf0.oob_score_
y_predprob = rf0.predict_proba(X)[:,1]
print "AUC Score (Train): %f" % metrics.roc_auc_score(y, y_predprob)

param_test2 = {'max_depth':range(3,14,2), 'min_samples_split':range(50,201,20)}
gsearch2 = GridSearchCV(estimator = RandomForestClassifier(n_estimators= 60, 
                                  min_samples_leaf=20,max_features='sqrt' ,oob_score=True, random_state=10),
   param_grid = param_test2, scoring='roc_auc',iid=False, cv=5)
gsearch2.fit(X,y)
gsearch2.grid_scores_, gsearch2.best_params_, gsearch2.best_score_

feature_importance_计算方法:

  • 袋外数据错误率评估,RF的数据是boostrap的有放回采样,形成了袋外数据。因此可以采用袋外数据(OOB)错误率进行特征重要性的评估。袋外数据错误率定义为: 袋外数据自变量值发生轻微扰动后的分类正确率与扰动前分类正确率的平均减少量。

  • 利用Gini系数计算特征的重要性,单棵树上特征的重要性定义为:特征在所有非叶节在分裂时加权不纯度的减少,减少的越多说明特征越重要。

随机森林得到的feature_importance的原理:
在随机森林中某个特征X的重要性的计算方法如下:

  • 对于随机森林中的每一颗决策树,使用相应的OOB(袋外数据)数据来计算它的袋外数据误差,记为\(err_{oob1}\).

  • 随机地对袋外数据OOB所有样本的特征X加入噪声干扰(就可以随机的改变样本在特征X处的值),再次计算它的袋外数据误差 ,记为\(err_{oob2}\).

  • 假设随机森林中有 \(N_{tree}\) 棵树,那么对于特征X的重要性\(= \sum (\frac{err_{oob2} - err_{oob1}}{N_{tree}})\),之所以可以用这个表达式来作为相应特征的重要性的度量值是因为:若给某个特征随机加入噪声之后,袋外的准确率大幅度降低,则说明这个特征对于样本的分类结果影响很大,也就是说它的重要程度比较高。

posted on 2021-04-20 19:33  朴素贝叶斯  阅读(476)  评论(0编辑  收藏  举报

导航