Skip to content

如何改进模型?

本文档提供了关于如何提高YDF模型质量、速度和规模的建议。改进的程度将取决于数据集。在某些情况下,变化可能微不足道,而在其他情况下,变化可能非常显著。无法事先知道某个变化会产生多少改进。

本指南分为两个章节:优化模型质量优化模型速度。在大多数情况下,提高模型质量也会使其变得更大和更慢,反之亦然。换句话说,模型的预测质量通常与其规模相关联。

对决策森林的工作原理有一个基本的了解有助于优化它们。更多信息,请参阅Google的决策森林类

超参数页面列出了可用的超参数并进行了解释。

随机森林还是梯度提升树?

随机森林(RF)和梯度提升树(GBT)是用于训练决策森林的两种不同算法。每种算法都有其自身的优缺点。从高层次来看,RF比GBT更不容易过拟合,因此它们是小型数据集和具有大量输入特征的数据集的不错选择。另一方面,GBT比RF学习效率更高。此外,GBT模型通常比类似的RF模型小得多,推理速度也更快。

在优化速度时,使用GBT。在优化质量时,应测试两种算法。

警告:两种算法都有一些共同的超参数,例如树的数量和树的最大深度。然而,这些超参数在每种算法中扮演的角色不同,应相应地进行调整。例如,GBT的最大树深度通常在3到8之间,而在RF中很少小于16。

优化模型质量

自动超参数调优

自动超参数调优是提高模型质量的一种简单但昂贵的解决方案。当完全超参数调优过于昂贵时,结合超参数调优和手动调优是一个很好的解决方案。

详情请参阅调优笔记本

超参数模板

YDF学习器的默认超参数设置为重现最初发布的算法,新方法默认情况下总是禁用的。

因此,默认参数并未针对性能进行优化,这可能导致合理但不理想的结果。为了在不理解这些超参数的情况下从最新的YDF算法中受益,并且无需运行超参数调优,YDF提供了预配置的超参数模板

可以通过调用hyperparameter_templates来获取超参数模板。

# 列出GBT学习器的可用模板。
templates = ydf.GradientBoostedTreesLearner.hyperparameter_templates()
print(templates)

# 使用"better_defaultv1"模板:
learner = ydf.GradientBoostedTreesLearner(**templates["better_defaultv1"], ...)

超参数模板也可以在超参数页面上找到。请注意,不同的学习器有不同的模板。

增加树的数量

num_trees参数控制模型中树的数量。增加树的数量通常会提高模型的质量。默认情况下,YDF使用300棵树训练模型。对于高质量的模型,有时使用1000棵甚至更多的树是有价值的。

注意:当使用早期停止(默认行为)训练梯度提升树模型时,早期停止可能会将模型中的树数量减少到小于“num_trees”的值。

使用斜向树

默认情况下,树是“正交”或“轴对齐”的,即每个分割/条件测试单个特征。相比之下,斜向树中的条件可以使用多个特征。斜向分割通常通过提高性能来实现,但训练速度较慢。

斜向树的训练成本更高。num_projections_exponent参数在训练时间和最终模型质量中起着重要作用(1是便宜的,2是更好但更昂贵的)。更多详情请参阅DecisionTreeTrainingConfig中的SparseObliqueSplit

learner = ydf.RandomForestLearner(
  split_axis="SPARSE_OBLIQUE",
  sparse_oblique_normalization="MIN_MAX",
  sparse_oblique_num_projections_exponent=1.0,
  ...)

随机分类分割(GBT和RF)

默认情况下,分类分割使用CART分类算法进行学习。随机分类算法是另一种可以提高模型性能的解决方案。 以模型大小为代价的性能表现。

learner = ydf.RandomForestLearner(categorical_algorithm="RANDOM", ...)

减少收缩率 [仅限GBT]

“收缩率”,有时也称为“学习率”,决定了GBT模型学习的速度。缓慢学习可以提高模型质量。shrinkage默认值为0.1。你可以尝试0.05或0.02。

其他对GBT有重大影响的超参数

虽然所有超参数都可以提高模型的质量,但有些超参数比其他超参数影响更大。除了上述提到的参数外,以下是GBT最重要的参数:

  • use_hessian_gain(默认False)。例如尝试use_hessian_gain=True
  • max_depth(默认6)。例如尝试max_depth=5
  • num_candidate_attributes_ratio(默认1)。例如尝试num_candidate_attributes_ratio=0.9
  • min_examples(默认5)。例如尝试min_examples=10
  • growing_strategy(默认"LOCAL")。例如尝试growing_strategy="BEST_FIRST_GLOBAL"

