机器学习-浅谈随机森林的几个tricks-20170917

这篇文章不会涉及大量原理性的介绍,因为在其他地方,这种介绍已经非常多了,这里只介绍几个在随机森林中容易忽视的点。

1、随机森林每个分裂点都是随机选取m个特征

先假设我们有N个样本,M个特征,那么在这种情况下我们是如何构建随机森林的:

a、构建一棵树,我们利用自助法(bootstrap)从N个样本中选取N个样本,需要注意的是,这N个样本是大概率会有重复的,选取的这N个样本就是根节点待分裂的样本;

b、在每个待分裂节点上,我们从M个特征中随机选取m个特征(<<M,通常是log2或sqrt的数量),从这m个属性中根据某种策略(如gini减少或信息增益等)确定分裂属性;

c、重复b步骤,直到不能分裂或达到我们设定的阈值(如叶子节点数或树的深度),此时建立了一颗决策树;

d、重复上面的a、b、c步骤,直到达到预定树的颗数为止。


以上图片来自周志华的书,

所以需要注意的是:在随机森林中不是每棵树随机选择一批特征来分裂,而是在每个节点上都是随机选取的。

2、为什么绝大多数随机森林算法中用的都是cart树

在sklearn中的随机森林算法中用的就是cart树,在分类问题中,分裂方式不限于gini,也可以选entropy,在回归问题中,用的是mse和mae。

我们知道在决策树当中,不仅仅有cart算法,还有ID3和C4.5,那为什么随机森林中一般用的都是cart树呢。

首先我们来看ID3,在ID3和C4.5中都用到了一个叫做“熵”的东西,概念来自信息论,主要用来衡量事物的不确定性,如变量x的熵:


事物越不确定,熵就越大。在决策树中,用到的另外一类熵被称为条件熵,即在一定的已知条件下的熵值:


那么在ID3中,我们选择了一个叫做信息增益的指标来选择分裂特征,信息增益越大,说明选择的变量分裂后的分支下输出更纯。比如我们有15个样本集合D,输出为0或者1。其中有9个输出为0, 6个输出为1。 样本中有个特征A,取值为A1,A2和A3。在取值为A1的样本的输出中,有3个输出为1, 2个输出为0,取值为A2的样本输出中,2个输出为1,3个输出为0, 在取值为A3的样本中,4个输出为1,1个输出为0。

样本D的熵为: H(D) = -(\frac{9}{15}log_2\frac{9}{15} + \frac{6}{15}log_2\frac{6}{15}) = 0.971

样本D在特征下的条件熵为: H(D|A) = \frac{5}{15}H(D1) + \frac{5}{15}H(D2) + \frac{5}{15}H(D3) = -\frac{5}{15}(\frac{3}{5}log_2\frac{3}{5} + \frac{2}{5}log_2\frac{2}{5}) - \frac{5}{15}(\frac{2}{5}log_2\frac{2}{5} + \frac{3}{5}log_2\frac{3}{5}) -\frac{5}{15}(\frac{4}{5}log_2\frac{4}{5} + \frac{1}{5}log_2\frac{1}{5}) = 0.888

对应的信息增益为: I(D,A) = H(D) - H(D|A) = 0.083

ID3有很多明显不足的地方:比如不能处理连续性变量;不能处理缺失值;选择分裂变量时会倾向于选择类别较多的变量(理解这个问题可以想的极端一点,如ID类的特征,每一类下都只有一个输出项);容易过拟合。

针对ID3算法的不足,后续又提出了C4.5的算法。首先第一个问题,ID3不能处理连续变量,在C4.5中,会先将连续变量离散化。如我们有一个连续变量A,共有m个不同的取值 {a_1,a_2,...,a_m} ,算法首先将连续变量按照一定的顺序排列,排列后一共有m-1个切分点,切分点的值总是取相邻两个值的均值,即第t个切分点的值表示为 \frac{a_{t}+a_{t+1}}{2} ,然后根据切分点将变量一分为二。第二个问题,ID3不能处理缺失值,C4.5是有一定方法处理缺失值的,这里不展开说明。第三个问题,ID3倾向于选择类别较多的的变量,针对这个问题,C4.5引入了一个特征熵的东西:

H_A(D) = -\sum\limits_{i=1}^{n}\frac{|D_i|}{|D|}log_2\frac{|D_i|}{|D|}

