随机森林
前面几个小节介绍了 Bagging 集成学习方法。简单来说,Bagging 方式是通过在样本以及特征空间上随机选取样本以及特征的方式来创建诸多差异性的子模型,然后将这些子模型集成在一起。使用 sklearn 实现 Bagging 这种集成学习,使用的基本分类器都是决策树,这种基本分类器使用决策树的集成学习通常被称为随机森林。 随机森林中的每一棵树都是通过随机的方式来训练生成的,因此具有随机性,这么多树放在一起,就形成了一个森林。前面实现的 Bagging Classifier,无论是 random subspaces classifier 还是 random patches classifier,指定的 base_estimator 参数都是 DecisionTreeClassifier(sklearn 封装的决策树类),因此都可以叫做随机森林。
在 sklearn 中,除了手动的指定 base_estimator 参数为决策树之外,sklearn 还专门封装了一个随机森林的类,我们可以非常容易的创建一个随机森林这样的集成学习模型,与此同时 sklearn 为我们封装的随机森林类还提供了更多的随机性。回忆前面学习过的决策树,在训练决策树的过程中,其实就是在每一个节点上进行划分,划分的依据是找到最好的维度(特征)以及相应的最优阈值。sklearn 封装的随机森林,在训练每一棵决策树的时,在每个节点上并不是在所有特征上去寻找最优的划分,而是在一个随机的特征子集上寻找最优的划分,这种划分方式增加了集成学习中子模型的随机性。 子模型之间越有差异性越有利于集成学习,而创造差异性的其中一种方式就是增加随机性,sklearn 封装的随机森林在随机的特征子集上寻找最优划分,进一步增加了随机性。
sklearn 封装的随机森林
接下来,看看如何使用 sklearn 封装好的随机森林类。
代码语言:javascript复制import numpy as np
import matplotlib.pyplot as plt
本小节使用分布呈现交错半圆形的二分类虚拟数据集,使用 sklearn.datasets 包下的 make_moons 函数即可生成这样的虚拟数据集。
代码语言:javascript复制from sklearn import datasets
X, y = datasets.make_moons(n_samples = 500,
noise = 0.3,
random_state = 666)
在使用 make_moons 函数时指定三个参数:
- n_samples,生成样本点的总数。默认为 100 个,由于本章需要的数据量相对比较大,因此将 n_samples 设置为 500;
- noise,加到数据集中的高斯噪声的标准差。默认为 None,noise 的值越小,生成的数据集呈现交错半圆形的分布形状越明显,noise 的值越大,生成的数据集呈现交错半圆形的分布形状越不明显,此时将 noise 设置为相对比较大的 0.3;
- random_state,随机种子。设置固定的随机种子,能够保证多次试验结果的一致性;
使用散点图将生成的虚拟数据集绘制出来。
代码语言:javascript复制plt.scatter(X[y == 0, 0], X[y == 0, 1])
plt.scatter(X[y == 1, 0], X[y == 1, 1])
plt.show()
使用 sklearn 封装好的随机森林非常简单,只需要从 ensemble(集成学习模块)中导入 RandomForestClassifier 类。
代码语言:javascript复制from sklearn.ensemble import RandomForestClassifier
rf_clf = RandomForestClassifier(n_estimators = 500,
oob_score = True,
random_state = 666,
n_jobs = -1)
rf_clf.fit(X, y)
代码语言:javascript复制RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',
max_depth=None, max_features='auto', max_leaf_nodes=None,
min_impurity_decrease=0.0, min_impurity_split=None,
min_samples_leaf=1, min_samples_split=2,
min_weight_fraction_leaf=0.0, n_estimators=500, n_jobs=-1,
oob_score=True, random_state=666, verbose=0, warm_start=False)
通过调用 fit 函数输出的结果可以看出,sklearn 实现的随机森林类的参数大部分在决策树分类器中能够找到,另外一些参数基本上在 BaggingClassifier 中也能够找到。这其实很好理解,因为随机森林的实质就是分类器为决策树和 Bagging 集成学习方式的结合。这其中:
- n_estimators,随机森林中决策树的个数;
- oob_socre,是否使用 oob 的那些样本对整个集成学习模型进行评估;
- random_state,随机种子。设置固定的随机种子,能够保证多次试验结果的一致性;
- n_jobs,随机森林极易进行并行化处理,传入 n_jobs 的参数值代表算法使用计算机中的几个核,如果传入 -1 则会使用计算机中的所有 CPU 核
使用 oob 样本对集成学习模型进行评估。
代码语言:javascript复制rf_clf.oob_score_
# 0.892
Extra-Trees
Extra-Trees (Extremely randomized trees,极度随机树) 方法和随机森林非常相似,有时也会将 Extra-Trees 称为随机森林。Extra-Trees 相比于随机森林,极度随机表现在对决策树节点的划分上,Extra-Trees 直接使用一个随机的特征以及随机特征上的随机阈值进行划分。 Extra-Trees 中的每个子模型(决策树)的随机性会变得更大,因此每个子模型(决策树)之间的差异性更大。每个子模型随机性变得更大,意味着每个子模型的性能会大大的降低,不过在介绍 Bagging 原理时,提到过我们只需要保证大多数子模型的性能比扔硬币好一点就足够了,集成成百上千这样的决策树子模型,最终集成学习的结果也会很不错,这也是 Extra-Trees 这种极度随机的集成学习具有价值的理论依据。
Extra-Trees 这种方式提供了非常强烈的额外的随机性,这种随机性可以抑制过拟合,不会因为某几个极端的样本点而将整个模型带偏,这是因为每棵决策树都是极度随机的,所以很有可能大部分决策树是看不到这些特别极端的样本点的,整个模型的过拟合现象会得到抑制。抑制过拟合就是降低了方差,与此同时也会增大了偏差,因此在使用 Extra-Trees 之前,需要检查样本数据以及要解决的问题是否适合使用 Extra-Trees。
Extra-Trees 由于划分方式完全是随机的,直接使用随机的特征以及随机的阈值进行划分。因此相比于随机森林而言,Extra-Trees 的训练速度要更快。
简单总结一下 Extra-Trees:
- 相比于随机森林,Extra-Trees 中的决策树子模型在节点划分上,使用随机的特征和随机的阈值;
- Extra-Trees 能够提供额外的随机性,抑制过拟合,降低方差,与此同时也会增大偏差;
- Extra-Trees 相比于随机森林,拥有更快的训练速度;
sklearn 封装的 Extra-Trees
使用 sklearn 封装好的随机森林非常简单,只需要从 ensemble(集成学习模块)中导入 ExtraTreesClassifier 类。
代码语言:javascript复制from sklearn.ensemble import ExtraTreesClassifier
et_clf = ExtraTreesClassifier(n_estimators = 500,
bootstrap = True,
oob_score = True,
random_state = 666,
n_jobs = -1)
et_clf.fit(X, y)
代码语言:javascript复制ExtraTreesClassifier(bootstrap=True, class_weight=None, criterion='gini',
max_depth=None, max_features='auto', max_leaf_nodes=None,
min_impurity_decrease=0.0, min_impurity_split=None,
min_samples_leaf=1, min_samples_split=2,
min_weight_fraction_leaf=0.0, n_estimators=500, n_jobs=-1,
oob_score=True, random_state=666, verbose=0, warm_start=False)
类似的,通过调用 fit 函数输出的结果可以看出,sklearn 实现的 Extra-Trees 类的参数大部分在决策树分类器中能够找到,另外一些参数基本上在 BaggingClassifier 中也能够找到。
使用 oob 样本对集成学习模型进行评估。
代码语言:javascript复制et_clf.oob_score_
# 0.892
集成学习解决回归问题
前面介绍了很多集成学习方法,不过在具体实例中,解决的都是分类问题,其实集成学习也是能够解决回归问题的。
代码语言:javascript复制from sklearn.ensemble import BaggingRegressor
from sklearn.ensemble import RandomForestRegressor
from sklearn.ensemble import ExtraTreesRegressor
这些解决回归问题的集成学习类和解决分类问题的集成学习类的使用方式几乎是一致的,只不过对于回归问题来说,最终的输出结果是一个具体的数值。
References:
- Python3入门机器学习 经典算法与应用: https://coding.imooc.com/class/chapter/169.html#Anchor