前言

决策树给我的感觉就是一系列的if else,随机森林就是一系列的决策树合并,并添加随机性。随机森林有决策树的所有优点而且还在一定程度上缓解了决策树过拟合的问题,但决策树是随机森林的基础,所以两者都需要了解。由于算法的原因,两者不需要对数据进行归一化处理,还是比较方便的。

正文

一、决策树

1.原理
看看书上是怎么说的

本质上,它从一层层的 if/else 问题中进行学习,并得出结论。这些问题类似于你在“20 Questions”游戏 9
中可能会问的问题。想象一下,你想要区分下 面这四种动物:熊、鹰、企鹅和海豚。你的目标是通过提出尽可能少的if/else
问题来得到正确答案。你可能首先会问:这种动物有没有羽毛,这个问题会将可能的动物减少到只有两种。如果答案是“有”,你可以问下一个问题,帮你区分鹰和企鹅。例如,你可以问这种动物会不会飞。如果这种动物没有毛,那么可能是海豚或熊,所以你需要问一个问题来区分这两种动物——比如问这种动物有没有鳍。

随机森林如何找出最优决策树 随机森林中决策树个数_决策树

算法具体是怎么做的呢?

简单来说就是每寻找能把数据尽可能分开的一个测试,然后递归调用这个过程,直到把所有数据都分开。

比如:

第一次划分(决策树的第一层)是这样的:

随机森林如何找出最优决策树 随机森林中决策树个数_随机森林_02


第九次划分是这样的:

随机森林如何找出最优决策树 随机森林中决策树个数_随机森林如何找出最优决策树_03


很显然,决策树太深的话很容易过拟合,我们可以通过“预剪枝”操作来减轻过拟合,就是限制其深度只能达到一个值。(类似于提前停止)

2.代码实例

先看下数据集:

import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_breast_cancer
cancer = load_breast_cancer()
print(cancer.data.shape)
print(cancer.target.shape)

用的是预测肿瘤阴性还是阳性的二分类数据集,训练集大小(569,30),即有30个特征。
结果:

(569, 30)
(569,)
X_train, X_test, y_train, y_test = train_test_split(
 cancer.data, cancer.target, stratify=cancer.target, random_state=42)
tree = DecisionTreeClassifier(max_depth=4, random_state=0)
tree.fit(X_train, y_train)
print("train acc:{:.3f}".format(tree.score(X_train, y_train)))
print("test acc:{:.3f}".format(tree.score(X_test, y_test)))

结果:

train acc:0.988
test acc:0.951

说明两点:
(1)DecisionTreeClassifier()中的max_depth参数就是进行“预剪枝”的,限制最大深度;
(2)train_test_split()中的stratify参数很重要,如果设置stratify参数,就可以让数据集按照类别比例进行划分,对于分类数据集中类别比例不一样的数据尤其有用。

train_test_split()的参数

测试集上结果还不错。
3.特征重要性
可以通过model.feature_importances_得到每个特征的重要性:

print("Feature importances:\n{}".format(tree.feature_importances_))

结果:

Feature importances:
[0.         0.         0.         0.         0.         0.
 0.         0.         0.         0.         0.01019737 0.04839825
 0.         0.         0.0024156  0.         0.         0.
 0.         0.         0.72682851 0.0458159  0.         0.
 0.0141577  0.         0.018188   0.1221132  0.01188548 0.        ]

将这个属性可视化会有很好的效果:

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(tree)

结果:

随机森林如何找出最优决策树 随机森林中决策树个数_python_04

二、随机森林

1.原理
背后思想

决策树的一个主要缺点在于经常对训练数据过拟合。随机森林是解决这个问题的一种方法。随机森林本质上是许多决策树的集合,其中每棵树都和其他树略有不同。随机森林背后的思想是,每棵树的预测可能都相对较好,但可能对部分数据过拟合。如果构造很多树,并且每棵树的预测都很好,但都以不同的方式过拟合,那么我们可以对这些树的结果取平均值来降低过拟合。既能减少过拟合又能保持树的预测能力,这可以在数学上严格证明。

构造随机森林。 想 要 构 造 一 个 随 机 森 林 模 型, 你 需 要 确 定 用 于 构 造 的 树 的 个 数。比如我们想要构造 10 棵树。这些树在构造时彼此完全独立,算法对每棵树进行不同的随机选择,以确保树和树之间是有区别的。想要构造一棵树,首先要对数据进行自助采样(bootstrap sample)。也就是说,从 n_samples 个数据点中有放回地(即同一样本可以被多次抽取)重
复随机抽取一个样本,共抽取 n_samples 次。这样会创建一个与原数据集大小相同的数据集,但有些数据点会缺失(大约三分之一),有些会重复。

举例说明,比如我们想要创建列表 [‘a’, ‘b’, ‘c’, ‘d’] 的自助采样。一种可能的自主采样是 [‘b’, ‘d’, ‘d’, ‘c’],另一种可能的采样为 [‘d’, ‘a’, ‘d’, ‘a’]。接下来,基于这个新创建的数据集来构造决策树。但是,要对我们在介绍决策树时描述的算法稍作修改。在每个结点处,算法随机选择特征的一个子集,并对其中一个特征寻找最佳测试,而不是对每个结点都寻找最佳测试。选择的特征个数由 max_features 参数来控制。每个结点中特征子集的选择是相互独立的,这样树的每个结点可以使用特征的不同子集来做出决策。由于使用了自助采样,随机森林中构造每棵决策树的数据集都是略有不同的。由于每个结点的特征选择,每棵树中的每次划分都是基于特征的不同子集。这两种方法共同保证随机森林中所有树都不相同。

2.代码实例

#随机森林
from sklearn.ensemble import RandomForestClassifier
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 on training set: {:.3f}".format(forest.score(X_train, y_train)))
print("Accuracy on test set: {:.3f}".format(forest.score(X_test, y_test)))

结果:

Accuracy on training set: 1.000
Accuracy on test set: 0.972

说明:

(1)RandomForestClassifier中的参数n_estimators表示随机森林中决策树的个数,原则上越多越好
(2)随机森林model也有feature_importances_属性,可用来做上述可视化,效果很好