如何从 BoostedTrees Estimators 迁移到 TensorFlow Decision Forests
2022 年 4 月 4 日

Mathieu Guillame-BertJosh Gordon 为 TensorFlow 团队发布

决策森林模型,例如 随机森林梯度提升树 通常是处理表格数据的最有效工具。它们比神经网络有很多优势,包括更容易配置和更快的训练速度。使用树木可以极大地减少准备数据集所需的代码量,因为它们可以原生处理数字、分类和缺失特征。而且它们通常可以提供开箱即用的良好结果,并且具有可解释的属性。

虽然我们通常认为 TensorFlow 是一个用于训练神经网络的库,但 Google 的一个流行用例是使用 TensorFlow 来创建决策森林。

决策树对数据进行分类的动画。

本文提供了一个迁移指南,如果您之前使用 tf.estimator.BoostedTrees 创建基于树的模型,该模型于 2019 年 发布。Estimator API 负责处理与生产环境中模型交互的许多复杂性,包括分布式训练和序列化。但是,它不再推荐用于新代码。

如果您要开始一个新项目,我们建议您使用 TensorFlow Decision Forests (TF-DF)。该库提供了用于训练、服务和解释决策森林模型的最新算法,与以前的方法相比具有许多优势,特别是质量、速度和易用性方面的优势。

首先,以下是使用 Estimator API 和 TF-DF 创建提升树模型的等效示例。

以前,您会使用 tf.estimator.BoostedTrees (不再推荐) 训练梯度提升树模型


import tensorflow as tf

# Dataset generators
def make_dataset_fn(dataset_path):
    def make_dataset():
        data = ... # read dataset
        return tf.data.Dataset.from_tensor_slices(...data...).repeat(10).batch(64)
    return make_dataset

# List the possible values for the feature "f_2".
f_2_dictionary = ["NA", "red", "blue", "green"]

# The feature columns define the input features of the model.
feature_columns = [
    tf.feature_column.numeric_column("f_1"),
    tf.feature_column.indicator_column(
       tf.feature_column.categorical_column_with_vocabulary_list("f_2",
         f_2_dictionary,
         # A special value "missing" is used to represent missing values.
         default_value=0)
       ),
    ]

# Configure the estimator
estimator = boosted_trees.BoostedTreesClassifier(
          n_trees=1000,
          feature_columns=feature_columns,
          n_classes=3,
          # Rule of thumb proposed in the BoostedTreesClassifier documentation.
          n_batches_per_layer=max(2, int(len(train_df) / 2 / FLAGS.batch_size)),
      )

# Stop the training is the validation loss stop decreasing.
early_stopping_hook = early_stopping.stop_if_no_decrease_hook(
      estimator,
      metric_name="loss",
      max_steps_without_decrease=100,
      min_steps=50)

tf.estimator.train_and_evaluate(
      estimator,
      train_spec=tf.estimator.TrainSpec(
          make_dataset_fn(train_path),
          hooks=[
              # Early stopping needs a CheckpointSaverHook.
              tf.train.CheckpointSaverHook(
                  checkpoint_dir=input_config.raw.temp_dir, save_steps=500),
              early_stopping_hook,
          ]),
      eval_spec=tf.estimator.EvalSpec(make_dataset_fn(valid_path)))

如何使用 TensorFlow Decision Forests 训练同一个模型


import tensorflow_decision_forests as tfdf

# Load the datasets
# This code is similar to the estimator.
def make_dataset(dataset_path):
    data = ... # read dataset
    return tf.data.Dataset.from_tensor_slices(...data...).batch(64)

train_dataset = make_dataset(train_path)
valid_dataset = make_dataset(valid_path)

# List the input features of the model.
features = [
  tfdf.keras.FeatureUsage("f_1", keras.FeatureSemantic.NUMERICAL),
  tfdf.keras.FeatureUsage("f_2", keras.FeatureSemantic.CATEGORICAL),
]

model = tfdf.keras.GradientBoostedTreesModel(
  task = tfdf.keras.Task.CLASSIFICATION,
  num_trees=1000,
  features=features,
  exclude_non_specified_features=True)

model.fit(train_dataset, valid_dataset)

# Export the model to a SavedModel.
model.save("project/model")

备注

  • 虽然在这个示例中没有明确说明,但提前停止会自动启用和配置。
  • "f_2" 特征的字典会自动构建和优化(例如,稀有值会合并到一个词汇外项目中)。
  • 类别数(在本例中为 3)会从数据集中自动确定。
  • 批大小(在本例中为 64)对模型训练没有影响。较大的值通常更可取,因为它可以提高读取数据集的效率。

