# 第6章 决策树

与支持向量机一样，决策树也是多功能的机器学习算法，既可以执行分类任务，也可以执行回归任务，甚至可以执行多输出任务。 它们是非常强大的算法，能够完美契合复杂的数据集。 例如，在第 2 章中，我们在加利福尼亚住房数据集上训练了一个 DecisionTreeRegressor 模型，并对其进行了完美拟合（实际上是对其进行过度拟合）。
决策树也是随机森林的基本组成部分（参见第 7 章），它是当今最强大的机器学习算法之一。
在本章中，我们将首先讨论如何使用决策树进行训练，可视化和预测。 然后快速过一遍 Scikit-Learn 中使用的 CART 训练算法，并且讨论如何调整树并将其用于回归任务。 最后，我们会讨论决策树的一些局限性。

## 训练和可视化决策树
为了理解决策树，我们只需构建一个决策树并查看它如何进行预测。 以下代码在鸢尾属植物数据集上训练决策树分类器（请参阅第4章）：

```python
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
iris = load_iris()
X = iris.data[:, 2:] # petal length and width y = iris.target
    tree_clf = DecisionTreeClassifier(max_depth=2)
    tree_clf.fit(X, y)
```

首先，我们可以通过使用 export_graphviz() 方法输出一个名为 iris_tree.dot 的图形定义文件来可视化已训练出来的决策树：

```python
from sklearn.tree import export_graphviz
    export_graphviz(
            tree_clf,
            out_file=image_path("iris_tree.dot"),
            feature_names=iris.feature_names[2:],
            class_names=iris.target_names,
            rounded=True,
            filled=True
        )
```

然后，w我们可以使用 graphviz 软件包中的 dot 命令行工具将此 .dot 文件转换为各种格式，例如 PDF 或 PNG 。下面的命令行将 .dot 文件转换为 .png 图像文件：

```powershell
$ dot -Tpng iris_tree.dot -o iris_tree.png
```

我们的第一个决策树如图6-1所示。

![Figure6-1](https://github.com/apachecn/hands_on_Ml_with_Sklearn_and_TF/blob/Lisanaaa/images/chapter_6/Figure6-1.jpeg)

## 预测

让我们看看图 6-1 中所呈现的树如何进行预测。假设我们找到了一种鸢尾花，并且想对它进行分类。我们从根节点开始（深度0，顶部）：该节点询问花朵的花瓣长度是否小于2.45厘米。如果是，则向下移动到根的左侧子节点（深度1，左侧）。在这种情况下，它是一个叶子节点（即它没有任何子节点），所以它不会提出任何问题：我们可以简单地查看该节点的预测类，决策树预测我们的花是一个Iris-Setosa（class = setosa）。
现在假设你找到另一朵花，但这次花瓣长度大于2.45厘米。我们必须向下移动到根节点的右侧（深度1，右侧），这不是叶子节点，因此它会提出另一个问题：花瓣宽度是否小于1.75厘米？如果是这样，那么我们的花很可能是一个 Iris-Versicolor（深度 2，左）。如果不是，它可能是一个 Iris-Virginica（深度 2，右）。就是这么简单。

> 决策树的许多特质之一是它们只需很少的数据准备。 特别是，它们不需要特征缩放或居中。

每个节点的样本属性计算它应用于的训练实例的数量。 例如，100 个训练样本的花瓣长度大于 2.45 厘米（深度1，右侧），其中 54 个花瓣宽度小于 1.75 厘米（深度2，左侧）。 节点的值属性告诉您此节点适用的每个类的训练实例数量：例如，右下角节点适用于 0 Iris-Setosa，1 Iris-Versicolor和 45 Iris-Virginica。 最后，节点的 gini 属性测量它的杂质：如果它适用的所有训练实例属于同一个类，则节点是“纯的”（gini = 0）。 例如，由于深度 1 左节点仅适用于 Iris-Setosa 训练实例，因此它是纯的，其基尼分数为 0。等式 6-1 显示训练算法如何计算出第 i 个节点的 gini 分数Gi。 例如，深度 2 左节点的基尼分数等于 
![1 - （0/54）2 - （49/54）2 - （5/54）2≈0.168](../images/tex-fc25e36aa4f56e211ba7c17003d30cdd.gif)
接下来讨论另一种纯度测量方法。
![Equation 6-1. Gini impurityn](../images/tex-1721011d2159c98b89cc63e73846d511.gif)

![G_{i}=1− ∑_{k=1}^{n} p_{i},k^2](../images/tex-ee055288b8f1ec24d0f6aadc2633f1ca.gif)

• 其中 p_{i,k} 是第 i 个节点中训练实例之间的 k 类实例的比率。

> Scikit-Learn使用只生成二叉树的CART算法：非叶节点总是有两个孩子（即问题只有yes / no的答案）。 但是，其他算法（如ID3）生成的决策树，可以具有两个以上孩子的节点。

图 6-2 显示了决策树的决策边界。 粗的垂直线代表根节点（深度 0 ）的决定边界：花瓣长度 = 2.45厘米。 由于左侧区域是纯粹的（只有Iris-Setosa），所以不能再进一步分割。 然而，右侧区域不纯，所以深度 1 右节点在花瓣宽度 = 1.75厘米（用虚线表示）分裂。 由于 max_depth 设置为 2，因此决策树在此处停止。 但是，如果将max_depth设置为3，那么两个深度 2 节点将分别添加另一个决策边界（用虚线表示）。

![Figure6-2](https://github.com/apachecn/hands_on_Ml_with_Sklearn_and_TF/blob/Lisanaaa/images/chapter_6/Figure6-2.jpeg)

> #### 模型解读：白盒与黑盒
>
> 正如你所看到的，决策树非常直观，他们的决策很容易解释。 这种模型通常被称为白盒模型。 相反，正如我们将看到的，随机森林或神经网络通常被认为是黑匣子模型。 他们做出了很好的预测，并且我们可以轻松检查他们执行的计算以进行这些预测; 然而，通常很难用简单的术语来解释为什么会做出预测。 例如，如果一个神经网络表示一个特定的人出现在图片上，很难知道究竟是什么促成了这个预测：模型是否认出了这个人的眼睛？ 她的嘴？ 她的鼻子？ 她的鞋子？ 或者甚至坐在沙发上？ 相反，决策树提供了好且简单的分类规则，甚至可以根据需要手动调参（例如，用于花卉分类）。

## 估计属于各类的概率

决策树还可以估计实例属于特定类 k 的概率：首先遍历树来找到此实例的叶子节点，然后返回该节点中类 k 的训练实例的比率。 例如，假设你已经找到一朵花长 5厘米，宽 1.5 厘米的花朵。 相应的叶子节点是深度为 2 的左节点，因此决策树应该输出以下概率：Iris-Setosa（0/54）为 0％，Iris-Versicolor为 (49/54)，即 90.7％， Iris-Virginica (5/54)，即 9.3 ％。 当然，如果你让它预测类别，它应该输出Iris-Versicolor（类别 1），因为它具有最高的概率。 让我们来检查一下：

```powershell
>>> tree_clf.predict_proba([[5, 1.5]]) 
array([[ 0. , 0.90740741, 0.09259259]])
>>> tree_clf.predict([[5, 1.5]]) 
array([1])
```

完美！ 请注意，估计的概率在图 6-2 的右下方矩形的其他任何地方都是相同的，比如说花瓣长 6 厘米，宽 1.5 厘米（尽管在这种情况下很明显它更有可能是 Iris -Virginica）。

