首页 > 编程语言 >GBDT算法

GBDT算法

时间:2024-11-11 17:50:35浏览次数:5  
标签:梯度 残差 学习 算法 GBDT 拟合 test 数据

GBDT

1. 残差提升树(BDT)

梯度提升树(Grandient Boosting)是提升树(Boosting Tree)的一种改进算法,所以在讲梯度提升树之前先来说一下残差提升树。
残差提升树:

  • 通过拟合残差的方式进行提升
  • 残差 = 真实值 - 预测值
  • 残差可以是正的,也可以是负的,不能加绝对值(与绝对误差相区分)

先来个通俗理解:

  • 预测某人的年龄为100岁
  • 第1次预测:对100岁预测,预测成80岁;100 – 80 = 20(残差)
  • 第2次预测:上一轮残差20岁作为目标值,预测成16岁;20 – 16 = 4 (残差)
  • 第3次预测:上一轮的残差4岁作为目标值,预测成3.2岁;4 – 3.2 = 0.8(残差)
  • 若三次预测的结果串联起来: 80 + 16 + 3.2 = 99.2
  • 通过拟合残差可将多个弱学习器组成一个强学习器,这就是提升树的最朴素思想

在这里插入图片描述

  • 上图中所说的新模型指的是集成学习模型;残差拟合模型就是集成学习中使用到的弱学习器

上面提到的残差是什么呢?

假设:

  1. 我们前一轮迭代得到的强学习器是:ft-1(x)
  2. 损失函数是:L(y,f​t−1(x))
  3. 本轮迭代的目标是找到一个弱学习器:ht(x)
  4. 让本轮的损失最小化: L(y, ft(x))=L(y, ft−1(x)) + ht(x))

当采用平方损失函数时:

在这里插入图片描述

则:

在这里插入图片描述

令:R = y - ft-1(x),则:

在这里插入图片描述

此处,R 是当前模型拟合数据的残差(residual)

所以,对于残差提升树来说只需要简单地拟合当前模型的残差。

2. 梯度提升树(GBDT)

梯度提升树不再使用拟合残差,而是利用最速下降的近似方法,利用损失函数的负梯度作为提升树算法中的残差近似值。
在这里插入图片描述
假设: 损失函数仍然为平方损失, 则每个样本要拟合的负梯度为:

在这里插入图片描述

此时, 我们发现 GBDT 拟合的负梯度就是残差,或者说对于回归问题,拟合的目标值就是残差。

如果我们的 GBDT 进行的是分类问题,则损失函数变为 logloss此时拟合的目标值就是该损失函数的负梯度值。

  • GBDT - 回归任务,拟合的是残差(损失函数的负梯度)
  • GBDT - 分类任务,拟合的是分类的损失函数负梯度(比如损失函数采用logloss)

3. GBDT算法实现案例

在这里插入图片描述

3.1 初始化弱学习器(CART树)

我们通过计算当模型预测值为何值时,会使得第一个基学习器的平方误差最小,即:求损失函数对 f(xi) 的导数,并令导数为0.

在这里插入图片描述

在这里插入图片描述

3.2 构建第一个弱学习器(CART树)

由于我们拟合的是样本的负梯度,即:

在这里插入图片描述

由此得到数据表如下:

在这里插入图片描述
损失计算:
在这里插入图片描述

在这里插入图片描述

上表中平方损失计算过程说明(以切分点1.5为例):

  1. 切分点1.5 将数据集分成两份 [5.56],[5.56 5.7 5.91 6.4 6.8 7.05 8.9 8.7 9. 9.05]

  2. 第一份的平均值为5.56 第二份数据的平均值为(5.7+5.91+6.4+6.8+7.05+8.9+8.7+9+9.05)/9 = 7.5011

  3. 由于是回归树,每份数据的平均值即为预测值,则可以计算误差,第一份数据的误差为0,第二份数据的平方误差为 :

