梯度提升树的基本思想

news2024/11/24 8:47:28

目录

1. 梯度提升树 VS AdaBoost

2. GradientBoosting回归与分类的实现

2.1 GradientBoosting回归

2.2 GradientBoosting分类


1. 梯度提升树 VS AdaBoost

        梯度提升树(Gradient Boosting Decision Tree,GBDT)是提升法中的代表性算法,它即是当代强力的XGBoost、LGBM等算法的基石,也是工业界应用最多、在实际场景中表现最稳定的机器学习算法之一。在最初被提出来时,GBDT被写作梯度提升机器(Gradient Boosting Machine,GBM),它融合了Bagging与Boosting的思想、扬长避短,可以接受各类弱评估器作为输入,在后来弱评估器基本被定义为决策树后,才慢慢改名叫做梯度提升树。受Boosting算法首个发扬光大之作AdaBoost的启发,GBDT中自然也包含Boosting三要素:

        ① 损失函数𝐿(𝑥,𝑦):用以衡量模型预测结果与真实结果的差异

        ② 弱评估器𝑓(𝑥):(一般为)决策树,不同的boosting算法使用不同的建树过程

        ③ 综合集成结果𝐻(𝑥):即集成算法具体如何输出集成结果

同时,GBDT也遵循boosting算法的基本流程进行建模:

        依据上一个弱评估器f(x)_{t-1}的结果,计算损失函数L(x,y)
        并使用L(x,y)自适应地影响下一个弱评估器f(x)_{t}的构建。
        集成模型输出的结果,受到整体所有弱评估器f(x)_{0} ~ f(x)_{T}的影响。

但与AdaBoost不同的是,GBDT在整体建树过程中做出了以下几个关键的改变:

① 弱评估器

        GBDT的弱评估器输出类型不再与整体集成算法输出类型一致。对于AdaBoost或随机森林算法来说,当集成算法执行的是回归任务时,弱评估器也是回归器,当集成算法执行分类任务时,弱评估器也是分类器。但对于GBDT而言,无论GBDT整体在执行回归/分类/排序任务,弱评估器一定是回归器。GBDT通过sigmoid或softmax函数输出具体的分类结果,但实际弱评估器一定是回归器。

② 损失函数𝐿(𝑥,𝑦)

        在GBDT当中,损失函数范围不再局限于固定或单一的某个损失函数,而从数学原理上推广到了任意可微的函数。因此GBDT算法中可选的损失函数非常多,GBDT实际计算的数学过程也与损失函数的表达式无关。

③ 拟合残差

        GBDT依然自适应调整弱评估器的构建,但却不像AdaBoost一样通过调整数据分布来间接影响后续弱评估器。相对的,GBDT通过修改后续弱评估器的拟合目标来直接影响后续弱评估器的结构。具体地来说,在AdaBoost当中,每次建立弱评估器之前需要修改样本权重,且用于建立弱评估器的是样本𝑋以及对应的𝑦,在GBDT当中,我们不修改样本权重,但每次用于建立弱评估器的是样本𝑋以及当下集成输出H(x_{i})与真实标签𝑦的差异(y-H(x_{i}))。这个差异在数学上被称之为残差(Residual),因此GBDT不修改样本权重,而是通过拟合残差来影响后续弱评估器结构

④ 抽样思想

        GBDT加入了随机森林中随机抽样的思想,在每次建树之前,允许对样本和特征进行抽样来增大弱评估器之间的独立性(也因此可以有袋外数据集)。虽然Boosting算法不会大规模地依赖于类似于Bagging的方式来降低方差,但由于Boosting算法的输出结果是弱评估器结果的加权求和,因此Boosting原则上也可以获得由“平均”带来的小方差红利。当弱评估器表现不太稳定时,采用与随机森林相似的方式可以进一步增加Boosting算法的稳定性。

        除了以上四个改变之外,GBDT的求解流程与AdaBoost大致相同。sklearn当中集成了GBDT分类与GBDT回归,我们使用如下两个类来调用它们:

class sklearn.ensemble.GradientBoostingClassifier(*, loss='deviance', learning_rate=0.1, n_estimators=100, subsample=1.0, criterion='friedman_mse', min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_depth=3, min_impurity_decrease=0.0, init=None, random_state=None, max_features=None, verbose=0, max_leaf_nodes=None, warm_start=False, validation_fraction=0.1, n_iter_no_change=None, tol=0.0001, ccp_alpha=0.0)

