随机森林(random forest)模型原理及sklearn实现

本文的主要内容是基于Python机器学习基础教程决策树部分进行整理和总结。

目的

决策树的主要缺点在于,即使做了剪枝处理,也会出现过拟合的情况,泛化能力相对而言并不高,为此,在大多数的应用中,往往使用集成(ensemble)方法来代替单棵决策树。集成是合并多个机器学习模型来构建更强大模型的方法,目前已经证明随机森林(random forest)作为决策树集成方法对大量分类和回归的数据集都是有效的。

思想

随机森林本质上是许多决策树的集合,,其中每棵树都和其他树有所不同,随机森林的思想在于,保证每棵树的预测都是相对较好的,但是可能对部分数据存在过拟合的情况,我们可以通过构造很多树,并且构造的树都是以不同的方式过拟合,那么我们可以对这些树的结果取平均来降低过拟合。

策略

那么要如何才能保证每棵树有很好的预测并且各有不同呢?随机森林的名字来自于将随机性添加到树的构造过程中,以确保每棵树各有不同,随机森林的随机化方法有两种:

  • 通过选择构造书的数据点,实现的方法叫做随机采样(booststrap sample),从n_samples个数据点中有放回的重复抽取一个样本,并且抽取n_samples次,也就是说每个数据点是会被多次抽取的,有的数据点可能一次也不会被抽到(通过数学证明这类样本占到1/3),这样就会生成一个数据点数量和原数据集数量相同的样本集合;

  • 通过选择每次划分测试的特征:仅使用随机采样的方法生成随机森林的方法是不够的,我们还需要针对决策树在每个节点处随机算则特征集合的一个子集,在sklearn中,算则的特征个数由max_features参数控制,每个节点中特征子集的选择是相互独立的,这样树的节点可以使用特征的不同子集进行决策。

由此可知,随机森林中构造每棵决策树的数据集都是稍有不同的,同时由于每个节点的特征选择,每棵树的每次特征划分都是基于特征的不同子集,这两种方法共同保证随机森林中所有树都不相同。

sklearn实现与可视化分析

使用5棵树组成的随机森林应用到two_moons数据集上。

import numpy as np
import matplotlib.pyplot as plt
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_moons
X,y = make_moons(n_samples=100,noise=0.25,random_state=3)
X_train,X_test,y_train,y_test = train_test_split(X,y,stratify=y,random_state=42)
forest = RandomForestClassifier(n_estimators=5,random_state=2)
forest.fit(X_train,y_train)

作为随机森林的一部分,树被保存在estimator_属性中,我们将每棵树学到的决策树边界可视化,也将它们的总预测(即整个森林做出的预测)可视化。

fig,axes = plt.subplots(2,3,figsize=(20,10))
for i,(ax,tree) in enumerate(zip(axes.ravel(),forest.estimators_)):
    ax.set_title("Tree {}".format(i))
    mglearn.plots.plot_tree_partition(X_train,y_train,tree,ax=ax)
    
mglearn.plots.plot_2d_separator(forest,X_train,fill=True,ax=axes[-1,-1],alpha=.4)
axes[-1,-1].set_title("random_forest")
mglearn.discrete_scatter(X_train[:,0],X_train[:,1],y_train)

随机森林(random forest)模型原理及sklearn实现_第1张图片
从训练结果可以看出,生成的5棵决策树决策边界各不相同,每棵树也都多多少少犯了一些错误,因为由于自助采样,一些训练点实际上并没有包含在训练集中。
随机森林的结果比单独每棵树的过拟合都要小,给出的决策边界也更加符合直观感受,在任何使用应用中,我们都会用到更多的树(几百乃至上千),从而得到更平滑的边界。
随机森林(random forest)模型原理及sklearn实现_第2张图片
现在我们将100棵树的随机森林应用到乳腺癌的数据中

import numpy as np
import matplotlib.pyplot as plt
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
import mglearn
from sklearn.datasets import load_breast_cancer
cancer = load_breast_cancer()
X_train,X_test,y_train,y_test = train_test_split(cancer['data'],cancer['target'],random_state=0)
forest = RandomForestClassifier(n_estimators=100,random_state=0)
forest.fit(X_train,y_train)

print("Accuracy of train set {:.3f}".format(forest.score(X_train,y_train)))
print("Accuracy of test set {:.3f}".format(forest.score(X_test,y_test)))
Accuracy of train set 1.000
Accuracy of test set 0.972

可以发现,在没有调节任何参数的情况下,随机森林的精度为97%,比线性模型或单棵决策树都要好,我们可以调节max_features参数,或者像单棵树那样进行预剪枝,但是一般情况下,随机森林的默认参数就能给出很好的结果。
给出随机森林的特征重要性直方图,随机森林特征重要性相比单棵决策树也会更加可靠。

def plot_feature_importances_cancer(model):
    n_features = cancer.data.shape[1]
    plt.barh(range(n_features),model.feature_importances_,align='center')
    plt.yticks(np.arange(n_features),cancer.feature_names)
    plt.xlabel('Feature importance')
    plt.ylabel("Feature")

plot_feature_importances_cancer(forest)

随机森林(random forest)模型原理及sklearn实现_第3张图片

模型评价

  • 用于回归和分类的随机森林是目前应用最广泛的机器学习方法之一,通常不需要反复调节参数就能得到很好的结果,也不需要对数据进行缩放(如归一化或标准化);
  • 随机森林拥有决策树的所有优点,同时弥补了决策树的一些缺陷,森林中的树越多,他对随机状态选择的鲁棒性也会越好;
  • max_features决定了每棵树的随机性大小,较小的max_features可以降低过拟合,对于分类,默认值是max_features=sqrt(n_features),对于回归,默认值是max_features=n_features,增大max_features或max_leaf_nodes有时也会提高性能;
  • 对于维度非常高的稀疏矩阵(如文本数据),随机森林的表现往往不是很好,对于这种数据,线性模型可能会更合适一些;

你可能感兴趣的:(随机森林(random forest)模型原理及sklearn实现)