使用OLS基础学习者的梯度提升

时间:2017-06-25 22:54:12

标签: python scikit-learn

我一直在使用Sklearn中的Boostings功能,我注意到sklearn.ensemble.GradientBoostingRegressorsklearn.ensemble.AdaBoostRegressor之间的关键区别。虽然后者允许用户指定基础学习者,但前者不允许。具体来说,sklearn.ensemble.GradientBoostingRegressor仅使用树。这有点烦人,因为在Gradient Boosting中使用OLS和Spline基础学习者会很不错。我错过了什么吗? Sklearn库中的另一个函数或不同的python库是否提供此功能?

1 个答案:

答案 0 :(得分:3)

这是实现目标的一种方式。

sklearn/ensemble/gradient_boosting.py替换为this script

然后,您就可以将base_estimator传递给GradientBoostingRegressor

如果您满意,请尽情享受。如果没有,请参阅下面的讨论。

示范

在开始之前,我想提一些事情。此帖中的所有图都可以从the scripts available in my repo复制到此项目中。只需将restore.shrun.sh的内容替换为本地安装Sklearn的相应目录即可。请记住,两个bash脚本将永久覆盖现有的Sklearn文件(gradient_boosting.py)。您只需从Sklearn仓库复制文件即可恢复该文件。我并不是说在这篇文章中展示的任何内容都是开发Sklearn新功能的好方法。我不隶属于Sklearn,也不是一位经验丰富的软件开发人员。所有脚本都在Sklearn 18.2上进行了测试。

现在,使用新的gradient_boosting.py脚本,我们可以指定线性基础学习器(通常用于AdaBoostRegressor)。作为一个完整性检查,我们可以将线性基础GBR放在单个变量上,并确保在针对该变量绘制时产生线性视觉。这是波士顿住房数据集中四个(任意)变量的结果。

Linear-base GBR fitted to single variables.

作为另一个健全性检查,我们可以确保通过将树base_estimat传递给新的GBR来再现原始的基于树的GBR的结果。下图是关于增强迭代的MSE 10倍交叉验证配置文件。也就是说,对于每次增强迭代次数,我交叉验证以获得10个MSE分数的向量并计算该向量的平均值/分钟。左图是原始GBR,而右图是使用新gradient_boosting.py的图。

CV profile for tree-base GBR.

究竟发生了什么变化?

我们可以use any diffchecker将原始gradient_boosting.py与新版_fit_stage()进行比较。这将显示我为创建此新脚本所采取的所有步骤,但主要步骤是修改_decision_function()_fit_stage()方法。在tree内,负责在每次提升迭代时拟合学习者,我们注意到基础学习者(名为DecisionTreeRegressor)用base_estimator实例化,所以我们只需要添加以下内容条件,以便此方法使用if (self.base_estimator is None or isinstance(self.base_estimator, (BaseDecisionTree, BaseForest))): # Original code for decision trees will go here. else: base_learner = self.base_estimator if X_csc is not None: base_learner.fit(X_csc, residual, sample_weight=sample_weight) else: base_learner.fit(X, residual, sample_weight=sample_weight) if X_csr is not None: y_pred[:, k] += self.learning_rate * base_learner.predict(X_csr).ravel() else: y_pred[:, k] += self.learning_rate * base_learner.predict(X).ravel() self.estimators_[i, k] = base_learner 参数指定的自定义学习器:

_decision_function()

接下来,我们可能会检查predict(),它负责在从GradientBoostingRegressor调用顶级predict_stages()函数时计算增强结果。这里,计算的核心在于一个名为.pyx的函数,它是仅用于基于树的集合的增强步骤的相当低级的Cython(predict_stages())实现。为了为任意基础学习者计算此步骤,我们绕过整个def _decision_function(self, X): score = self._init_decision_function(X) score += self.learning_rate*sum(estimator[0].predict(X) for estimator in self.estimators_).reshape((-1, 1)) # predict_stages(self.estimators_, X, self.learning_rate, score) return score 计算并在Python级别手动输入:

BaseGradientBoosting

以上两个变化是我认为需要做出的主要变化。其余的都是次要的技术细节,包括:

  • 如果在使用不包含要素重要性方法的基础学习者时请求要素重要性,则会显示错误消息
  • 在参数检查和估算器验证中包含基本估算器(请参阅原始脚本以查看有关这些的详细信息,因为我并不完全熟悉)
  • 在类标题和接口中包含基本估算器(例如,在GradientBoostingRegressorsample_weights的类定义中包含超文本)

还有什么不能完成?

您选择的基础学习者必须能够支持'ls'参数。出于这个原因,我无法插入类似样条的回归量(如PyEarth)。如果您或任何人设法实现此目的,请告诉我。

另请注意,使用非树基础学习者时,您仍可以无错误地传递与树相关的参数,但当然,它们将被完全忽略。

以下是我的脚本无法做到的事情:

  • 使用除默认值base_estimator之外的其他损失。 (也许它可以,但我还没试过。)
  • 允许GradientBoostingClassifier传递给{{1}}

总的来说,这只是真正定制基础学习者的一个温和的开端。希望它有所帮助。