class sklearn.ensemble.GradientBoostingRegressor(*, loss='squared_error', learning_rate=0.1, n_estimators=100, subsample=1.0, criterion='friedman_mse', min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_depth=3, min_impurity_decrease=0.0, init=None, random_state=None, max_features=None, alpha=0.9, verbose=0, max_leaf_nodes=None, warm_start=False, validation_fraction=0.1, n_iter_no_change=None, tol=0.0001, ccp_alpha=0.0)

比起AdaBoost,GBDT的超参数数量增加了不少,但与其他集成算法一样,GBDT回归器与GBDT分类器的超参数高度一致。

2. GradientBoosting回归与分类的实现

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.ensemble import GradientBoostingRegressor as GBR
from sklearn.ensemble import GradientBoostingClassifier as GBC
from sklearn.ensemble import AdaBoostRegressor as ABR
from sklearn.ensemble import RandomForestRegressor as RFR
from sklearn.model_selection import cross_validate, KFold
data = pd.read_csv(r"F:\\Jupyter Files\\机器学习进阶\\datasets\\House Price\\train_encode.csv",index_col=0)

def RMSE(result,name):
    return abs(result[name].mean())

2.1 GradientBoosting回归

梯度提升回归树:

#回归数据
X = data.iloc[:,:-1]
y = data.iloc[:,-1]
gbr = GBR(random_state=1412) #实例化
cv = KFold(n_splits=5,shuffle=True,random_state=1412) #定义所需的交叉验证方式
result_gbdt = cross_validate(gbr,X,y,cv=cv
                             ,scoring="neg_root_mean_squared_error" #负根均方误差
                             ,return_train_score=True
                             ,verbose=True)
RMSE(result_gbdt,"train_score") #13990.790813889864
RMSE(result_gbdt,"test_score") #28783.954343252786

 梯度提升回归与其它算法的对比

import time
modelname = ["GBDT","RF","AdaBoost","RF-TPE","Ada-TPE"]

models = [GBR(random_state=1412)
         ,RFR(random_state=1412)
         ,ABR(random_state=1412)
         ,RFR(n_estimators=89, max_depth=22, max_features=14, min_impurity_decrease=0
              ,random_state=1412, verbose=False)
         ,ABR(n_estimators=39, learning_rate=0.94,loss="exponential"
              ,random_state=1412)]

colors = ["green","gray","orange","red","blue"]

for name,model in zip(modelname,models):
    start = time.time()
    result = cross_validate(model,X,y,cv=cv,scoring="neg_root_mean_squared_error"
                            ,return_train_score=True
                            ,verbose=False)
    end = time.time()-start
    print(name)
    print("\t train_score:{:.3f}".format(RMSE(result,"train_score")))
    print("\t test_score:{:.3f}".format(RMSE(result,"test_score")))
    print("\t time:{:.2f}s".format(end))
    print("\n")

------------------------------------------------------------------------------
GBDT
	 train_score:13990.791
	 test_score:28783.954
	 time:2.54s


RF
	 train_score:11177.272
	 test_score:30571.267
	 time:6.65s


AdaBoost
	 train_score:27062.107
	 test_score:35345.931
	 time:1.20s


RF-TPE
	 train_score:11208.818
	 test_score:28346.673
	 time:1.54s


Ada-TPE
	 train_score:27401.542
	 test_score:35169.730
	 time:0.86s
算法RFAdaBoostGBDTRF
(TPE)
AdaBoost
(TPE)
5折验证
运行时间
6.65s1.20s2.54s1.54s0.86s
最优分数
(RMSE)
30571.26735345.93128783.95428346.67335169.730

首先来看默认参数下所有算法的表现。当不进行调参时,随机森林的运行时间最长、AdaBoost最快,GBDT居中,但考虑到AdaBoost的n_estimators参数的默认值为50,而GBDT和随机森林的n_estimators默认值都为100,可以认为AdaBoost的运行速度与GBDT相差不多。从结果来看,未调参状态下GBDT的结果是最好的,其结果甚至与经过TPE精密调参后的随机森林结果相差不多,而AdaBoost经过调参后没有太多改变,可以说AdaBoost极其缺乏调参空间、并且学习能力严重不足。

