如何改进模型?
本文档提供了关于如何提高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分类算法进行学习。随机分类算法是另一种可以提高模型性能的解决方案。 以模型大小为代价的性能表现。
减少收缩率 [仅限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
参数。
警告: 禁用早期停止可能会导致模型过拟合。为避免这种情况,首先在启用早期停止的情况下运行训练,以确定最佳的树数量。例如,如果早期停止在训练结束前从未触发,你可能可以禁用它(并使用额外的数据进行训练)。如果早期停止总是在接近某个树数量时触发,你也可以这样做。请记住,更改任何其他超参数都需要你重新测试早期停止的行为。
优化模型速度(和大小)
模型的速度和大小受输入特征数量、树的数量和树的平均深度的限制。
你可以使用benchmark方法测量模型的推理速度。
结果示例
从随机森林切换到梯度提升树
随机森林模型比梯度提升树模型大得多且慢。当速度重要时,使用梯度提升树模型。
减少树的数量
num_trees
参数控制模型中的树数量。减少此参数将减少模型的大小,但会牺牲模型质量。
注意: 当使用早期停止(默认行为)训练梯度提升树模型时,早期停止可能会将模型中的树数量减少到小于“num_trees”的值。
当使用growing_strategy="BEST_FIRST_GLOBAL"
训练时,最好不要限制最大树数量,而是优化max_num_nodes
。
移除模型调试数据
YDF模型包含用于模型解释和调试的元数据。这些元数据不用于模型推理,可以丢弃以减少模型大小。移除这些数据通常会将模型大小减少约50%。移除这些数据不会提高模型的速度。
要训练一个没有元数据的模型,请将学习器构造函数参数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
可以减小模型的大小并提高随机森林模型的质量。
设置 maximum_model_size_in_memory_in_bytes=...
maximum_model_size_in_memory_in_bytes
参数控制模型在内存中的最大大小。通过设置此值,您可以控制模型的最终大小。
模型在内存中的大小可能大于模型在磁盘上的大小。加载模型到内存中使用的RAM对应于模型在内存中的大小。在运行模型推理之前,模型会被编译成通常更小的格式。
不同的学习算法对最大大小的限制方式不同。
增加收缩率 [仅限GBT]
“收缩率”,有时称为“学习率”,决定了GBT模型学习的速度。学习过快通常会导致结果较差,但会生成更小、训练更快、运行更快的模型。shrinkage
默认值为0.1。您可以尝试0.15甚至0.2。