目录
机器学习实战(7)中我们已经提到,随机森林是决策树的集成,通常用bagging方法训练,训练集大小通过max_samples来设置。除了先构建一个 BaggingClassifier 然后将结果传输到 DecisionTreeClassifier ,还有一种方法就是使用 RandomForestClassifier 类(对于回归任务有RandomForestRegressor类),这种方法更方便。
1 随机森林
常规模块的导入以及图像可视化的设置:(注意,本节是基于第7节集成学习的代码继续往下演示的)
# Common imports
import numpy as np
import os
# to make this notebook's output stable across runs
np.random.seed(42)
# To plot pretty figures
%matplotlib inline
import matplotlib as mpl
import matplotlib.pyplot as plt
mpl.rc('axes', labelsize=14)
mpl.rc('xtick', labelsize=12)
mpl.rc('ytick', labelsize=12)
以下代码训练一个拥有500棵树的随机森林分类器(其中每棵树限制为最多16个叶节点):
from sklearn.ensemble import RandomForestClassifier
rnd_clf = RandomForestClassifier(n_estimators=500, max_leaf_nodes=16, n_jobs=-1, random_state=42)
rnd_clf.fit(X_train, y_train)
y_pred_rf = rnd_clf.predict(X_test)
np.sum(y_pred == y_pred_rf) / len(y_pred) # almost identical predictions
运行结果如下:
0.936
除了少数例外(没有splitter(强制为random),没有presort(强制为False),没有max_samples(强制为1.0),没有base_estimator(强制为DecisionTreeClassifier)),RandomForestClassifier 具有 DecisionTreeClassifier 和 BaggingClassifier 的所有超参数,前者用来控制树的生长,后者用来控制集成本身。
用 BaggingClassifier 实现与上述代码效果相同的效果:
bag_clf = BaggingClassifier(
DecisionTreeClassifier(splitter="random", max_leaf_nodes=16, random_state=42),
n_estimators=500, max_samples=1.0, bootstrap=True, n_jobs=-1, random_state=42)
bag_clf.fit(X_train, y_train)
y_pred = bag_clf.predict(X_test)
from sklearn.metrics import accuracy_score
accuracy_score(y_test, y_pred)
运行结果如下:
0.92
2 极端随机树
随机森林里单棵树的生长过程中,每个节点在分裂时仅考虑到一个随机子集所包含的特征。如果我们对每个特征使用随机阈值,而不是搜索得出的最佳阈值,则可能让决策树生产得更随机。这种极端随机的决策树组成的森林被称为极端随机树。同样,它也是以更高的偏差换取了更低的方差。
我们使用Scikit-Learn的 ExtraTreeClassifier 可以创建一个极端随机树分类器。
我们很难预先知道一个 RandomForestClassifier 是否比一个 ExtraTreeClassifier 更好或是更差,只有两种都尝试一遍,然后使用交叉验证进行比较。
3 特征重要性
我们查看单个决策树会发现,重要的特征更可能出现在靠近根节点的位置,而不重要的特征通常出现在靠近叶节点的位置。因此,通过计算一个特征在森林中所有树上的平均深度,就可以估算出一个特征的重要程度。Scikit-Learn 在训练结束后自动计算每个特征的重要性。
例如下列代码:
from sklearn.datasets import load_iris
iris = load_iris()
rnd_clf = RandomForestClassifier(n_estimators=500, n_jobs=-1, random_state=42)
rnd_clf.fit(iris["data"], iris["target"])
for name, score in zip(iris["feature_names"], rnd_clf.feature_importances_):
print(name, score)
运行结果如下:
sepal length (cm) 0.11249225099876375
sepal width (cm) 0.02311928828251033
petal length (cm) 0.4410304643639577
petal width (cm) 0.4233579963547682