其中n为特征A的类别数,Di为特征A各类别的数量,D为总样本数量,特征熵反映了一个变量类别的信息,类别越多,带来的不确定信息越多,所以C4.5基于这个指标改良了信息增益,构造了一个信息增益率的概念:

I_R(D,A) = \frac{I(A,D)}{H_A(D)}

第四个问题,C4.5中引入了正则化系数进行了初步剪枝,这里不展开。

同样,C4.5也有一些问题:C4.5生成的是多叉树,即一个父节点可以有多个节点。很多时候,在计算机中二叉树模型会比多叉树运算效率高,如果采用二叉树,可以提高效率;C4.5只能用于分类,不能用于回归;C4.5由于使用了熵模型,里面有大量耗时的对数运算,如果是连续值还有大量的排序运算,运算效率较低。

基于C4.5算法的一些缺陷,cart树可以在一定程度上解决,cart树既可以做回归,也可以做分类,为了作比较,这里只考虑分类树。

cart树里面引入了一个gini系数的概念:

在分类问题中,假设有K个类别,第k个类别的概率为pk:

Gini(p) = \sum\limits_{k=1}^{K}p_k(1-p_k) = 1- \sum\limits_{k=1}^{K}p_k^2

特别的,对于样本D,如果根据特征A的某个值a,把D分成D1和D2两部分,则在特征A的条件下,D的基尼系数表达式为:

Gini(D,A) = \frac{|D_1|}{|D|}Gini(D_1) + \frac{|D_2|}{|D|}Gini(D_2)

那么,你肯定想知道gini系数与熵的关系,这里有一幅二分类的图可以看出二者的关系:

可以看出二者非常接近,但gini的计算相比熵要简单的多,所以可以减少一定的运算量。

cart树第二个特点在于节点的分裂上,每次节点分裂都是二叉的,所以cart树就是多个二叉树组成的,这种特点使得cart算法与C4.5算法在处理离散变量上有很大的不同,离散变量在C4.5中只有一次可能出现在分裂节点上,分裂的枝数与离散变量的类别数量有关。

如某个特征A被选取建立决策树节点,如果它有A1,A2,A3三种类别,我们会在决策树上一下建立一个三叉的节点。这样导致决策树是多叉树。但是cart分类树使用的方法不同,他采用的是不停的二分,CART分类树会考虑把A分成 \{A1\}和\{A2,A3\}\{A2\}和\{A1,A3\}\{A3\}和\{A1,A2\} ,若最终选择 \{A1\}和\{A2,A3\} 作为分裂类,那么A2和A3在后续还是有可能会被再次分裂开。

因为每次都是二分裂,所以cart也没有ID3中倾向于选择类别较多的变量的缺陷。

cart树对连续变量的处理与C4.5类似。

3、为什么说bagging减少了variance,而boosting减少了bias

首先我们来看什么是variance,什么是bias,一图胜千言:

广义上的bias是指预测值与真实值之间的差值,而variance是指预测值之间的离散程度。bias比较好理解,但如何理解variance呢,variance其实也很好理解,它就是指模型之间的差异性,这个概念虽然不能量化,但理解即可。那么什么是模型之间的差异呢,不同算法之间的衡量差异的东西不一样,如逻辑回归,差异主要在于系数的不同,决策树在于树结构的不同。如果我选定了算法,什么样的模型variance是高的呢。举个例子,如果我有一个训练集D,可分为A1和A2,二者数量足够,我利用这两个训练集训练了两个模型分别是F1和F2,你发现这两个模型之间的有很大不同,如果你用了逻辑回归,可能发现系数有很大差异,那么此时意味着用A2的样本在F1上验证,或A1的样本在F2上验证,会出现准确率很低的现象,那么这就是过拟合,或者说是模型的variance很高。

我们一般认为集成学习中的基模型是一种弱模型,即bias高,variance高的模型,但在不同的框架下,基模型弱的程度其实是不一样的。在bagging和boosting框架中,通过计算基模型的期望和方差,我们可以得到模型整体的期望和方差。为了简化模型,我们假设基模型的权重、方差及两两间的相关系数相等。由于bagging和boosting的基模型都是线性组成的,那么有:

E是期望函数,Var是方差函数,F是整体模型,fi是第i个基模型,gamma是基模型权重, \rho 是基模型相关系数,sigma^2是基模型方差。

对于bagging来说,每个基模型的权重等于1/m且期望近似相等(子训练集都是从原训练集中进行子抽样),那么bagging的偏差和方差可以表示为:

