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

Python 使用OLS基础学习器的梯度提升,python,scikit-learn,Python,Scikit Learn,我一直在使用Sklearn中的Boostings函数,我注意到Sklearn.employee.gradientboostingressionor和Sklearn.employee.AdaBoostRegressor之间的一个关键区别。后者允许用户指定基础学习者,而前者则不允许。具体来说,sklearn.employee.GradientBoostingRegressor只使用树。这有点烦人,因为在渐变增强中使用OLS和样条线基学习器会很好。我错过什么了吗?Sklearn库中的另一个函数或不同的

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

这里有一种方法

sklearn/emble/gradient_boosting.py
替换为

然后,您将能够将
base\u估计器
传递到
梯度增强回归器

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

示范 在开始之前,我想提几件事。这篇文章中的所有情节都可以从这个项目中复制出来。只需将
restore.sh
run.sh
的内容替换为适合本地安装Sklearn的目录即可。请记住,这两个bash脚本将永久覆盖现有的Sklearn文件(
gradient\u boosting.py
)。您只需从Sklearn repo复制文件即可恢复该文件。我并不认为本文中演示的任何内容都是为Sklearn开发新功能的良好实践。我不是Sklearn的会员,也不是一名经验丰富的软件开发人员。所有脚本都在Sklearn 18.2上进行了测试

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

作为另一个健全性检查,我们可以通过将树基估计量传递给新的GBR来确保原始树基GBR的结果可以复制。下面的曲线图是关于推进迭代的MSE 10倍交叉验证曲线。也就是说,对于每个boosting迭代次数,我交叉验证以获得10 MSE分数的向量,并计算该向量的平均值/分钟。左图是原始GBR,而右图是使用新的
gradient\u boosting.py
的图

到底发生了什么变化? 我们可以将原始的
gradient\u boosting.py
与新的进行比较。这将向您展示我创建这个新脚本的所有步骤,但主要步骤是修改
\u fit\u stage()
\u decision\u function()
方法。在负责在每次提升迭代中装配学习者的
\u fit\u stage()
中,我们注意到基本学习者(名为
)用
决策树重组器
实例化,因此,我们只需添加以下条件,以便此方法使用
base\u 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
接下来,我们可以检查
\u decision\u function()
,它负责在从
梯度boosting回归器调用顶级
predict()
函数时计算增强的结果。在这里,计算的核心在于一个名为
predict_stages()
的函数,它是仅用于基于树的集成的boosting步骤的低级Cython(
.pyx
)实现。为了为任意基础学习者计算此步骤,我们绕过整个
predict\u 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
上述两个变化是我认为需要做的主要变化。其余为次要技术细节,包括:

  • 使用不包含特征重要性方法的基础学习器时,如果请求特征重要性,则显示错误消息
  • 在参数检查和估计器验证中包括基本估计器(请参阅原始脚本以查看这些方面的详细信息,因为我并不完全熟悉)
  • 在类标题和接口中包括基本估算器(例如,在类定义中包括
    BaseGradientBoosting
    gradientboostingressor
    的超级文本)
什么事还不能做? 您选择的基础学习者必须能够支持
sample\u weights
参数。由于这个原因,我无法插入类似样条曲线的回归器(例如PyEarth)。请让我知道,如果你或任何人设法实现这一点

还请注意,当使用非树基学习器时,您仍然可以传递与树相关的参数而不会出错,但当然,它们将被完全忽略

以下是我的脚本无法(必须)完成的事情:

  • 处理除默认损失以外的其他损失,
    'ls'
    。(也许可以,但我还没试过。)
  • 允许将
    base\u估计器
    传递给
    GradientBoostingClassifier

总的来说,对于真正的定制基础学习者来说,这只是一个适度的开始。希望能有所帮助。

可能是因为scikit中使用的梯度增强实际上是,也可能是因为这是最常见的梯度增强形式。其他最流行的库,如
xgboost
,也只使用树。xgboost允许使用线性学习器(使用booster='gblinear')