关灯

Sklearn 与 TensorFlow 机器学习实用指南第7章 集成学习和随机森林 (中)

[复制链接]
admin 发表于 2019-1-20 13:04:46 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
 

随机贴片与随机子空间

  1. BaggingClassifier
复制代码
也支持采样特征。它被两个超参数
  1. max_features
复制代码
  1. bootstrap_features
复制代码
控制。他们的工作方式和
  1. max_samples
复制代码
  1. bootstrap
复制代码
一样,但这是对于特征采样而不是实例采样。因此,每一个分类器都会被在随机的输入特征内进行训练。

 

当你在处理高维度输入下(例如图片)此方法尤其有效。对训练实例和特征的采样被叫做随机贴片。保留了所有的训练实例(例如

  1. bootstrap=False
复制代码
  1. max_samples=1.0
复制代码
),但是对特征采样(
  1. bootstrap_features=True
复制代码
并且/或者
  1. max_features
复制代码
小于 1.0)叫做随机子空间。

 

采样特征导致更多的预测多样性,用高偏差换低方差。

 

 

随机森林 

正如我们所讨论的,随机森林是决策树的一种集成,通常是通过 bagging 方法(有时是 pasting 方法)进行训练,通常用

  1. max_samples
复制代码
设置为训练集的大小。与建立一个
  1. BaggingClassifier
复制代码
然后把它放入 DecisionTreeClassifier 相反,你可以使用更方便的也是对决策树优化够的
  1. RandomForestClassifier
复制代码
(对于回归是
  1. RandomForestRegressor
复制代码
)。接下来的代码训练了带有 500 个树(每个被限制为 16 叶子结点)的决策森林,使用所有空闲的 CPU 核:

  1. >>>from sklearn.ensemble import RandomForestClassifier
  2. >>>rnd_clf = RandomForestClassifier(n_estimators=500, max_leaf_nodes=16, n_jobs=-1)
  3. >>>rnd_clf.fit(X_train, y_train)
  4. >>>y_pred_rf = rnd_clf.predict(X_test)
复制代码

除了一些例外,

  1. RandomForestClassifier
复制代码
使用
  1. DecisionTreeClassifier
复制代码
的所有超参数(决定数怎么生长),把
  1. BaggingClassifier
复制代码
的超参数加起来来控制集成本身。

 

随机森林算法在树生长时引入了额外的随机;与在节点分裂时需要找到最好分裂特征相反(详见第六章),它在一个随机的特征集中找最好的特征。它导致了树的差异性,并且再一次用高偏差换低方差,总的来说是一个更好的模型。以下是

  1. BaggingClassifier
复制代码
大致相当于之前的
  1. randomforestclassifier
复制代码

 

  1. >>>bag_clf = BaggingClassifier(DecisionTreeClassifier(splitter="random", max_leaf_nodes=16),n_estimators=500, max_samples=1.0, bootstrap=True, n_jobs=-1)
复制代码

 

 

极端随机树 

当你在随机森林上生长树时,在每个结点分裂时只考虑随机特征集上的特征(正如之前讨论过的一样)。相比于找到更好的特征我们可以通过使用对特征使用随机阈值使树更加随机(像规则决策树一样)。

 

这种极端随机的树被简称为 Extremely Randomized Trees(极端随机树),或者更简单的称为 Extra-Tree。再一次用高偏差换低方差。它还使得 Extra-Tree 比规则的随机森林更快地训练,因为在每个节点上找到每个特征的最佳阈值是生长树最耗时的任务之一。

 

你可以使用 sklearn 的

  1. ExtraTreesClassifier
复制代码
来创建一个 Extra-Tree 分类器。他的 API 跟
  1. RandomForestClassifier
复制代码
是相同的,相似的, ExtraTreesRegressor 跟
  1. RandomForestRegressor
复制代码
也是相同的 API。

 

我们很难去分辨

  1. ExtraTreesClassifier
复制代码
  1. RandomForestClassifier
复制代码
到底哪个更好。通常情况下是通过交叉验证来比较它们(使用网格搜索调整超参数)。

 

 

特征重要度 

最后,如果你观察一个单一决策树,重要的特征会出现在更靠近根部的位置,而不重要的特征会经常出现在靠近叶子的位置。因此我们可以通过计算一个特征在森林的全部树中出现的平均深度来预测特征的重要性。sklearn 在训练后会自动计算每个特征的重要度。你可以通过

  1. feature_importances_
复制代码
变量来查看结果。例如如下代码在 iris 数据集(第四章介绍)上训练了一个
  1. RandomForestClassifier
复制代码
模型,然后输出了每个特征的重要性。看来,最重要的特征是花瓣长度(44%)和宽度(42%),而萼片长度和宽度相对比较是不重要的(分别为 11% 和 2%):   

  1. >>> from sklearn.datasets import load_iris
  2. >>> iris = load_iris()
  3. >>> rnd_clf = RandomForestClassifier(n_estimators=500, n_jobs=-1)
  4. >>> rnd_clf.fit(iris["data"], iris["target"])
  5. >>> for name, score in zip(iris["feature_names"], rnd_clf.feature_importances_):
  6. >>>     print(name, score)
  7. sepal length (cm) 0.112492250999
  8. sepal width (cm) 0.0231192882825
  9. petal length (cm) 0.441030464364
  10. petal width (cm) 0.423357996355
复制代码

相似的,如果你在 MNIST 数据及上训练随机森林分类器(在第三章上介绍),然后画出每个像素的重要性,你可以得到图 7-6 的图片。

1532672897510877094.jpg

随机森林可以非常方便快速得了解哪些特征实际上是重要的,特别是你需要进行特征选择的时候。

 

 

