提交 5785538b 编写于 作者: F friedhelm

4-19

上级 c40f24c9
...@@ -212,18 +212,139 @@ petal width (cm) 0.423357996355 ...@@ -212,18 +212,139 @@ petal width (cm) 0.423357996355
其中 $\widetilde{y_{j}}^{i}$ 是第 $j^{th}$ 个分类器对于第 $i^{th}$ 实例的预测。 其中 $\widetilde{y_{j}}^{i}$ 是第 $j^{th}$ 个分类器对于第 $i^{th}$ 实例的预测。
分类器的权重 $α_{j}$ 随后用公式7-2计算出来。其中`η`是超参数学习率(默认为1)。分类器准确率越高,它的权重就越高。如果它只是瞎猜,那么它的权重会趋近于0.然而,如果它总是出错(比瞎猜的几率都低),它的权重会使负数。
公式7-2: 分类器权重
![公式7-2](../images/chapter_7/E7-2.png)
接下来实例的权重会按照公式7-3更新:误分类的实例权重会被提升。
公式7-3 权重更新规则
对于 `i=1,2···,m`
![公式7-3](../images/chapter_7/E7-3.png)
随后所有实例的权重都被归一化(例如被 $\sum_{i=1}^{m}w^{i}$ 整除)
最后,一个新的分类器通过更新过的权重训练,整个过程被重复(新的分类器权重被计算,实例的权重被更新,随后另一个分类器被训练,以此类推)。当规定的分类器数量达到或者最好的分类器被找到后算法就会停止。
为了进行预测,Adaboost通过分类器权重 $α_{j}$ 简单的计算了所有的分类器和权重。预测类别会是权重投票中主要的类别。(详见公式7-4)
公式7-4: Adaboost分类器
![公式7-4](../images/chapter_7/E7-4.png)
其中`N`是分类器的数量。
sklearn通常使用Adaboost的多分类版本 *SAMME* (这就代表了 *分段加建模使用多类指数损失函数* ) 。如果只有两类别,那么 *SAMME* 是与Adaboost相同的。如果分类器可以预测类别概率(例如如果它们有 *predict_proba()* ),如果sklearn可以使用 *SAMME* 叫做 *SAMME.R* 的变量(R代表“REAL”),这种依赖于类别概率的通常比依赖于分类器的更好。
接下来的代码训练了使用sklearn的 *AdaBoostClassifier* 基于200个决策树桩Adaboost分类器(正如你说期待的,对于回归也有 *AdaBoostRegressor* )。一个决策树桩是 *max_depth=1*的决策树-换句话说,是一个单一的决策节点加上两个叶子结点。这就是 *AdaBoostClassifier* 的默认基分类器:
```python ```python
>>>from sklearn.ensemble import BaggingClassifier >>>from sklearn.ensemble import AdaBoostClassifier
>>>from sklearn.tree import DecisionTreeClassifier >>>ada_clf = AdaBoostClassifier(DecisionTreeClassifier(max_depth=1), n_estimators=200,algorithm="SAMME.R", learning_rate=0.5)
>>>bag_clf = BaggingClassifier(DecisionTreeClassifier(), n_estimators=500, >>>max_samples=100, bootstrap=True, n_jobs=-1) >>>ada_clf.fit(X_train, y_train)
>>>bag_clf.fit(X_train, y_train)
>>>y_pred = bag_clf.predict(X_test)
``` ```
如果你的Adaboost集成过拟合了训练集,你可以尝试减少基分类器的数量或者对基分类器使用更强的正则化。
## Gradient Boosting
另一个非常著名的提升算法是 *Gradient Boosting* (梯度提升)。与Adaboost一样,梯度提升也是通过向集成中逐步增加分类器运行的,每一个分类器都修正之前的分类结果。然而,它并不像Adaboost那样每一次迭代都更改实例的权重,这个方法是去使用新的分类器去拟合前面分类器预测的 *残差*
让我们通过一个使用决策树当做基分类器的简单的回归例子(回归当然也可以使用梯度提升)。这被叫做 *Gradient Tree Boosting* 或者 *Gradient Boosted Regression Trees* (GBRT)。首先我们用 *DecisionTreeRegressor* 去拟合训练集(例如一个有噪二次训练集):
```python
>>>from sklearn.tree import DecisionTreeRegressor
>>>tree_reg1 = DecisionTreeRegressor(max_depth=2)
>>>tree_reg1.fit(X, y)
```
现在在第一个分类器的残差上训练第二个分类器:
```python
>>>y2 = y - tree_reg1.predict(X)
>>>tree_reg2 = DecisionTreeRegressor(max_depth=2)
>>>tree_reg2.fit(X, y2)
```
随后在第二个分类器的残差上训练第三个分类器:
```python
>>>y3 = y2 - tree_reg1.predict(X)
>>>tree_reg3 = DecisionTreeRegressor(max_depth=2)
>>>tree_reg3.fit(X, y3)
```
现在我们有了一个包含三个回归器的集成。它可以通过集成所有树的预测来在一个新的实例上进行预测。
```python
>>>y_pred = sum(tree.predict(X_new) for tree in (tree_reg1, tree_reg2, tree_reg3))
```
图7-9在左栏展示了这三个树的预测,在右栏展示了集成的预测。在第一行,集成只有一个树,所以它与第一个树的预测相似。在第二行,一个新的树在第一个树的残差上进行训练。在右边栏可以看出集成的预测等于前两个树预测的和。相同的,在第三行另一个树在第二个数的残差上训练。你可以看到集成的预测会变的更好。
我们可以使用sklean中的 *GradientBoostingRegressor* 来训练GBRT集成。与 *RandomForestClassifier* 相似,它也有超参数去控制决策树的生长(例如 *max_depth**min_samples_leaf* 等等),也有超参数去控制集成训练,例如基分类器的数量( *n_estimators* )。接下来的代码创建了与之前相同的集成:
```python
>>>from sklearn.ensemble import GradientBoostingRegressor
>>>gbrt = GradientBoostingRegressor(max_depth=2, n_estimators=3, learning_rate=1.0)
>>>gbrt.fit(X, y)
```
![图7-9](../images/chapter_7/7-9.png)
超参数 *learning_rate* 确立了每个树的贡献。如果你把它设置为一个很小的树,例如0.1,在集成中就需要更多的树去拟合训练集,但预测通常会更好。这个正则化技术叫做 *shrinkage* 。图7-10展示了两个在低学习率上训练的GBRT集成:其中左面是一个没有足够树去拟合训练集的树,右面是有过多的树过拟合训练集的树。
![图7-10](../images/chapter_7/7-10.png)
为了找到树的最优数量,你可以使用早停技术(第四章讨论)。最简单使用这个技术的方法就是使用 *staged_predict()* :它在训练的每个阶段(用一棵树,两棵树等)返回一个迭代器。加下来的代码用120个树训练了一个GBRT集成,然后在训练的每个阶段验证错误以找到树的最佳数量,最后使用GBRT树的最优数量训练另一个集成:
```python
>>>import numpy as np
>>>from sklearn.model_selection
>>>import train_test_split from sklearn.metrics
>>>import mean_squared_error
>>>X_train, X_val, y_train, y_val = train_test_split(X, y)
>>>gbrt = GradientBoostingRegressor(max_depth=2, n_estimators=120) gbrt.fit(X_train, y_train)
>>>errors = [mean_squared_error(y_val, y_pred)
for y_pred in gbrt.staged_predict(X_val)]
>>>bst_n_estimators = np.argmin(errors)
>>>gbrt_best = GradientBoostingRegressor(max_depth=2,n_estimators=bst_n_estimators) >>>gbrt_best.fit(X_train, y_train)
```
验证错误在图7-11的左面展示,最优模型预测被展示在右面。
![图7-11](../images/chapter_7/7-11.png)
你也可以早早的停止训练来实现早停(与先在一大堆树中训练,然后再回头去找最优数目相反)。你可以通过设置 *warm_start=True* 来实现 ,这使得当fit()方法被调用时sklearn保留现有树,并允许增量训练。接下来的代码在当一行中的五次迭代验证错误没有改善时会停止训练:
```python
>>>gbrt = GradientBoostingRegressor(max_depth=2, warm_start=True)
min_val_error = float("inf")
error_going_up = 0
for n_estimators in range(1, 120):
gbrt.n_estimators = n_estimators
gbrt.fit(X_train, y_train)
y_pred = gbrt.predict(X_val)
val_error = mean_squared_error(y_val, y_pred)
if val_error < min_val_error:
min_val_error = val_error
error_going_up = 0
else:
error_going_up += 1
if error_going_up == 5:
break # early stopping
```
*GradientBoostingRegressor* 也支持指定用于训练每棵树的训练实例比例的超参数 *subsample* 。例如如果 *subsample=0.25* ,那么每个树都会在25%随机选择的训练实例上训练。你现在也能猜出来,这也是个高偏差换低方差的作用。它同样也加速了训练。这个技术叫做 *随机梯度提升*
也可能对其他损失函数使用梯度提升。这是由损失超参数控制(见scikit学习文档)。
## Stacking
![图7-5](../images/chapter_7/7-1.png) ![图7-12](../images/chapter_7/7-12.png)
\ No newline at end of file ![图7-13](../images/chapter_7/7-12.png)
![图7-14](../images/chapter_7/7-12.png)
![图7-15](../images/chapter_7/7-12.png)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册