首页 > 其他分享 >梯度提升Gradient Boosting

梯度提升Gradient Boosting

时间:2024-05-12 20:19:39浏览次数:18  
标签:Gradient 梯度 self torch Boosting np array 模型

总览

Gradient Boosting 梯度提升,是一种强大的 ML 技术,用于回归和分类问题。

弱学习算法通常更易发现、更易训练。Boosting 系列算法的基本思想是将弱基础模型组合为一个强大的集成。

Gradient Boosting 的基本思想是:不断重复生成弱学习器,每次生成弱学习器的目标是拟合先前累加模型的损失函数的负梯度, 使组合上该弱学习器后的累积模型 损失往负梯度的方向减少。

Gradient Boosting 概述

约定以下符号:

  • 输入 \(x\) 输出 \(y\)
  • 模型 \(F_m(x)\)
  • 弱模型 \(f_m(x)\)
  • 损失函数 \(L(\hat{F}_m(x),y)\)

由于 Gradient Boosting 会依次训练出 \(m\) 个模型,所以用下标 \(m\) 区分它们。

在 Gradient Boosting 中,我们对 损失函数相对于模型输出的导数 感兴趣:

\[g(x)=\frac{\partial L(\hat{F}(x),y)}{\partial \hat{F}(x)} \]

为了训练出下一个弱模型 \(f_m(x)\),需要拟合模型 \(\hat{F}_{m-1}(x)\) 输出的负梯度:

\[\hat{f}_m= \underset{f}{\text{arg min}}\frac{1}{N}\sum^N_{i=1} (g(x)-f(x_i))^2 \]

很容易令人联想到均方误差 \(L(x,y)=\frac{1}{n}\sum(x_i-y_i)^2\)。可以说,获得弱模型就是使用 MSE 损失函数拟合负梯度 \(-g(x)\)

借助弱模型 \(f_m(x)\) 更新 \(\hat{F}_{m-1}(x)\),获得下一个模型 \(\hat{F}_m(x)\)。其中 \(\gamma\) 是学习率(一般在 0.01 或 0.001):

\[\hat{F}_m(x)=\hat{F}_{m-1}(x)+\gamma\hat{f}_m(x) \]

如此,一直重复获得 \(f_m(x)\) 和更新 \(F_{m-1}(x)\) 的步骤,便可逐渐获得强大模型。

第一个弱模型

第一个弱模型通常只是一个常数 \(c\)。找到一个使得损失 \(L\) 最小的常数:

\[\hat{f}_0= \underset{c}{\text{arg min}}\frac{1}{N}\sum^N_{i=1} L(c, y_i) \]

对于 MSE 损失,这个 \(c\) 就是 \(y\) 的均值。

Gradient Boosting 的步骤

有了以上的认识,应当能理解 Gradient Boosting 算法流程:

  1. 初始化一个常数模型
  2. 拟合模型的负梯度,获得一个弱模型
  3. 用弱模型更新模型
  4. 回到 step.2

实现

以下一个示例,从输入 x 预测 sigmamu

可见使用到了 DecisionTreeRegressor。这个学习器易训练,很适合堆叠。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.tree import DecisionTreeRegressor
from sklearn.linear_model import LinearRegression
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
import torch
from torch.distributions.normal import Normal
from torch.autograd import Variable
from typing import List, Optional

class GaussianGradientBoosting:
    def __init__(self,
                 learning_rate: float = 0.025,
                 max_depth: int = 1,
                 n_estimators: int =100):
        self.learning_rate: float = learning_rate
        self.max_depth: int = max_depth
        self.n_estimators: int = n_estimators
        self.init_mu: Optional[float] = None
        self.mu_trees: List[DecisionTreeRegressor] = []
        
        self.init_sigma: Optional[float] = None
        self.sigma_trees: List[DecisionTreeRegressor] = []
        
        self.is_trained: bool = False
    def predict(self, X: np.array) -> np.array:
        assert self.is_trained
        mus = self._predict_mus(X).reshape(-1,1)
        log_sigmas = np.exp(self._predict_log_sigmas(X).reshape(-1,1))
        return np.concatenate([mus, log_sigmas], 1) 
    def _predict_raw(self, X: np.array) -> np.array:
        assert self.is_trained
        mus = self._predict_mus(X).reshape(-1,1)
        log_sigmas = self._predict_log_sigmas(X).reshape(-1,1)
        return np.concatenate([mus, log_sigmas], 1) 
    
    def fit(self, X: np.array, y: np.array) -> None:
        self._fit_initial(y)
        self.is_trained = True
        for _ in range(self.n_estimators):
            y_pred = self._predict_raw(X)
            gradients = self._get_gradients(y, y_pred)
            mu_tree = DecisionTreeRegressor(max_depth=self.max_depth)
            mu_tree.fit(X, gradients[:,0])
            self.mu_trees.append(mu_tree)
            sigma_tree = DecisionTreeRegressor(max_depth=self.max_depth)
            sigma_tree.fit(X, gradients[:,1])
            self.sigma_trees.append(sigma_tree)
    def _fit_initial(self, y: np.array) -> None:
        assert not self.is_trained
        
        self.init_mu = np.mean(y)
        self.init_sigma = np.log(np.std(y))
    def _get_gradients(self, y: np.array, y_pred: np.array) -> np.array:
        y_torch = torch.tensor(y).float()
        y_pred_torch = Variable(torch.tensor(y_pred).float(), requires_grad=True)
        normal_dist = Normal(y_pred_torch[:,0], torch.exp(y_pred_torch[:,1])).log_prob(y_torch).sum()
        normal_dist.backward()
        return y_pred_torch.grad.numpy()
    def _predict_mus(self, X: np.array) -> np.array:
        output = np.zeros(len(X))
        output += self.init_mu
        for tree in self.mu_trees:
            output += self.learning_rate * tree.predict(X)
        return output
    def _predict_log_sigmas(self, X: np.array) -> np.array:
        output = np.zeros(len(X))
        output += self.init_sigma
        for tree in self.sigma_trees:
            output += self.learning_rate * tree.predict(X)
        return output