基于以上信息,我们可以观察三个算法的过拟合情况:

xaxis = range(1,6)
plt.figure(figsize=(8,6),dpi=80)

for name,model,color in zip(modelname[:3],models[:3],colors[:3]):
    result = cross_validate(model,X,y,cv=cv,scoring="neg_root_mean_squared_error"
                            ,return_train_score=True
                            ,verbose=False)
    plt.plot(xaxis,abs(result["train_score"]), color=color, label = name+"_Train")
    plt.plot(xaxis,abs(result["test_score"]), color=color, linestyle="--",label = name+"_Test")

plt.xticks([1,2,3,4,5])
plt.xlabel("CVcounts",fontsize=16)
plt.ylabel("RMSE",fontsize=16)
plt.title("RF vs GBDT vs AdaBoost")
plt.legend()
plt.show()

不难发现,AdaBoost是过拟合程度最轻的,这也反映出它没有调参空间的事实,而GBDT与随机森林过拟合程度差不多,不过GBDT的过拟合程度相对较轻一些,这是因为Boosting算法的原理决定了Boosting算法更加不容易过拟合

绘制随机森林调参前后、以及AdaBoost调参前后的结果对比:

xaxis = range(1,6)
plt.figure(figsize=(8,6),dpi=80)

for name,model,color in zip(modelname[2:5:2],models[2:5:2],colors[2:5:2]):
    result = cross_validate(model,X,y,cv=cv,scoring="neg_root_mean_squared_error"
                            ,return_train_score=True
                            ,verbose=False)
    plt.plot(xaxis,abs(result["train_score"]), color=color, label = name+"_Train")
    plt.plot(xaxis,abs(result["test_score"]), color=color, linestyle="--",label = name+"_Test")

plt.xticks([1,2,3,4,5])
plt.xlabel("CVcounts",fontsize=16)
plt.ylabel("RMSE",fontsize=16)
plt.title("AdaBoost vs AdaBoost-TPE")
plt.legend()
plt.show()
xaxis = range(1,6)
plt.figure(figsize=(8,6),dpi=80)

for name,model,color in zip(modelname[1:4:2],models[1:4:2],colors[1:4:2]):
    result = cross_validate(model,X,y,cv=cv,scoring="neg_root_mean_squared_error"
                            ,return_train_score=True
                            ,verbose=False)
    plt.plot(xaxis,abs(result["train_score"]), color=color, label = name+"_Train")
    plt.plot(xaxis,abs(result["test_score"]), color=color, linestyle="--",label = name+"_Test")

plt.xticks([1,2,3,4,5])
plt.xlabel("CVcounts",fontsize=16)
plt.ylabel("RMSE",fontsize=16)
plt.title("RF vs RF-TPE")
plt.legend()
plt.show()

 AdaBoost在经过精密调参后,并没有太多改变,而随机森林调参后过拟合程度明显降低,测试集上的结果明显提升,这是随机森林在潜力和根本原则上都比AdaBoost要强大的表现。

GBDT在默认参数上的结果接近经过TPE调参后的随机森林,我们来看看这两个算法的对比:

xaxis = range(1,6)
plt.figure(figsize=(8,6),dpi=80)

for name,model,color in zip(modelname[:5:3],models[:5:3],colors[:5:3]):
    result = cross_validate(model,X,y,cv=cv,scoring="neg_root_mean_squared_error"
                            ,return_train_score=True
                            ,verbose=False
                            ,n_jobs=-1)
    plt.plot(xaxis,abs(result["train_score"]), color=color, label = name+"_Train")
    plt.plot(xaxis,abs(result["test_score"]), color=color, linestyle="--",label = name+"_Test")

plt.xticks([1,2,3,4,5])
plt.xlabel("CVcounts",fontsize=16)
plt.ylabel("RMSE",fontsize=16)
plt.title("GBDT vs RF-TPE")
plt.legend()
plt.show()

 

不难发现,GBDT的过拟合程度是轻于优化后的随机森林的。并且,在大部分交叉验证的结果下,GBDT的效果都接近或好于优化后的随机森林。在cv=2时GBDT的表现远不如森林,一次糟糕的表现拉低了GBDT的整体表现,否则GBDT可能在默认参数上表现出比优化后的随机森林更好的结果。如果我们可以通过调参优化让GBDT的表现更加稳定,GBDT可能会出现惊人的表现。

