在生产中实现梯度增强回归树 - 以数学方式描述学习模型
Posted
技术标签:
【中文标题】在生产中实现梯度增强回归树 - 以数学方式描述学习模型【英文标题】:Implementing Gradient Boosted Regression Trees in production - mathematically describing the learned model 【发布时间】:2014-08-20 03:50:35 【问题描述】:我一直在使用逻辑回归(LR 与 start_params 作为先前(训练)数据集和 L1 正则化获得的参数)来建模我们的用例(使用一些复杂的特征转换)。我在部分相同数据上尝试了 Gradient Boosting Classifier,它似乎更适合。传统上,我一直使用 Gradient Boosting Classifier 的特征重要性并将其用作我的 LR 特征工程的反馈。
我认为完全使用梯度提升 (GB) 的经典障碍是,我不太了解如何将“学习树”表达到其数学结构中。 到目前为止,我主要使用 SKLearn 文档中的 classification 和 regression 示例来玩弄和比较预测。
问题: 我知道梯度提升是一个非参数模型。这是否意味着我永远无法恢复数学结构。抱歉,如果这听起来很原始,但我没有将这些投入生产的经验。即,除非我真的实时学习和预测类别,否则我将如何将标签“分类”为一类或另一类?如何在生产中使用该模型?
# Fit regression model
params = 'n_estimators': 500, 'max_depth': 4, 'min_samples_split': 1,
'learn_rate': 0.01, 'loss': 'ls'
clf = ensemble.GradientBoostingRegressor(**params)
pred_object=clf.fit(X_train, y_train)
pred_object
GradientBoostingRegressor(alpha=0.9, init=None, learning_rate=0.01, loss='ls',
max_depth=4, max_features=None, min_samples_leaf=1,
min_samples_split=1, n_estimators=500, random_state=None,
subsample=1.0, verbose=0)
# Next, I get the feature importances,
pred_object.feature_importances_
array([ 3.08111834e-02, 1.44739767e-04, 1.31885157e-02,
2.68202997e-05, 3.01134511e-02, 2.82639689e-01,
7.67647932e-02, 5.90503853e-02, 7.86688625e-03,
2.48124873e-02, 8.52094429e-02, 3.93616279e-02,
3.50009978e-01])
我深入研究了dir(pred_object)
,但找不到我可以立即理解的东西。考虑到特征重要性数组、损失函数 ='ls'、alpha 和其他参数,是否可以将特定的数学结构放入其中?或者,因为它是一棵树,所以在尝试预测新数据点的类别时,它总是会尝试在给定更多数据点(测试集)的情况下“重新平衡”?
【问题讨论】:
你在这方面有什么进展吗?我有同样的问题,我只是想不出一种将它投入生产的方法。从数学公式中,如果可以得到系数和弱树的形成,应该可以在生产中使用。 为什么不对新数据使用predict
?
【参考方案1】:
有两种方法可以将 GBM“投入生产”。
-
将数据提取到 python、R 或您用来拟合模型的任何语言中。对其进行评分,然后将其写回数据库(或您的生产数据存储区)。这实际上可以很好地扩展:如果您可以将需要评分的“事件”放入队列中,那么您可以让 20、100 或 1000 台机器运行您的 Python 模型的副本,独立地对每个“事件”进行评分。
将您的模型编码为 SQL 语句,并在您选择的数据库上运行它。 (如果您使用的是 nosql 数据库或其他一些数据存储,希望您有一些运行 if-then-else 语句的方法。
1 是不言自明的。将您的生产数据分解为可管理的块,并在运行模型的不同机器上对每个块进行评分。这需要一些工作来构建基础架构,但您不需要更改任何建模代码。
2 有点难以理解:基于树的模型的核心是 if-else 语句的集合:
if var1>10 and var2<3 then outcome = 0
else if var1<10 and var2<3 then outcome = 1
else if var2<10 and var2<1 then outcome = 0
等等
此类语句在基于 SQL 的数据库中很容易编码,并且在大多数编程语言中也很容易编码。如果您可以在 python 中遍历 GBM 中的每棵树并将其转换为 SQL 语句,则可以通过运行每个 SQL 语句并将其乘以 GBM 中的正确权重来对生产中的模型进行评分。这需要您将模型转码为另一种语言,但它可以让您对数据进行评分,而无需将其从数据存储中提取出来。
【讨论】:
对于否决这个答案的人,你能发表评论解释原因吗?这是目前这个问题的唯一答案,我很乐意改进它。【参考方案2】:梯度提升,以及经典的决策树和随机森林,都属于所谓的树建模或树方法。这意味着他们的评分逻辑通常只是“如果那么,如果……否则”。不确定这是否符合“数学构造”的要求。我想不会。
根据需要数学构造的目的,我可以在以后跟进扩展。我怀疑构建的 GB 模型的观察或逐行贡献计算可能是问题背后的动机。
【讨论】:
【参考方案3】:SKompiler 库可能有助于将您训练的模型转换为 SQL(或各种其他语言)中的表达式。
from skompiler import skompile
import sys
sys.setrecursionlimit(10000) # Necessary for models with many estimators
expr = skompile(gbr.predict)
现在可以获取模型的SQL形式了:
sql_code = expr.to('sqlalchemy/sqlite')
或将其转换为 C 代码(至少在 GradientBoostingRegressor 的情况下,与其他类 C 语言兼容,例如 C++/C#/Java/javascript)
c_code = expr.to('sympy/c')
或 Rust:
rust_code = expr.to('sympy/rust')
或转至 R:
r_code = expr.to('sympy/r')
甚至是 Excel 公式:
excel_code = expr.to('excel')
(不过,使用n_estimators=500
,您将无法将其粘贴到 Excel 单元格中,因为公式将超过 Excel 允许的最大 8196 个字符)
最后,将 SKompiler expr
对象的编译器编写为您的部署可能需要的表示或代码类型并不太复杂。
【讨论】:
以上是关于在生产中实现梯度增强回归树 - 以数学方式描述学习模型的主要内容,如果未能解决你的问题,请参考以下文章
机器学习中的数学-回归(regression)梯度下降(gradient descent)