( 5.70 − 7.5011 ) 2 + ( 5.91 − 7.5011 ) 2 + . . . + ( 9.05 − 7.5011 ) 2 = 15.72308 (5.70-7.5011)^2+(5.91-7.5011)^2+...+(9.05-7.5011)^2 = 15.72308 (5.70−7.5011)2+(5.91−7.5011)2+...+(9.05−7.5011)2=15.72308

以 6.5 作为切分点损失最小,构建决策树如下:

在这里插入图片描述

  • 以6.5进行划分,左侧和右侧样本的输出值采用负梯度的平均值

3.3 构建第二个弱学习器(CART树)

在这里插入图片描述

以 3.5 作为切分点损失最小,构建决策树如下:

在这里插入图片描述

  • 以3.5进行划分,左侧和右侧样本的输出值采用负梯度的平均值

3.4 构建第三个弱学习器(CART树)

在这里插入图片描述

以 6.5 作为切分点损失最小,构建决策树如下:
在这里插入图片描述

3.5 最终强学习器

在这里插入图片描述

以把x=6样本为例:输入到最终学习器中的结果 :7.31 + (-1.07) + 0.22 + 0.15 = 6.61

4. GBDT算法

1.初始化弱学习器

f 0 ( x ) = arg ⁡ min ⁡ c ∑ i = 1 N L ( y i , c ) f_0(x)=\arg\min_c\sum_{i=1}^NL(y_i,c) f0​(x)=argcmin​i=1∑N​L(yi​,c)

2.对 m = 1 , 2 , ⋯   , M m=1,2,\cdots,M m=1,2,⋯,M有:

(a)对每个样本 i = 1 , 2 , ⋯   , N i=1,2,\cdots,N i=1,2,⋯,N,计算负梯度,回归任务即残差

r i m = − [ ∂ L ( y , f ( x i ) ) ∂ f ( x i ) ] = y i − f m − 1 ( x i ) r_{im}=-\left[\frac{\partial L(y,f(x_i))}{\partial f(x_i)}\right]=yi - f_{m-1}(x_i) rim​=−[∂f(xi​)∂L(y,f(xi​))​]=yi−fm−1​(xi​)

(b)将上步得到的残差作为样本新的真实值,并将数据 ( x i , r i m ) , i = 1 , 2 , . . N (x_i,r_{im}), i=1,2,..N (xi​,rim​),i=1,2,..N作为下棵树的训练数据,得到一颗新的回归树 f m ( x ) f_{m} (x) fm​(x)其对应的叶子节点区域为 R j m , j = 1 , 2 , ⋯   , J R_{jm}, j =1,2,\cdots,J Rjm​,j=1,2,⋯,J。其中J为回归树t的叶子节点的个数。

(c)对叶子区域 j = 1 , 2 , ⋯   , J j=1,2,\cdots,J j=1,2,⋯,J计算最佳拟合值

Υ j m = arg ⁡ min ⁡ ⏟ Υ ∑ x i ∈ R j m L ( y i , f m − 1 ( x i ) + Υ ) \Upsilon_{jm}=\underbrace{\arg\min}_{\Upsilon}\sum_{x_i\in R_{jm}}L(y_i, f_{m-1}(x_i)+\Upsilon) Υjm​=Υ argmin​​xi​∈Rjm​∑​L(yi​,fm−1​(xi​)+Υ)

  • Υ \Upsilon Υ相当于是在上一个学习器的残差基础上加了一个修正项

(d)更新强学习器

f m ( x ) = f m − 1 ( x ) + ∑ i = 1 J r j m I ( x ∈ R j m ) f_m(x)=f_{m-1}(x)+\sum_{i=1}^Jr_{jm}I(x\in R_{jm}) fm​(x)=fm−1​(x)+i=1∑J​rjm​I(x∈Rjm​)

(3)得到最终学习器

f ( x ) = f M ( x ) = f 0 ( x ) + ∑ m = 1 M ∑ j = 1 J r j m I ( x ∈ R j m ) f(x)=f_M(x)=f_0(x)+\sum_{m=1}^M\sum_{j=1}^Jr_{jm}I(x \in R_{jm}) f(x)=fM​(x)=f0​(x)+m=1∑M​j=1∑J​rjm​I(x∈Rjm​)

