【机器学习】随机森林原理与调参小结

之前在集成原理小结中总结了Bagging的原理。 理解了bagging算法,随机森林(Random Forest,以下简称RF)就好理解了。它是Bagging算法的进化版,也就是说,它的思想仍然是bagging,但是进行了独有的改进。

1. 随机森林的原理(普通bagging的升级版)

第一,RF使用了CART决策树作为弱学习器。第二,在使用决策树的基础上,RF对决策树的建立做了改进,对于普通的决策树,我们会在节点上所有的n个样本特征中选择一个最优的特征来做决策树的左右子树划分,但是RF是会在节点上随机选择一部分样本特征,然后在这些随机选择的部分样本特征中,选择一个最优的特征来做决策树的左右子树划分。这样进一步增强了模型的泛化能力。    

假设RF中节点上所有的特征为n个,随机选择的部分特征为 ns个。

  • 如果ns=n,则此时RF的CART决策树和普通的CART决策树没有区别。
  • ns越小,则模型约健壮,当然此时对于训练集的拟合程度会变差。也就是说ns越小,模型的方差会减小,但是偏差会增大。在实际案例中,一般会通过交叉验证调参获取一个合适的ns的值。

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

输入为样本集D={(x,y1),(x2,y2),...(xm,ym)},弱分类器迭代次数T。

输出为最终的强分类器f(x)
1)对于t=1,2...,T:

  a)对训练集进行第t次随机采样,共采集m次,得到包含m个样本的采样集Dt
  b)用采样集Dt训练第t个决策树模型Gt(x),在训练决策树模型的节点的时候, 在节点上所有的样本特征中选择一部分样本特征, 在这些随机选择的部分样本特征中选择一个最优的特征来做决策树的左右子树划分

2) 如果是分类算法预测,则T个弱学习器投出最多票数的类别或者类别之一为最终类别。如果是回归算法,T个弱学习器得到的回归结果进行算术平均得到的值为最终的模型输出。

2.随机森林的特点

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

(1)优点

1) 训练可以高度并行化,对于大数据时代的大样本训练速度有优势。个人觉得这是的最主要的优点。

2) 由于采用随机采样,可以防止模型过拟合。训练出的模型的方差小,泛化能力强。

3) 由于可以随机选择决策树节点划分的特征,这样在样本特征维度很高的时候,不用降维,无需做特征选择,仍然能高效的训练模型,。

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

5) 对部分特征缺失不敏感。

6) 在训练后,可以给出各个特征对于输出的重要性,模型有可解释性

(2) 缺点

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

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

3. 随机森林的实现和调参

在 scikit-learn 中,随机森林的实现用集成包ensemble 中 RandomForestClassifier类。

from sklearn.ensemble import RandomForestClassifier

class sklearn.ensemble.RandomForestClassifier (n_estimators=’10’, 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)

1. 重要参数

  • 基评估器的参数
    随机森林的基评估器是决策树,单个决策树的准确率越高,随机森林的准确率也会越高,因为装袋法是依赖于平均值或
    者少数服从多数原则来决定集成的结果的。

  • n_estimators
    这是森林中树木的数量,即基评估器的数量。一般n_estimators越大,模型的效果往往越好。但是超过边界后,随机森林的精确性往往不在上升或开始波动,同时n_estimators越大,需要的计算量和内存也越大,训练的时间也会越来越长。对于这个参数,我们是渴望在训练难度和模型效果之间取得平衡。
    现在的版本中个默认值为100。

# 单个决策树和随机森林,10折交叉验证的平均准确率结果对比
%matplotlib inline
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_wine  
from sklearn.model_selection import cross_val_score
import matplotlib.pyplot as plt

wine = load_wine()
wine.data
wine.target

rfc_l = []
clf_l = []
for i in range(10):
    rfc = RandomForestClassifier(n_estimators=25)
    rfc_s = cross_val_score(rfc,wine.data,wine.target,cv=10).mean()
    rfc_l.append(rfc_s)
    clf = DecisionTreeClassifier()
    clf_s = cross_val_score(clf,wine.data,wine.target,cv=10).mean()
    clf_l.append(clf_s)
    
plt.plot(range(1,11),rfc_l,label = "Random Forest")
plt.plot(range(1,11),clf_l,label = "Decision Tree")
plt.legend()
plt.show()

# 随机森林中,模型准确率与森林中决策树的数量的关系
superpa = []
for i in range(100):
    rfc = RandomForestClassifier(n_estimators=i+1,n_jobs=-1)
    rfc_s = cross_val_score(rfc,wine.data,wine.target,cv=10).mean()
    superpa.append(rfc_s)
    
print(max(superpa),superpa.index(max(superpa)))
plt.figure(figsize=[20,5])
plt.plot(range(1,101),superpa)
plt.show()  
0.9888888888888889 40
  • random_state
    由于决策树从最重要的特征中随机选择出一个特征来进行分枝,因此每次生成的决策树都不一样,这个功能由参数random_state控制。
    随机森林中其实也有random_state,用法和分类树中相似,只不过在分类树中,一个random_state只控制生成一棵树,而随机森林中的random_state控制的是生成森林的模式,而非让一个森林中只有一棵树。
    random_state指定一个随机数种子,会生成一组固定的树。
