种植决策树

与所有监督式机器学习模型一样,决策树的训练目标是尽可能准确地解释一组训练示例。决策树的最佳训练是一个 NP 难问题。因此,训练通常使用启发词语(一种易于创建的学习算法)来完成,该算法会生成非最优但接近最优的决策树。

用于训练决策树的大多数算法都采用贪心分而治之策略。该算法首先创建一个节点(根节点),然后以贪心的方式递归地扩展决策树。

在每个节点,系统都会评估所有可能的条件并为其评分。算法会选择“最佳”条件,即得分最高的条件。目前,只需知道得分是与任务相关的指标,并且条件的选择是为了尽可能提高该指标。

例如,在 Palmer Penguins 数据集(用于本课程后面的代码示例)中,大多数阿德利企鹅和巴布亚企鹅的嘴长度大于 16 毫米,而大多数颊纹企鹅的嘴较小。因此,条件 bill_length_mm ≥ 16 可以对冠企鹅进行近乎完美的预测,但无法区分帝企鹅和巴布亚企鹅。算法可能会选择此条件。

一个条件导致两个叶子。条件为“bill_length_mm >= 16”。如果是,则为“阿德利企鹅或巴布亚企鹅”。如果没有,则叶子为“Gentoo”。

图 7. 种植树的第一步。

 

然后,该算法会在两个子节点上独立递归重复。如果找不到任何满足条件的节点,则该节点会变为叶节点。叶子预测是根据示例中最具代表性的标签值确定的。

算法如下:

def train_decision_tree(training_examples):
  root = create_root() # Create a decision tree with a single empty root.
  grow_tree(root, training_examples) # Grow the root node.
  return root

def grow_tree(node, examples):
  condition = find_best_condition(examples) # Find the best condition.

  if condition is None:
    # No satisfying conditions were found, therefore the grow of the branch stops.
    set_leaf_prediction(node, examples)
    return

  # Create two childrens for the node.
  positive_child, negative_child = split_node(node, condition)

  # List the training examples used by each children.
  negative_examples = [example for example in examples if not condition(example)]
  positive_examples = [example for example in examples if condition(example)]

  # Continue the growth of the children.
  grow_tree(negative_child, negative_examples)
  grow_tree(positive_child, positive_examples)

我们来详细了解训练特定决策树的步骤。

第 1 步:创建根目录:

带有问号的节点。

第 2 步:扩展节点 1。找到了条件“x1 ≥ 1”。 系统会创建两个子节点:

一个根节点,指向两个未定义的节点。

第 3 步:扩容节点 2。未找到任何满足条件的设备。因此,将该节点转换为叶节点:

一个根节点,指向两个未定义的节点。

第 4 步:扩展节点 3。发现了条件“x2 ≥ 0.5”。系统会创建两个子节点。

一个根节点、一个条件和三个叶子。

还有其他方法可以扩展决策树。一种常见的替代方法是全局优化节点,而不是使用分而治之策略。

YDF 代码
在 YDF 中,默认情况下,决策树是使用上述“贪心分而治之”算法进行扩展的。或者,您也可以使用 growing_strategy="BEST_FIRST_GLOBAL" 参数启用全局增长。如需了解详情,请参阅 文档

给定节点的可能条件数量可能非常多,通常是无限的,具体取决于输入特征的数量和类型。例如,给定阈值条件 $\mathrm{feature}_i \geq t$,对于 $t \in \mathbb{R}$,所有可能的阈值值的组合是无限的。

负责查找最佳条件的例程称为拆分器。由于需要测试许多可能的条件,因此分屏器是训练决策树时的瓶颈。

分屏器最大化的得分取决于任务。例如:

有许多分屏算法,每种算法对以下各项的支持各不相同:

  • 特征的类型;例如,数值、分类、文本
  • 任务;例如,二元分类、多类分类、回归
  • 条件的类型;例如,阈值条件、集合内条件、斜线条件
  • 正则化条件;例如,用于阈值条件的完全分隔符或近似分隔符

此外,还有等效的分屏变体,它们在内存用量、CPU 用量、计算分布等方面具有不同的权衡。

YDF 代码
在 YDF 中,系统会根据自动检测到的(或手动指定的)特征类型、超参数以及每个分屏器的估算速度(在训练期间,YDF 会运行一个小型模型来预测每个候选分屏器的速度)来隐式选择分屏器。