5. 泰坦尼克号案例实战

该案例是在随机森林的基础上修改的,可以对比讲解。

数据地址:

titanic数据

5.1 导包并选取特征
#1.数据导入
#1.1导入数据
import  pandas as pd
#1.2.利用pandas的read.csv模块从互联网中收集泰坦尼克号数据集
titanic=pd.read_csv("data/titanic.csv")
titanic.info() #查看信息
#2人工选择特征pclass,age,sex
X=titanic[['pclass','age','sex']]
y=titanic['survived']
#3.特征工程
#数据的填补
X['age'].fillna(X['age'].mean(),inplace=True)
5.2 切分数据及特征处理
#数据的切分
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test =train_test_split(X,y,test_size=0.25,random_state=22)
#将数据转化为特征向量
from sklearn.feature_extraction import DictVectorizer
vec=DictVectorizer(sparse=False)
X_train=vec.fit_transform(X_train.to_dict(orient='records'))
X_test=vec.transform(X_test.to_dict(orient='records'))
5.3 三种分类器训练及预测
#4.使用单一的决策树进行模型的训练及预测分析
from sklearn.tree import DecisionTreeClassifier
dtc=DecisionTreeClassifier()
dtc.fit(X_train,y_train)
dtc_y_pred=dtc.predict(X_test)
print("score",dtc.score(X_test,y_test))
#5.随机森林进行模型的训练和预测分析
from sklearn.ensemble import RandomForestClassifier
rfc=RandomForestClassifier(random_state=9)
rfc.fit(X_train,y_train)
rfc_y_pred=rfc.predict(X_test)
print("score:forest",rfc.score(X_test,y_test))
#6.GBDT进行模型的训练和预测分析
from sklearn.ensemble import GradientBoostingClassifier
gbc=GradientBoostingClassifier()
gbc.fit(X_train,y_train)
gbc_y_pred=gbc.predict(X_test)
print("score:GradientBoosting",gbc.score(X_test,y_test))
5.4 三种分类器性能评估
#7.性能评估
from sklearn.metrics import classification_report
print("dtc_report:",classification_report(dtc_y_pred,y_test))
print("rfc_report:",classification_report(rfc_y_pred,y_test))
print("gbc_report:",classification_report(gbc_y_pred,y_test))

6. 集成算法多样性

集成学习中,个体学习器多样性越大越好。通常为了增大个体学习器的多样性,在学习过程中引入随机性。常用的方法包括:对数据样本进行扰动、对输入属性进行扰动、对算法参数进行扰动。

6.1 数据样本扰动

给定数据集,可以使用采样法从中产生出不同的数据子集。然后在利用不同的数据子集训练出不同的个体学习器。

该方法简单有效,使用广泛。

(1)数据样本扰动对于“不稳定学习器”很有效。“不稳定学习器”是这样一类学习器:训练样本稍加变化就会导致学习器有显著的变动,如决策树和神经网络等。

(2)数据样本扰动对于“稳定学习器”无效。“稳定学习器”是这样一类学习器:学习器对于数据样本的扰动不敏感,如线性学习器、支持向量机、朴素贝叶斯、K近邻学习器等。

如Bagging算法就是利用Bootstrip抽样完成对数据样本的自助采样。

6.2 输入属性的扰动

训练样本通常由一组属性描述,可以基于这些属性的不同组合产生不同的数据子集,然后在利用这些数据子集训练出不同的个体学习器。

(1)若数据包含了大量冗余的属性,则输入属性扰动效果较好。此时不仅训练出了多样性大的个体,还会因为属性数量的减少而大幅节省时间开销。同时由于冗余属性多,即使减少一些属性,训练个体学习器也不会很差。

(2)若数据值包含少量属性,则不宜采用输入属性扰动法。

6.3 算法参数的扰动

通常可以通过随机设置不用的参数,比如对模型参数加入小范围的随机扰动,从而产生差别较大的个体学习器。

在使用交叉验证法(GridSearch网格搜索)来确定基学习器的参数时,实际上就是用不同的参数训练出来了多个学习器,然后从中挑选出效果最好的学习器。集成学习相当于将所有这些学习器利用起来了。