我们可以看到,整体模型的准确率与基模型的准确率相差无几;整体模型的方差受基模型的方差,相关系数和基模型个数影响,我们看到基模型个数越大,可以降低模型的过拟合,但当m增大到一定程度时,降低模型过拟合的能力达到极限。同时降低基模型之间的相关性,也可以降低模型的过拟合,这也是为什么随机森林中采用行和列随机的方式构建树。

对于boosting来说,基模型的训练集抽样是强相关的(假设没有进行子抽样,虽然不准确),那么模型的相关系数近似等于1,boosting的偏差和方差:

从原理上很好理解,boosting降低bias,即增加基模型的个数逼近目标,但同样我们也发现boosting的方差是随着基模型的个数逐渐增大的,所以当我们增大基模型个数提高准确率时,整体模型的方差也随之增大了。

4、随机森林的变量重要性真的能衡量变量的重要程度吗

上面这个问题的答案既“是”也“不是”,换句话说,随机森林的变量重要性衡量的并不完全是变量对目标变量预测的贡献能力,而是在这个模型中对目标变量预测的贡献能力。

要理解上面这句话,首先我们来看随机森林中变量的重要性是如何计算的。常见的计算方法有两种,一种是mean decrease impurity,即平均不纯度的减少,现在sklearn中用的就是这种方法;一种是mean decrease accuracy,即平均准确率的减少,常用袋外误差率去衡量。

以上两种计算方法从字面上应该都很好理解,但这两种方法来衡量变量重要性有一定的陷阱。假设我们有两个变量,分别是A和B,A和B之间有较强的相关性,如果A对模型贡献度较大,由于B很像A,所以B也应该对模型贡献较大,但实际情况并不会这样。我们来看一个实际的例子,分别是一个变量,加上了相似的噪音:

size = 10000
np.random.seed(seed=10)
X_seed = np.random.normal(0, 1, size)
X0 = X_seed + np.random.normal(0, .1, size)
X1 = X_seed + np.random.normal(0, .1, size)
X2 = X_seed + np.random.normal(0, .1, size)
X = np.array([X0, X1, X2]).T
Y = X0 + X1 + X2
  
rf = RandomForestRegressor(n_estimators=20, max_features=2)
rf.fit(X, Y);
print "Scores for X0, X1, X2:", map(lambda x:round (x,3),
                                    rf.feature_importances_)
Scores for X0, X1, X2: [0.278, 0.66, 0.062]

我们可以清楚的看到X1与X2的变量重要性相差10倍左右,但实际上二者其实是很相似的。

另外一个trick是随机森林中类别数较多的变量会倾向于有较高的变量重要性,这个问题可以从dummy化去考虑,由于类别较多的变量横向dummy化的变量较多,其被选进m特征的概率会比其他变量更高。

所以变量重要性要慎用。

5、随机森林可以处理相关性较强的变量吗

这个问题是接着上一个问的,答案是在一定程度可以,但建议剔除相关性较强的变量,降低这种影响。

我们首先来看,为什么相关性较强的一些变量会影响随机森林。在随机森林的步骤中,有一步是要求每次分裂都从随机的m个特征中选择一特征作为分裂特征,这种随机性就是为了使得树与树之间的相关性变低,或者说变得不一样。如果变量集里面出现了两个完全一致(相关性的极端)的变量,那该变量被选到m个变量的机会就会变高,那么构造出来的树就会变得越像,树与树之间的相关性就会变高,那么随机森林的泛化的能力就会变差。换句话说,这些相似的变量挤占了带有其他信息的变量入模的机会,从而使得模型变差。

6、有些变量dummy化,有些变量不dummy会对模型有影响吗

当变量中有缺失值时,我们通常会将变量dummy化,尤其当这个变量是连续变量时,会先简单离散,再dummy化。那如果某一连续变量没有缺失值,我们知道cart树是可以处理缺失值的,这种情况下可以不离散dummy化吗。

我的答案是不能,因为其他变量dummy化后,意味着其他变量的横向维度变多了,那么会影响随机森林分裂时随机选取m变量的概率,即没有dummy化的变量,被选到的可能性会变低,从而影响树的结构。


引用文章如下:

决策树算法原理(上) - 刘建平Pinard - 博客园

使用sklearn进行集成学习--理论 - jasonfreak - 博客园

说说随机森林

为什么说bagging是减少variance,而boosting是减少bias?

Selecting good features - Part III: random forests

Bias in random forest variable importance measures: Illustrations, sources and a solution

编辑于 2017-09-18

文章被以下专栏收录