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