TF-DF 注重易用性,上面的示例可以进一步简化和改进,如下所示。

如何训练 TensorFlow Decision Forests (推荐解决方案)

import tensorflow_decision_forests as tfdf
import pandas as pd

# Pandas dataset can be used easily with pd_dataframe_to_tf_dataset.
train_df = pd.read_csv("project/train.csv")

# Convert the Pandas dataframe into a TensorFlow dataset.
train_ds = tfdf.keras.pd_dataframe_to_tf_dataset(train_df, label="my_label")

model = tfdf.keras.GradientBoostedTreeModel(num_trees=1000)
model.fit(train_dataset)

备注

  • 我们没有指定特征的语义(例如,数字或分类)。在这种情况下,语义将自动推断。
  • 我们也没有列出要使用的输入特征。在这种情况下,将使用所有列(标签除外)。输入特征的列表和语义在训练日志或使用模型检查器 API 中可见。
  • 我们没有指定任何验证数据集。每种算法可以选择从训练示例中提取最适合该算法的验证数据集。例如,默认情况下,GradientBoostedTreeModel 如果未提供验证数据集,则使用 10% 的训练数据进行验证。

现在,让我们看看 Estimator API 和 TF-DF 之间的几个区别。

Estimator API 和 TF-DF 之间的区别

算法类型

TF-DF 是一个决策森林算法集合。这包括(但不限于)Estimator API 中可用的梯度提升树。值得注意的是,TF-DF 还支持 随机森林(非常适合噪声数据集)和 CART 实现(非常适合模型解释)。

此外,对于这些算法中的每一个,TF-DF 都包含了文献中发现的许多变体,并在实验中得到了验证 [1, 2, 3]。

精确分割与近似分割

TF1 GBT Estimator 是一种近似树学习算法。非正式地说,Estimator 构建 树的方式只考虑在每一步的随机示例子集和随机条件子集。

默认情况下,TF-DF 是一种精确树训练算法。非正式地说,TF-DF 在每一步都考虑所有训练示例和所有可能的分割。这是一种更常见的且通常性能更好的解决方案。

虽然在较大的数据集(>10B 个示例 x 特征)上有时更快,但估算器近似值通常不太准确(因为需要生长更多的树才能达到相同的质量)。在较小的数据集(<100M 个示例 x 特征)中,估算器中实现的近似训练形式甚至可能比精确训练更慢。

TF-DF 还支持各种类型的“近似”树训练。推荐的方法是使用精确训练,并可以选择在大型数据集上测试近似训练。

推理

Estimator 使用 自上而下的树路由算法 执行模型推理。TF-DF 使用 QuickScorer 算法的扩展。

虽然两种算法都返回完全相同的结果,但自上而下的算法效率较低,因为存在过度分支预测和缓存未命中问题。TF-DF 推理在同一模型上通常快 10 倍。

对于延迟敏感的应用程序,TF-DF 提供了 C++ API。它通常提供约 1µs/示例/核心推理时间。这通常比 TF SavedModel 推理快 50-1000 倍(尤其是在小批量的情况下)。

多头模型

Estimator 支持多头模型(一个模型输出多个预测)。TF-DF(目前)不支持直接使用多头模型,但是,使用 Keras 函数式 API,可以将并行训练的多个 TF-DF 模型组装成多头模型。

了解更多

您可以访问 网站 了解有关 TensorFlow Decision Forests 的更多信息。如果您不熟悉这个库,初学者示例 是一个不错的起点。有经验的 TensorFlow 用户可以访问此 指南,以了解有关在 TensorFlow 中使用决策森林和神经网络之间的区别的重要细节,包括如何配置您的训练管道以及有关数据集 I/O 的提示。您还可以查看 从 Estimator 迁移到 Keras API,以获取有关从 Estimators 迁移到 Keras 的更多信息。

下一篇文章
How to migrate from BoostedTrees Estimators to TensorFlow Decision Forests

Mathieu Guillame-BertJosh Gordon 为 TensorFlow 团队发布 决策森林模型,例如 随机森林梯度提升树 通常是处理表格数据的最有效工具。它们比神经网络有很多优势,包括更容易配置和更快的训练速度。使用树木可以极大地减少准备数据集所需的代码量,因为它们可以原生处理数字、分类和缺失特征。而且它们通常可以提供开箱即用的良好结果,并且具有可解释的属性。…