使用 OLS Base Learner 进行梯度提升

Jac*_*b H 2 python scikit-learn

我一直在使用 Sklearn 中的 Boostings 函数,我注意到sklearn.ensemble.GradientBoostingRegressor和之间的关键区别sklearn.ensemble.AdaBoostRegressor。后者允许用户指定基学习器,而前者则不允许。具体来说,sklearn.ensemble.GradientBoostingRegressor只利用树木。这有点烦人,因为在梯度提升中使用 OLS 和样条基学习器会很好。我错过了什么吗?Sklearn 库中的另一个函数或不同的 Python 库是否提供此功能?

Jus*_* Le 5

这是一种方法。

替换sklearn/ensemble/gradient_boosting.py这个脚本

然后,您将能够传递base_estimatorGradientBoostingRegressor.

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

示范

在我们开始之前,我想提一些事情。这篇文章中的所有图都可以从这个项目的repo 中可用的脚本中复制。只需更换内容restore.sh,并run.sh为您的本地安装Sklearn的相应的目录。请记住,这两个 bash 脚本将永久覆盖您现有的 Sklearn 文件 ( gradient_boosting.py)。您可以通过简单地从 Sklearn 存储库复制文件来恢复文件。我不认为本文中展示的任何内容都是为 Sklearn 开发新功能的好习惯。我不隶属于 Sklearn,也不是经验丰富的软件开发人员。所有脚本都在 Sklearn 18.2 上进行了测试。

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

拟合单个变量的线性基 GBR。

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

基于树的 GBR 的 CV 配置文件。

究竟发生了什么变化?

我们可以使用任何 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
Run Code Online (Sandbox Code Playgroud)

接下来,我们可能会检查_decision_function(),它负责计算predict()从 调用顶级函数时的提升结果GradientBoostingRegressor。在这里,计算的核心在于一个名为 的函数predict_stages(),它是.pyx仅用于基于树的集成的增强步骤的相当低级的 Cython( ) 实现。为了为任意基学习器计算此步骤,我们绕过整个predict_stages()计算并在 Python 级别手动输入:

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
Run Code Online (Sandbox Code Playgroud)

以上两个改动是我认为需要做的主要改动。其余的是次要的技术细节,它们包括:

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

什么不能做(还)?

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

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

以下是我的脚本不能(必须)执行的操作:

  • 处理除默认值之外的其他损失,'ls'。(也许可以,但我没试过。)
  • 允许base_estimator传递给GradientBoostingClassifier

总的来说,这只是迈向真正定制的基础学习者的一个适度的开始。希望能帮助到你。