说明:本文依据《Sklearn 与 TensorFlow 机器学习实用指南》完成,所有版权和解释权均归作者和翻译成员所有,我只是搬运和做注解。
第六章集成学习和随机森林
假设你去随机问很多人一个很复杂的问题,然后把它们的答案合并起来。通常情况下你会发现这个合并的答案比一个专家的答案要好。这就叫做群体智慧。
如果合并一组分类器的预测(像分类或者回归),同样会得到一个比单一分类器更好的预测结果。这一组分类器就叫做集成。
因此,这个技术就叫做集成学习,一个集成学习算法就叫做集成方法。
例如,你可以训练一组决策树分类器,每一个都在一个随机的训练集上。为了去做预测,你必须得到所有单一树的预测值,然后通过投票(例如第六章的练习)来预测类别。例如一种决策树的集成就叫做随机森林,它除了简单之外也是现今存在的最强大的机器学习算法之一。
一般会在一个项目快结束的时候使用集成算法,一旦你建立了一些好的分类器,就把他们合并为一个更好的分类器。在机器学习竞赛中获得胜利的算法经常会包含一些集成方法。
本章中,教程讨论了几个著名的集成方法:bagging, boosting, stacking和其他一些算法。我们也会讨论随机森林。
源代码已经同步在github中 https://github.com/jwc19890114/-02-learning-file-100days
本章中理论多过实操,所以基本上是抄了,如果不喜欢的同学可以直接看github里面的源文档。
3.随机森林
随机森林是决策树的一种集成,通常使用bagging方法进行训练。
参数设置:
- max_samples设置训练集大小
- n_estimators设置随机森林树大小
- max_leaf_nodes设置叶子节点数
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.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) # 0.976
随机森林算法在树生长时引入了额外的随机;与在节点分裂时需要找到最好分裂特征相反,它在一个随机的特征集中找最好的特征,导致了树的差异性,并且再一次用高偏差换低方差,总的来说是一个更好的模型。以下是BaggingClassifier大致相当于之前的randomforestclassifier
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.11249225099876374 sepal width (cm) 0.023119288282510326 petal length (cm) 0.44103046436395765 petal width (cm) 0.4233579963547681 ''' plt.figure(figsize=(6,4)) for i in range(15): tree_clf=DecisionTreeClassifier(max_leaf_nodes=16, random_state=42 + i) indices_with_replacement = np.random.randint(0, len(X_train), len(X_train)) tree_clf.fit(X[indices_with_replacement], y[indices_with_replacement]) plot_decision_boundary(tree_clf, X, y, axes=[-1.5, 2.5, -1, 1.5], alpha=0.02, contour=False) plt.show()
极端随机树
教程在这里仅是介绍了一下极端随机树。
可以使用Sklearn 的ExtraTreesClassifier来创建一个Extra-Tree分类器。API与RandomForestClassifier是相同的。很难分辨ExtraTreesClassifier和RandomForestClassifier到底哪个更好。通常情况下是通过交叉验证来比较它们(使用网格搜索调整超参数)。
特征重要度
如果观察一个单一决策树,重要的特征会出现在更靠近根部(顶端)的位置,而不重要的特征会经常出现在靠近叶子的位置。
可以通过计算一个特征在森林的全部树中出现的平均深度来预测特征的重要性。sklearn 在训练后会自动计算每个特征的重要度。可以通过feature_importances_变量来查看结果。例如如下代码在 iris 数据集(第四章介绍)上训练了一个RandomForestClassifier模型,然后输出了每个特征的重要性。看来,最重要的特征是花瓣长度(44%)和宽度(42%),而萼片长度和宽度相对比较是不重要的(分别为 11% 和 2%)
rnd_clf.feature_importances_ ''' sepal length (cm) 0.11249225099876374 sepal width (cm) 0.023119288282510326 petal length (cm) 0.44103046436395765 petal width (cm) 0.4233579963547681 '''
接下来介绍了通过绘制热力图来画出每个像素的重要性。
try: from sklearn.datasets import fetch_openml mnist = fetch_openml('mnist_784', version=1) mnist.target = mnist.target.astype(np.int64) except ImportError: from sklearn.datasets import fetch_mldata mnist = fetch_mldata('MNIST original', data_home="./MNIST_data") rnd_clf=RandomForestClassifier(n_estimators=10,random_state=42) rnd_clf.fit(mnist["data"],mnist["target"]) def plot_digit(data): image=data.reshape(28,28) plt.imshow(image,cmap=mpl.cm.hot,interpolation="nearest") plt.axis("off") plot_digit(rnd_clf.feature_importances_) cbar = plt.colorbar(ticks=[rnd_clf.feature_importances_.min(), rnd_clf.feature_importances_.max()]) cbar.ax.set_yticklabels(['Not important', 'Very important']) plt.show()