2.2 GradientBoosting分类

#分类数据
X_clf = data.iloc[:,:-2]
y_clf = data.iloc[:,-2]
np.unique(y_clf) #6分类
-----------------------------------------
array([0., 1., 2., 3., 4., 5.])
#GBDT分类的实现
clf = GBC(random_state=1412) #实例化
cv = KFold(n_splits=5,shuffle=True,random_state=1412)
result_clf = cross_validate(clf,X_clf,y_clf,cv=cv
                            ,return_train_score=True
                            ,verbose=True)
result_clf
----------------------------------------------------------
{'fit_time': array([3.47425294, 3.40723777, 3.38023067, 3.39023256, 3.41823983]),
 'score_time': array([0.0040009 , 0.00400043, 0.00400066, 0.00300074, 0.00400186]),
 'test_score': array([0.89726027, 0.8869863 , 0.90410959, 0.8869863 , 0.90753425]),
 'train_score': array([0.99058219, 0.99315068, 0.99229452, 0.99143836, 0.99143836])}
# 准确率
result_clf["train_score"].mean()  # 0.9917808219178083
result_clf["test_score"].mean()   # 0.8965753424657535

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/792262.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

kali中的一些工具简单使用dirb、netdiscover、ffuf、nmap、sqlmap、hydra、msfconsole

kali渗透常用工具 dirbnetdiscover介绍 ffuf介绍 nmap介绍 sqlmaphydra介绍 msfconsolemsfconsole上线windows dirb dirb <目标URL> <字典文件> [选项] <目标URL>&#xff1a;要扫描的目标URL&#xff0c;例如&#xff1a;http://example.com。 <字典文件…

nodeiis部署步骤

用nodejs写了一个express框架的接口&#xff0c;记录一下它如何在iis上发布部署 nodeiis部署步骤 第一步 安装nodejs 安装步骤&#xff1a;略确认安装结果&#xff1a;在cmd执行命令node -v效果图 第二步 安装iisnode 下载地址&#xff1a;iisnode下载地址&#xff08;htt…

Sentinel针对IP限流

改造限流策略的针对来源选项 import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;Configuration public class Senti…

php 中文字符串反转【字符串】

场景&#xff1a;英文字符串反转 使用 方法 strrev($str) ,但是中文字符串怎么反转呢&#xff1f; 代码 /*** 多字符 字符串反转* param string $string 字符串* param string $encoding 编码* php > 7.4 否则需要实现 mb_str_split 多字符变成字符串*/ function mb_str…

【雕爷学编程】Arduino动手做(88)---水流量传感器模块4

37款传感器与执行器的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&am…

Centos7安装cloudreve+onlyoffice

Centos7安装cloudreveonlyoffice 1.安装onlyoffice 1.1 安装onlyoffice镜像 docker run -i -t -d -p 801:80 --restartalways -e JWT_ENABLEDfalse --name onlyoffice \-v /home/xxx/important_onlyoffice/logs:/var/log/onlyoffice \-v /home/xxx/important_onlyoffice/dat…

Linux搭建Promtail + Loki + Grafana 轻量日志监控系统

一、简介 日志监控告警系统&#xff0c;较为主流的是ELK&#xff08;Elasticsearch 、 Logstash和Kibana核心套件构成&#xff09;&#xff0c;虽然优点是功能丰富&#xff0c;允许复杂的操作。但是&#xff0c;这些方案往往规模复杂&#xff0c;资源占用高&#xff0c;操作苦…

可视化时序输入与输出|python

请帮我生成可视化图的python代码&#xff0c;输入是xxx变量&#xff0c;输出是xxx变量&#xff0c;横坐标是时间&#xff0c;输入用蓝线表示&#xff0c;输出用黄线表示&#xff0c;然后输入和输出在时间维度上是分别一个在前&#xff0c;一个在后。 import matplotlib.pyplot…

安全狗深度参与编写的《云原生安全配置基线规范》正式发布!

7月25日&#xff0c;由中国信息通信研究院、中国通信标准化协会主办的2023可信云大会在北京顺利开幕。 作为国内云原生安全领导厂商&#xff0c;安全狗受邀出席此次活动。 厦门服云信息科技有限公司&#xff08;品牌名&#xff1a;安全狗&#xff09;成立于2013年&#xff0c…

《算法竞赛·快冲300题》每日一题:“凹”

