sklearn GBDT源码阅读

CSDN

Example 文档:

Gradient Boosting regression

API文档:

sklearn.ensemble.GradientBoostingClassifier

sklearn.ensemble.GradientBoostingRegressor

sklearn.ensemble.HistGradientBoostingClassifier

野生博客与实现:

数学推导+纯Python实现机器学习算法15:GBDT

梯度提升树(GBDT)原理小结

scikit-learn 梯度提升树(GBDT)调参小结

gbdt的残差为什么用负梯度代替?


  • ls
class LeastSquaresError(RegressionLossFunction):
    def init_estimator(self):
        return DummyRegressor(strategy='mean')

    def __call__(self, y, raw_predictions, sample_weight=None):
        return (1 / sample_weight.sum() * np.sum(
            sample_weight * ((y - raw_predictions.ravel()) ** 2)))

    def negative_gradient(self, y, raw_predictions, **kargs):
        return y - raw_predictions.ravel()
  • lad
class LeastAbsoluteError(RegressionLossFunction):
    def init_estimator(self):
        return DummyRegressor(strategy='quantile', quantile=.5)

    def __call__(self, y, raw_predictions, sample_weight=None):
        return (1 / sample_weight.sum() * np.sum(
            sample_weight * np.abs(y - raw_predictions.ravel())))

    def negative_gradient(self, y, raw_predictions, **kargs):
        raw_predictions = raw_predictions.ravel()
        return 2 * (y - raw_predictions > 0) - 1
  • huber
class HuberLossFunction(RegressionLossFunction):
    def __init__(self, alpha=0.9):
        super().__init__()
        self.alpha = alpha
        self.gamma = None

    def init_estimator(self):
        return DummyRegressor(strategy='quantile', quantile=.5)

    def __call__(self, y, raw_predictions, sample_weight=None):
        raw_predictions = raw_predictions.ravel()
        diff = y - raw_predictions
        gamma = self.gamma
        if gamma is None:
            if sample_weight is None:
                gamma = np.percentile(np.abs(diff), self.alpha * 100)
            else:
                gamma = _weighted_percentile(np.abs(diff), sample_weight,
                                             self.alpha * 100)

        gamma_mask = np.abs(diff) <= gamma
        sq_loss = np.sum(0.5 * sample_weight[gamma_mask] *
                         diff[gamma_mask] ** 2)
        lin_loss = np.sum(gamma * sample_weight[~gamma_mask] *
                          (np.abs(diff[~gamma_mask]) - gamma / 2))
        loss = (sq_loss + lin_loss) / sample_weight.sum()
        return loss

    def negative_gradient(self, y, raw_predictions, sample_weight=None,
                          **kargs):
        raw_predictions = raw_predictions.ravel()
        diff = y - raw_predictions
        if sample_weight is None:
            gamma = np.percentile(np.abs(diff), self.alpha * 100)
        else:
            gamma = _weighted_percentile(np.abs(diff), sample_weight,
                                         self.alpha * 100)
        gamma_mask = np.abs(diff) <= gamma
        residual = np.zeros((y.shape[0],), dtype=np.float64)
        residual[gamma_mask] = diff[gamma_mask]
        residual[~gamma_mask] = gamma * np.sign(diff[~gamma_mask])
        self.gamma = gamma
        return residual
  • quantile
class QuantileLossFunction(RegressionLossFunction):
    def __init__(self, alpha=0.9):
        super().__init__()
        self.alpha = alpha
        self.percentile = alpha * 100

    def init_estimator(self):
        return DummyRegressor(strategy='quantile', quantile=self.alpha)

    def __call__(self, y, raw_predictions, sample_weight=None):
        raw_predictions = raw_predictions.ravel()
        diff = y - raw_predictions
        alpha = self.alpha

        mask = y > raw_predictions
        if sample_weight is None:
            loss = (alpha * diff[mask].sum() -
                    (1 - alpha) * diff[~mask].sum()) / y.shape[0]
        else:
            loss = ((alpha * np.sum(sample_weight[mask] * diff[mask]) -
                    (1 - alpha) * np.sum(sample_weight[~mask] *
                                         diff[~mask])) / sample_weight.sum())
        return loss

    def negative_gradient(self, y, raw_predictions, **kargs):
        alpha = self.alpha
        raw_predictions = raw_predictions.ravel()
        mask = y > raw_predictions
        return (alpha * mask) - ((1 - alpha) * ~mask)
  • deviance

二项式偏差度

from scipy.special import expit, logsumexp

class BinomialDeviance(ClassificationLossFunction):
    def init_estimator(self):
        return DummyClassifier(strategy='prior')

    def __call__(self, y, raw_predictions, sample_weight=None):
        return (-2 / sample_weight.sum() * np.sum(
            sample_weight * ((y * raw_predictions) -
                             np.logaddexp(0, raw_predictions))))

    def negative_gradient(self, y, raw_predictions, **kargs):
        return y - expit(raw_predictions.ravel())

在这里插入图片描述
这个公式化简一下是 − 2 [ y ⋅ y ^ − l o g ( 1 + e y ^ ) ] -2[y\cdot \hat{y}-log(1+e^{\hat{y}})] 2[yy^log(1+ey^)]

这个损失函数与numpy-ml不同,这篇博客讲的很透彻:

Scikit Binomial Deviance Loss Function

推下这个式子的负梯度

= y − e y ^ 1 + e y ^ = y − 1 1 + e − y ^ = y − σ ( y ^ ) =y-\frac{e^{\hat{y}}}{1+e^{\hat{y}}}=y-\frac{1}{1+e^{-\hat{y}}}=y-\sigma(\hat{y}) =y1+ey^ey^=y1+ey^1=yσ(y^)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值