注意: 当使用growing_strategy=LOCAL(默认)训练模型时,通常有益于调整max_depth参数(默认6)。当使用growing_strategy=BEST_FIRST_GLOBAL训练模型时,最好不限制max_depth(默认-1),而是调整max_num_nodes参数。

禁用验证数据集(仅限GBT)

默认情况下,如果没有提供验证数据集,梯度提升树学习器会提取10%的训练数据集来构建一个验证数据集,以控制早期停止(即当模型开始过拟合时停止训练)。

对于小型和大型数据集,使用所有数据进行训练(因此禁用早期停止)可能是有益的。在这种情况下,应调整num_trees参数。

learner = ydf.GradientBoostedTreesLearner(validation_ratio=0.0, ...)

警告: 禁用早期停止可能会导致模型过拟合。为避免这种情况,首先在启用早期停止的情况下运行训练,以确定最佳的树数量。例如,如果早期停止在训练结束前从未触发,你可能可以禁用它(并使用额外的数据进行训练)。如果早期停止总是在接近某个树数量时触发,你也可以这样做。请记住,更改任何其他超参数都需要你重新测试早期停止的行为。

优化模型速度(和大小)

模型的速度和大小受输入特征数量、树的数量和树的平均深度的限制。

你可以使用benchmark方法测量模型的推理速度。

model.benchmark(dataset)

结果示例

每个示例和每个CPU核心的推理时间:0.702微秒
估计在3.026秒内进行了441次运行。
* 使用C++服务API测量。查看model.to_cpp()获取详细信息。

从随机森林切换到梯度提升树

随机森林模型比梯度提升树模型大得多且慢。当速度重要时,使用梯度提升树模型。

# 之前
learner = ydf.RandomForestLearner(...)

# 之后
learner = ydf.GradientBoostedTreesLearner(...)

减少树的数量

num_trees参数控制模型中的树数量。减少此参数将减少模型的大小,但会牺牲模型质量。

注意: 当使用早期停止(默认行为)训练梯度提升树模型时,早期停止可能会将模型中的树数量减少到小于“num_trees”的值。

当使用growing_strategy="BEST_FIRST_GLOBAL"训练时,最好不要限制最大树数量,而是优化max_num_nodes

移除模型调试数据

YDF模型包含用于模型解释和调试的元数据。这些元数据不用于模型推理,可以丢弃以减少模型大小。移除这些数据通常会将模型大小减少约50%。移除这些数据不会提高模型的速度。

要训练一个没有元数据的模型,请将学习器构造函数参数pure_serving_model=True

learner = ydf.GradientBoostedTreesLearner(pure_serving_model=True, ...)

如果使用CLI API,可以使用edit_model CLI工具移除元数据:

# 从模型中移除元数据
./edit_model --input=/tmp/model_with_metadata --output=/tmp/model_without_metadata --pure_serving=true

# 查看模型的大小
du -h /tmp/model_with_metadata
du -h /tmp/model_without_metadata

设置winner_take_all_inference=False与随机森林

随机森林学习器的winner_take_all_inference参数默认设置为True。这确保了默认情况下,YDF随机森林是 等同于Breiman的原始随机森林。

然而,在许多情况下,winner_take_all=False可以减小模型的大小并提高随机森林模型的质量。

learner = ydf.RandomForestLearner(winner_take_all=False, ...)

设置 maximum_model_size_in_memory_in_bytes=...

maximum_model_size_in_memory_in_bytes 参数控制模型在内存中的最大大小。通过设置此值,您可以控制模型的最终大小。

模型在内存中的大小可能大于模型在磁盘上的大小。加载模型到内存中使用的RAM对应于模型在内存中的大小。在运行模型推理之前,模型会被编译成通常更小的格式。

# 模型限制为10GB
learner = ydf.RandomForestLearner(maximum_model_size_in_memory_in_bytes=10e+9, ...)

不同的学习算法对最大大小的限制方式不同。

增加收缩率 [仅限GBT]

“收缩率”,有时称为“学习率”,决定了GBT模型学习的速度。学习过快通常会导致结果较差,但会生成更小、训练更快、运行更快的模型。shrinkage 默认值为0.1。您可以尝试0.15甚至0.2。