《算法竞赛快冲300题》将于2024年出版&#xff0c;是《算法竞赛》的辅助练习册。 所有题目放在自建的OJ New Online Judge。 用C/C、Java、Python三种语言给出代码&#xff0c;以中低档题为主&#xff0c;适合入门、进阶。 文章目录 题目描述题解C代码Java代码Python代码 “ 凹…

Java SpringMvc

0目录 java SpringMvc拓展 1.SpringMvc 创建工程&#xff0c;导入依赖 配置 web.xml文件 配置Spring配置文件&#xff0c;resources目录下新建applicationContext.xml 控制层配置 新建list.jsp并测试 Web.xml详解 如果required是true必须要传参 设置默…

深度揭秘C++继承:理解面向对象编程的核心概念

目录 一.继承1.继承与面向对象2.继承方式访问权限3.切片&#xff08;赋值转换&#xff09;4.作用域5.默认成员函数6.友元与静态函数7.解决菱形继承的二义性与数据冗余8.继承与组合 一.继承 1.继承与面向对象 我们知道C语言是面向过程的编程语言&#xff0c;C在C语言的基础上进…

【TiDB理论知识06】PD架构与作用

目录 一 PD的架构与功能 PD架构 PD作用 名词解释 路由功能 二 TSO的分配 概念 分配过程 性能问题 高可用问题 三 PD的调度原理 总流程 1 信息收集 2 生成调度 3 执行调度 四 Label的作用 Label的配置 给TiKV打标签 PD配置 一 PD的架构与功能 PD架构 PD集群…

机器学习|学习类型-监督学习

让我们来讨论什么是机器学习如下所示&#xff1a; 如果机器在给定任务中的性能随着经验的改善而改善&#xff0c;则可以说机器正在从过去的经验&#xff08;数据馈入&#xff09;中学习某些类别的任务。例如&#xff0c;假设一台机器必须预测客户今年是否会购买特定的产品&…

指针进阶(三)

指针进阶&#xff08;三&#xff09; 指针习题组&#xff1a; 01&#xff1a; int main() {int a[5] { 1, 2, 3, 4, 5 };int *ptr (int *)(&a 1);printf( "%d,%d", *(a 1), *(ptr - 1));return 0; }运行结果&#xff1a; 原因&#xff1a;这里a是数组名&a…

点云拟合球体

前言&#xff1a;在很多情况下&#xff0c;需要根据点云来拟合球体&#xff0c;本博文主要介绍各种方法的拟合情况及优缺点&#xff0c;希望对各位小伙伴有所帮助&#xff01; 目录 1. vtkFitImplicitFunction进行球拟合 2. 四点求解球 1. vtkFitImplicitFunction进行球拟合 …

汽车减震器弹簧阻尼模型及python代码

U为主动减震施加的力。 通过python control库&#xff0c;可以得到在单位脉冲激励下X1的响应曲线 import control import matplotlib.pyplot as pltM1 2500 M2 320 K1 80000 K2 500000 b1 350 b2 15020s control.TransferFunction.sH (b1*b2*s*s (b1*K2b2*K1)*s K1*…

foreverlasting and fried-chicken hdu7293

Problem - 7293 题目大意&#xff1a;给出一个n个点&#xff0c;m条边的图&#xff0c;问其中包含了几个下面这样的子图 1<n<1000; 思路&#xff1a;我们要找两个点u,v&#xff0c;他们至少有4个公共点&#xff0c;且至少有一个点的度数至少为6&#xff0c;其中还要判断…

【Nodejs】Koa基本使用

1.简介 koa 是由 Express 原班人马打造的&#xff0c;致力于成为一个更小、更富有表现力、更健壮的 Web 框架。使用 koa 编写 web 应用&#xff0c;通过组合不同的 generator&#xff0c;可以免除重复繁琐的回调函数嵌套&#xff0c;并极大地提升错误处理的效率。koa 不在内核方…

Python+Playwright自动化测试--标签页操作(tab)

1.简介 标签操作其实也是基于浏览器上下文&#xff08;BrowserContext&#xff09;进行操作的&#xff0c;而且宏哥在之前的BrowserContext也有提到过&#xff0c;但是有的童鞋或者小伙伴还是不清楚怎么操作&#xff0c;或者思路有点模糊&#xff0c;因此今天单独来对其进行讲…