rfc = RandomForestClassifier(n_estimators=20,random_state=2)
rfc = rfc.fit(Xtrain, Ytrain)
#随机森林的重要属性之一:estimators,查看森林中树的状况
# 森林中的每一棵树都有自己的随机数种子
for i in range(len(rfc.estimators_)):
    print(rfc.estimators_[i].random_state)
1872583848
794921487
111352301
1853453896
213298710
1922988331
1869695442
2081981515
1805465960
1376693511
1418777250
663257521
878959199
854108747
512264917
515183663
1287007039
2083814687
1146014426
570104212
  • bootstrap & oob_score

随机森林采用bootstrap的随机采样,即有放回的随机抽样基数,参数默认bootstrap = True。一般不做修改。

随机森林由于是有放回的抽样,一些样本可能在同一个自助集中出现多次,而其他一些却可能被忽略,一般来说,自助集大约平均会包含63%的原始数据。会有约37%的训练数据被浪费掉,没有参与建模,这些数据被称为袋外数据(out of bag data,简写为oob)。除了我们最开始就划分好的测试集之外,这些数据也可以被用来作为集成算法的测试集。

如果希望用袋外数据来测试,则需要在实例化时就将oob_score这个参数调整为True,训练完后,用oob_score_ 属性来查看我们的在袋外数据上测试的结果。

#无需划分训练集和测试集
rfc = RandomForestClassifier(n_estimators=25,oob_score=True)
rfc = rfc.fit(wine.data,wine.target)
#重要属性oob_score_
rfc.oob_score_
0.9606741573033708

以下对随机森林调参模型的优先级做了总结:

2.重要的属性和接口

随机森林的接口与决策树完全一致,因此依然有四个常用接口:apply, fit, predict和score。
除此之外,还需要注意随机森林的predict_proba接口,这个接口返回每个测试样本对应的被分到每一类标签的概率,标签有几个分类
就返回几个概率。

传统的随机森林是利用袋装法中的规则,平均或少数服从多数来决定集成的结果,而sklearn中的随机森林是平均每个弱分类器对应的predict_proba返回的概率,得到一个平均概率,从而决定测试样本的分类 。

# 常用的属性和接口
rfc = RandomForestClassifier(n_estimators=25)
rfc = rfc.fit(Xtrain, Ytrain)
rfc.score(Xtest,Ytest)
rfc.feature_importances_
rfc.apply(Xtest)
rfc.predict(Xtest)
rfc.predict_proba(Xtest)
array([[0.04, 0.92, 0.04],
       [0.28, 0.64, 0.08],
       [0.  , 1.  , 0.  ],
       [0.88, 0.08, 0.04],
       [0.92, 0.08, 0.  ],
       [0.04, 0.92, 0.04],
       [0.  , 0.92, 0.08],
       [1.  , 0.  , 0.  ],
       [1.  , 0.  , 0.  ],
       [0.  , 0.88, 0.12],
       [0.  , 1.  , 0.  ],
       [0.8 , 0.12, 0.08],
       [0.04, 0.92, 0.04],
       [0.04, 0.16, 0.8 ],
       [0.12, 0.8 , 0.08],
       [0.12, 0.44, 0.44],
       [0.  , 1.  , 0.  ],
       [0.16, 0.76, 0.08],
       [1.  , 0.  , 0.  ],
       [0.12, 0.08, 0.8 ],
       [0.4 , 0.44, 0.16],
       [0.  , 0.04, 0.96],
       [0.  , 0.2 , 0.8 ],
       [1.  , 0.  , 0.  ],
       [0.2 , 0.68, 0.12],
       [0.96, 0.04, 0.  ],
       [1.  , 0.  , 0.  ],
       [0.  , 0.16, 0.84],
       [0.  , 0.92, 0.08],
       [0.  , 0.4 , 0.6 ],
       [0.  , 0.04, 0.96],
       [0.48, 0.44, 0.08],
       [0.2 , 0.8 , 0.  ],
       [0.92, 0.08, 0.  ],
       [0.84, 0.04, 0.12],
       [0.04, 0.92, 0.04],
       [1.  , 0.  , 0.  ],
       [1.  , 0.  , 0.  ],
       [0.04, 0.96, 0.  ],
       [1.  , 0.  , 0.  ],
       [0.  , 0.52, 0.48],
       [1.  , 0.  , 0.  ],
       [1.  , 0.  , 0.  ],
       [0.24, 0.76, 0.  ],
       [0.  , 0.  , 1.  ],
       [1.  , 0.  , 0.  ],
       [1.  , 0.  , 0.  ],
       [1.  , 0.  , 0.  ],
       [1.  , 0.  , 0.  ],
       [0.04, 0.88, 0.08],
       [0.88, 0.04, 0.08],
       [0.  , 0.88, 0.12],
       [0.  , 0.08, 0.92],
       [1.  , 0.  , 0.  ]])
原文地址:https://www.cnblogs.com/laiyaling/p/14047595.html