随机森林学习器就结合了数据样本的扰动及输入属性的扰动。

7. 小结

  1. 提升树中的每一个弱学习器通过拟合残差来构建强学习器
  2. 梯度提升树中的每一个弱学习器通过拟合负梯度来构建强学习器

标签:梯度,残差,学习,算法,GBDT,拟合,test,数据
From: https://blog.csdn.net/weixin_51385258/article/details/143665534

相关文章

  • AdaBoost算法
    Boosting和AdaBoost1.BoostingBoosting体现了提升思想,每一个训练器重点关注前一个训练器不足的地方进行训练,通过加权投票的方式,得出预测结果。Bagging与Boosting区别一:数据方面Bagging:有放回采样Boosting:全部数据集,重点关注前一个弱学习器不足区别二:投票方......
  • 【算法】【优选算法】二分查找算法(上)
    目录一、二分查找简介1.1朴素二分模板1.2查找区间左端点模版1.3查找区间右端点模版二、leetcode704.⼆分查找2.1二分查找2.2暴力枚举三、Leetcode34.在排序数组中查找元素的第⼀个和最后⼀个位置3.1二分查找3.2暴力枚举四、35.搜索插⼊位置4.1二分查找4.2......
  • 多种算法解决组合优化问题平台
    ......
  • 代码随想录算法训练营day43| 300.最长递增子序列 674. 最长连续递增序列 718. 最长
    学习资料:https://programmercarl.com/0300.最长上升子序列.html#算法公开课动态规划系列之子序列学习记录300.最长递增子序列(长度最少为1;dp[i]代表到i为止的最长子序列的长度;i的值根据i之前比如j的值来判断;每个地方都有可能获得最长长度)点击查看代码classSolution:def......
  • 算法学习—归并排序
    1.算法介绍 归并算法是一种由冯·诺伊曼发明的分治算法,相较于普通排序算法时间复杂度较低,运行效率高。通常情况下,归并算法的时间复杂度为O(nlogn)。2.算法思想以及大致步骤 归并算法主要运用到了分治以及归并的思想,主要步骤如下:首先将一个无序数组分为n个有序的单个数......
  • 算法学习—快速排序
    1.算法介绍   快速排序算法是一种高效排序算法,效率相比普通排序算法较高,通常情况下时间复杂度为O(nlogn),但在最坏情况下时间复杂度会提高到O(n^2)2.算法思想和大致步骤 快速排序算法主要用到了二分和递归的思想,主要有三个步骤:(1)在数组中选取一个元素作为基准值(pivot)......
  • 十大经典排序算法-插入排序
    插入排序的代码实现虽然没有冒泡排序和选择排序那么简单粗暴,但它的原理应该是最容易理解的了,因为只要打过扑克牌的人都应该能够秒懂。插入排序是一种最简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排......
  • 区域人数统计视频分析网关算法网关客流统计AI算法介绍及应用场景
    在当今数字化转型的浪潮中,人工智能技术正以其独特的数据处理能力和智能分析优势,深刻改变着各行各业的运作方式。特别是在客流量管理这一领域,AI算法的应用已经成为提升效率、优化决策的关键工具。本文将详细介绍客流量统计AI算法及其在区域人数统计视频分析网关中的应用,展示如何通......
  • 随机化算法
    随机化算法随机化函数rand()srand(seed);intx=rand()%n+1;seed可以是一个常数如114514也可以是时间time(0)。注意,rand()函数在windows系统下返回的取值范围为\([0,2^{15}-1]\),在linux系统下返回的取值范围为\([0,2^{31}-1]\)。mt19937mt19937rd(seed);pf("......
  • 代码随想录算法训练营第十一天 | 150. 逆波兰表达式求值+ 239. 滑动窗口最大值+347.前
    今天接着补上周末的栈与队列的part2,下午继续完成今天的任务。150.逆波兰表达式求值 给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。请你计算该表达式。返回一个表示表达式值的整数。注意:有效的算符为 '+'、'-'、'*' 和 '/' 。每个......