提升 

提升(Boosting,最初称为假设增强)指的是可以将几个弱学习者组合成强学习者的集成方法。对于大多数的提升方法的思想就是按顺序去训练分类器,每一个都要尝试修正前面的分类。现如今已经有很多的提升方法了,但最著名的就是 Adaboost(适应性提升,是 Adaptive Boosting 的简称) 和 Gradient Boosting(梯度提升)。让我们先从 Adaboost 说起。

 

Adaboost 

使一个新的分类器去修正之前分类结果的方法就是对之前分类结果不对的训练实例多加关注。这导致新的预测因子越来越多地聚焦于这种情况。这是 Adaboost 使用的技术。

 

举个例子,去构建一个 Adaboost 分类器,第一个基分类器(例如一个决策树)被训练然后在训练集上做预测,在误分类训练实例上的权重就增加了。第二个分类机使用更新过的权重然后再一次训练,权重更新,以此类推(详见图 7-7

1532672890114741381.jpg

 

图 7-8 显示连续五次预测的 moons 数据集的决策边界(在本例中,每一个分类器都是高度正则化带有 RBF 核的 SVM)。第一个分类器误分类了很多实例,所以它们的权重被提升了。第二个分类器因此对这些误分类的实例分类效果更好,以此类推。右边的图代表了除了学习率减半外(误分类实例权重每次迭代上升一半)相同的预测序列。你可以看出,序列学习技术与梯度下降很相似,除了调整单个预测因子的参数以最小化代价函数之外,AdaBoost 增加了集合的预测器,逐渐使其更好。

1532672883730282504.jpg

 

一旦所有的分类器都被训练后,除了分类器根据整个训练集上的准确率被赋予的权重外,集成预测就非常像Bagging和Pasting了。

 

序列学习技术的一个重要的缺点就是:它不能被并行化(只能按步骤),因为每个分类器只能在之前的分类器已经被训练和评价后再进行训练。因此,它不像Bagging和Pasting一样。

 

让我们详细看一下 Adaboost 算法。每一个实例的权重

  1. wi
复制代码
初始都被设为
  1. 1/m
复制代码
第一个分类器被训练,然后他的权重误差率
  1. r1
复制代码
在训练集上算出,详见公式 7-1。

公式7-1:第

  1. j
复制代码
个分类器的权重误差率

1532672864001751357.jpg

 

其中 1532672872581307980.jpg 是第

  1. j
复制代码
个分类器对于第
  1. i
复制代码
实例的预测。

 

分类器的权重 j 随后用公式 7-2 计算出来。其中

  1. η
复制代码
是超参数学习率(默认为 1)。

 

分类器准确率越高,它的权重就越高。如果它只是瞎猜,那么它的权重会趋近于 0。然而,如果它总是出错(比瞎猜的几率都低),它的权重会使负数。

 

公式 7-2:分类器权重

 

1532672854352787721.jpg

 

接下来实例的权重会按照公式 7-3 更新:误分类的实例权重会被提升。

公式7-3 权重更新规则

对于

  1. i=1, 2, ..., m
复制代码

 

1532672846643280087.jpg

 

随后所有实例的权重都被归一化(例如被 1532672839610218142.jpg 整除)

 

最后,一个新的分类器通过更新过的权重训练,整个过程被重复(新的分类器权重被计算,实例的权重被更新,随后另一个分类器被训练,以此类推)。当规定的分类器数量达到或者最好的分类器被找到后算法就会停止。

 

为了进行预测,Adaboost 通过分类器权重 j 简单的计算了所有的分类器和权重。预测类别会是权重投票中主要的类别。(详见公式 7-4)

 

公式7-4: Adaboost 分类器

1532672831802924391.jpg

其中

  1. N
复制代码
是分类器的数量。 

 

sklearn 通常使用 Adaboost 的多分类版本 SAMME(这就代表了 分段加建模使用多类指数损失函数)。如果只有两类别,那么 SAMME 是与 Adaboost 相同的。如果分类器可以预测类别概率(例如如果它们有

  1. predict_proba()
复制代码
),如果 sklearn 可以使用 SAMME 叫做
  1. SAMME.R
复制代码
的变量(R 代表“REAL”),这种依赖于类别概率的通常比依赖于分类器的更好。

 

接下来的代码训练了使用 sklearn 的

  1. AdaBoostClassifier
复制代码
基于 200 个决策树桩 Adaboost 分类器(正如你说期待的,对于回归也有
  1. AdaBoostRegressor
复制代码
)。一个决策树桩是
  1. max_depth=1
复制代码
的决策树-换句话说,是一个单一的决策节点加上两个叶子结点。这就是
  1. AdaBoostClassifier
复制代码
的默认基分类器:

  1. >>>from sklearn.ensemble import AdaBoostClassifier
  2. >>>ada_clf = AdaBoostClassifier(DecisionTreeClassifier(max_depth=1), n_estimators=200,algorithm="SAMME.R", learning_rate=0.5)
  3. >>>ada_clf.fit(X_train, y_train)
复制代码

如果你的 Adaboost 集成过拟合了训练集,你可以尝试减少基分类器的数量或者对基分类器使用更强的正则化。

回复

使用道具 举报

 
*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


1关注

0粉丝

1603帖子

排行榜

关注我们:微信订阅号

官方微信

APP下载

全国服务热线:

4000-018-018

公司地址:上海市嘉定区银翔路655号B区1068室

运营中心:成都市锦江区东华正街42号广电仕百达国际大厦25楼

邮编:610066 Email:3318850993#qq.com

Copyright   ©2015-2016  比特趋势Powered by©Discuz!技术支持:迪恩网络