参考来源

标签:Gradient,梯度,self,torch,Boosting,np,array,模型
From: https://www.cnblogs.com/chirp/p/18188119

相关文章

  • 策略梯度玩 cartpole 游戏,强化学习代替PID算法控制平衡杆
     cartpole游戏,车上顶着一个自由摆动的杆子,实现杆子的平衡,杆子每次倒向一端车就开始移动让杆子保持动态直立的状态,策略函数使用一个两层的简单神经网络,输入状态有4个,车位置,车速度,杆角度,杆速度,输出action为左移动或右移动,输入状态发现至少要给3个才能稳定一会儿,给2个完全学不明白,......
  • 数据分享|python分类预测职员离职:逻辑回归、梯度提升、随机森林、XGB、CatBoost、LGB
    全文链接:https://tecdat.cn/?p=34434原文出处:拓端数据部落公众号分析师:ShilinChen离职率是企业保留人才能力的体现。分析预测职员是否有离职趋向有利于企业的人才管理,提升组织职员的心理健康,从而更有利于企业未来的发展。解决方案任务/目标采用分类这一方法构建6种模型对职......
  • 导数、偏导数、方向导数与梯度
    目录导数偏导数全微分方向导数梯度参考导数导数是一元函数的概念.函数\(y=f(x)\)在点\(x_0\)的某个邻域内有定义,自变量\(x\)在\(x_0\)处每取得\(\Deltax\)增量,因变量\(y\)取得\(\Deltay=f(x_0+\Deltax)-f(x_0)\)增量.如果\(\Deltax\to0\)时,极限\(\lim\limits_{\Deltax\t......
  • 临近点梯度法
    可微凸优化临近点梯度法 求解约束优化问题: \begin{align*} \mathop{min}\limits_{x}&\quadf(x)\\ s.t.&\quadx\inS \end{align*} 其中,$f$是可微凸函数,$S$是凸集合。这个问题等价于: \begin{align*} \mathop{min}\limits_{x}&\quadf(x)+I_S(x)\\ \end{align*}其中$I......
  • 随机森林Adaboosting算法与Python实现(二)
    AdaBoost是Freund和Schapire于1996年提出的一种集成学习方法。它的核心思想是通过迭代训练一系列弱分类器,每次调整样本权重以便更好地拟合被前一轮分类器错误分类的样本,从而构建一个强分类器。最终的模型是基于这些弱分类器的加权组合。AdaBoost广泛应用于二分类和多分类问题,尤其......
  • Machine Learning - 梯度下降
    一、梯度下降:目的是为了寻找到最合适的$w$和$b$,让成本函数的值最小\[w=w-α\frac{\partialJ(w,b)}{\partialw}\]\[b=b-α\frac{\partialJ(w,b)}{\partialb}\]    其中\(α\)的值通常在\(0-1\)之间,用于控制梯度下降算法的幅度。\(α\)太大,会造成发......
  • 次梯度算法的收敛性
    次梯度算法: 梯度下降法的迭代格式为$$x_{k+1}=x_k-\alpha_k\nablaf(x_k)$$ 但是对于不可微的凸函数,梯度并不存在,于是使用此梯度算法: $$x_{k+1}=x_k-\alpha_kg_k)$$其中$g_k\in\partialf(x_k)$次梯度算法的收敛性证明:假设:$f$是凸函数且存在最小值点$f^*$,且是$G-$利普西茨连......
  • 梯度下降法的两个收敛性证明
    **梯度下降法:** 对于无约束最优化问题:$$\mathop{min}_{x}f(x)$$其中$f$是可微函数,梯度下降法的更新方式如下: $$x_{k+1}=x_k-\alpha_k\nablaf(x_k)$$ 步长$\alpha_k$有多种选择方式,普通的梯度法就选择固定步长$\alpha$。 下面介绍固定步长的梯度下降法在凸函数以及强凸函数......
  • amCharts粒状梯度柱形图
    代码案例<!DOCTYPEhtml><html><head><scriptsrc="https://cdn.amcharts.com/lib/5/index.js"></script><scriptsrc="https://cdn.amcharts.com/lib/5/xy.js"></script><scriptsrc=&qu......
  • JMeter的梯度压测
        ApacheJMeter是Apache组织基于Java开发的压力测试工具,用于对软件做压力测试。   一般大家说熟悉的压测脚本方案是,通过一次次去提高线程数量,来对接口性能峰值进行摸底,如果压测任务中出现了几十几百个接口,每个接口都去压5min的(10、20、30、40.。。并发)这样......