GBDT算法超参数评估(一)

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
注册配置 MSE Nacos/ZooKeeper,118元/月
云原生网关 MSE Higress,422元/月
简介: GBDT(Gradient Boosting Decision Tree)是一种强大的机器学习技术,用于分类和回归任务。超参数调整对于发挥GBDT性能至关重要。其中,`n_estimators`是一个关键参数,它决定了模型中弱学习器(通常是决策树)的数量。增加`n_estimators`可以提高模型的复杂度,提升预测精度,但也可能导致过拟合,并增加训练时间和资源需求。

GBDT(Gradient Boosting Decision Tree)算法是一种强大的机器学习技术,广泛应用于分类、回归等任务。然而,为了充分发挥其性能,超参数的合理设置至关重要。超参数,如学习率、树的最大深度、子样本比例等,直接影响到模型的复杂度、训练速度和预测精度。因此,对GBDT算法的超参数进行细致的评估和调整,是确保模型性能达到最优的关键步骤。


弱评估器数量:参数n_estimators


n_estimators指的是集成算法中弱评估器的数量。对于Boosting算法来说,可以使用任意弱评估器,当然了默认的弱评估器还是决策树。GBDT算法无论是分类器还是回归器,默认弱评估器都是回归树。


X_c,y_c = load_wine(return_X_y=True,as_frame=True) #分类数据
X_r,y_r = fetch_california_housing(return_X_y=True,as_frame=True) #回归数据
 
# 建立GBDT分类器和回归器
clf = GBC(n_estimators=2).fit(X_c,y_c)
reg = GBR(n_estimators=2).fit(X_r,y_r)
 
# n_estimators_:实际迭代次数
clf.n_estimators_
2
 
reg.n_estimators_
2
 
# estimators_:实际建立的弱评估器数量
clf.estimators_
 
array([[DecisionTreeRegressor(criterion='friedman_mse', max_depth=3,
                              random_state=RandomState(MT19937) at 0x1083D8340),
        DecisionTreeRegressor(criterion='friedman_mse', max_depth=3,
                              random_state=RandomState(MT19937) at 0x1083D8340),
        DecisionTreeRegressor(criterion='friedman_mse', max_depth=3,
                              random_state=RandomState(MT19937) at 0x1083D8340)],
       [DecisionTreeRegressor(criterion='friedman_mse', max_depth=3,
                              random_state=RandomState(MT19937) at 0x1083D8340),
        DecisionTreeRegressor(criterion='friedman_mse', max_depth=3,
                              random_state=RandomState(MT19937) at 0x1083D8340),
        DecisionTreeRegressor(criterion='friedman_mse', max_depth=3,
                              random_state=RandomState(MT19937) at 0x1083D8340)]],
      dtype=object)
 
reg.estimators_
 
 
array([[DecisionTreeRegressor(criterion='friedman_mse', max_depth=3,
                              random_state=RandomState(MT19937) at 0x1083D8340)],
       [DecisionTreeRegressor(criterion='friedman_mse', max_depth=3,
                              random_state=RandomState(MT19937) at 0x1083D8340)]],
      dtype=object)


  • 对于 GradientBoostingRegressor,因为处理的是回归问题,每个迭代步骤只构建一个回归树来预测连续的目标变量。所以,在回归器的 estimators_ 中有两个 DecisionTreeRegressor 实例,与指定的 n_estimators=2 相匹配。
  • 对于 GradientBoostingClassifier,如果数据是多类别的(比如 wine 数据集可能有多个类别),则在每个提升迭代中,算法会为每个类别构建一个回归树来预测该类别的概率。因此,如果数据集有三个类别,每个迭代步骤将会构建三个树,每个树预测一个类别的概率。
  • 如果是二分类则不会出现这种现象



出现这种情况的根本原因在于:GBDT的弱评估器为回归树,在实际调用GBDT来完成分类任务时,需要softmax函数或者sigmoid函数对回归树输出的结果进行处理。对于二分类来说,就是直接调用sigmoid函数,输出的概率值大于0.5就被预测为类别1 ,反之预测为类别0。


对于多分类来说,就比较复杂了。在多分类任务中,我们必须求解出所有标签类别所对应的概率,在所有这些概率当中,最大的概率所对应的标签才是多分类的预测标签。此时,我们需要softmax函数(归一化指数函数)帮助我们将回归值转化为概率。而**softmax函数是接受K个连续型结果,并输出K个相对概率的函数。所以在使用softmax之前我们需要准备每个类别的概率值,因此就需要建立同等数量的弱评估器。  


不难发现,使用GBDT完成多分类任务时,计算量以及弱评估器数量都会远远超出二分类以及回归类问题。


参数n_estimators对模型效果的影响:


X,y = load_breast_cancer(return_X_y=True,as_frame=True)
Xtrain,Xtest,Ytrain,Ytest = train_test_split(X,y,test_size=0.3,random_state=0)
 
# 绘制n_estimators的学习曲线
 
# ===========【TIME WARNING:2min】============#
scores = []
for i in np.arange(1,300,10):
    gbc = GBC(n_estimators=i)
    s = cross_val_score(gbc,X,y,cv=5).mean()
    scores.append(s)
 
print(f"当n_estimators={np.arange(1,300,10)[scores.index(max(scores))]}时,准确率取得最大值{max(scores)}")
plt.plot(np.arange(1,300,10),scores,label = "GBDT")
plt.show()



# 细化学习曲线
scores = []
for i in np.arange(1,50):
    gbc = GBC(n_estimators=i)
    s = cross_val_score(gbc,X,y,cv=5).mean()
    scores.append(s)
 
print(f"当n_estimators={np.arange(1,50)[scores.index(max(scores))]}时,准确率取得最大值{max(scores)}")
plt.plot(np.arange(1,50),scores,label = "GBDT")
plt.show()




可以看出,随着参数n_estimators的增大,模型的效果是逐渐变好的。但是,n_estimators达到一定的程度之后,GBDT的精确性往往不在上升或开始波动,并且,n_estimators越大,需要的计算量和内存也越大,训练的时间也会越来越长。所以对于这个参数,我们是渴望在模型训练难度和模型效果之间取得平衡。  


学习率:参数`learning_rate`


在Boosting集成算法中,集成算法最终的输出结果往往是多个弱评估器输出结果的加权平均结果。但是这个最终结果并不是在所有的弱评估器建好之后才统一加权求解的,而是在逐渐建立弱评估器的过程中就随着迭代不断计算出来的。


例如,对于样本x_i,集成算法当中一共有T棵树(也就是参数`n_estimators`的取值),现在正在建立第t个弱评估器,则第t个弱评估器上x_i的结果可以表示为f_t(x_i)。假设整个Boosting算法对样本x_i输出的结果为H(x_i),则该结果一般可以被表示为t=1~t=T过程当中,所有弱评估器结果的加权求和:



  • 以上式子为boosting算法中计算方式的一般规则,并不是具体到某一个Boosting集成算法的具体公式


# 绘制不同n_estimators、learning_rate下,模型效果变化
plt.figure(figsize=(10,6))
for i in [3,10,50,100,200]:
    scores = []
    for j in np.arange(0.001,0.5,0.01):
        gbc = GBC(n_estimators=i,learning_rate=j,random_state=0)
        s = cross_val_score(gbc,X,y,cv=5).mean()
        scores.append(s)
    plt.plot(np.arange(0.001,0.5,0.01),scores,label = f"n_estimators={i}")
    plt.legend()



初始预测结果的设置:参数init


  • 传入实例的参数



from sklearn.metrics import mean_squared_error as MSE
 
X,y = fetch_california_housing(return_X_y=True,as_frame=True)
Xtrain,Xtest,Ytrain,Ytest = train_test_split(X,y,test_size=0.3,random_state=0)
 
for init in [DTR(),RFR(),"zero",None]:
    reg = GBR(init = init,random_state=0)
    reg = reg.fit(Xtrain,Ytrain)
    MSE_train = MSE(Ytrain,reg.predict(Xtrain))
    MSE_test = MSE(Ytest,reg.predict(Xtest))
    
    print(f"{init}:")
    print(f"训练集MSE:{MSE_train}")
    print(f"测试集MSE:{MSE_test}")
    print("\n")
 
 
zero:
训练集MSE:0.25572269323849983
测试集MSE:0.289857007749968
 
 
None:
训练集MSE:0.25572269022058913
测试集MSE:0.2897994977087412
 
  • 不难发现,初始参数的具体输入会对模型的最终结果造成巨大影响,在init中输入训练好的模型会加重GBDT的过拟合,但同时也可能得到更好的测试集结果。


GBDT的6种损失函数:参数loss


GBDT算法的损失函数非常多,我们在调参的时候可以把损失函数作为需要调整的参数进行考量。在sklearn中,控制具体损失函数的参数为:loss。GBDT中的损失函数因GBDT具体执行的预测任务而存在区别,同时也因标签的分布而存在区别。


老版本


对于梯度提升分类树来说,loss的备选项有2种:{"deviance", "exponential"},默认值为"deviance"。


  • "deviance":直译为偏差,特指逻辑回归的损失函数——**交叉熵损失**;
  • "exponential":表示的是 指数损失函数。需要注意的是:此损失函数只能支持二分类数据**。


新版本


deviance ->log_loss


对于梯度提升回归树来说,loss的备选项有如下几种:


  • “squared_error”:指回归的平方误差;
  • “absolute_error”:指回归的绝对误差;
  • “huber”:平方误差和绝对误差的结合(使用alpha进行调节);
  • “quantile”:表示允许分位数回归(使用alpha 指定分位数)


其中的alpha是需要我们自己设置的超参数,由参数alpha控制。在huber损失中,alpha是阈值,在quantile损失中,alpha用于辅助计算损失函数的输出结果,默认为0.9。


=========更新警告=========


在sklearn1.0版本及后续版本当中,损失函数"ls"与"lad"被删除了,其中"ls"的功能被"squared_error"取代,而"lad"被"absolute_error"取代。如果你在运行代码时,发现你的参数默认值、参数名称与课件中不相同,或者在运行过程中出现报错、警告等现象,你可能需要更新你的sklearn。



=========================


GBDT是工业应用最广泛的模型,工业数据大部分都极度偏态、具有长尾,因此GBDT必须考虑离群值带来的影响。数据中的离群值会极大程度地影响模型地构建,当离群值在标签当中、而我们是依赖于减小损失函数来逐渐构建算法时,这种影响会前所未有地大。因此Boosting是天生更容易被离群值影响的模型、也更擅长学习离群值的模型。



举例来说,若离群值的标签为1000,大部分正常样本的标签在0.1~0.2之间,算法一定会异常努力地学习离群值的规律,因为将离群值预测错误会带来巨大的损失。在这种状况下,最终迭代出的算法可能是严重偏离大部分数据的规律的。同样,我们也会遇见很多离群值对我们很关键的业务场景:例如,电商中的金额离群用户可能是VIP用户,风控中信用分离群的用户可能是高风险用户,这种状况下我们反而更关注将离群值预测正确。不同的损失函数可以帮助我们解决不同的问题——


  • 当高度关注离群值、并且希望努力将离群值预测正确时,选择平方误差squared_error


  • 这在工业中是大部分的情况。在实际进行预测时,离群值往往比较难以预测,因此离群样本的预测值和真实值之间的差异一般会较大。MSE作为预测值和真实值差值的平方,会放大离群值的影响,会让算法更加向学习离群值的方向进化,这可以帮助算法更好地预测离群值。


  • 努力排除离群值的影响、更关注非离群值的时候,选择绝对误差absolute_error


  • MAE对一切样本都一视同仁,对所有的差异都只求绝对值,因此会保留样本差异最原始的状态。相比其MSE,MAE对离群值完全不敏感,这可以有效地降低GBDT在离群值上的注意力。


  • 试图平衡离群值与非离群值、没有偏好时,选择huber或者quantile


  • Huberloss损失结合了MSE与MAE,在Huber的公式中,当预测值与真实值的差异大于阈值时,则取绝对值,小于阈值时,则取平方。在真实数据中,部分离群值的差异会大于阈值,部分离群值的差异会小于阈值,因此比起全部取绝对值的MAE,Huberloss会将部分离群值的真实预测差异求平方,相当于放大了离群值的影响(但这种影响又不像在MSE那样大)。因此HuberLoss是位于MSE和MAE之间的、对离群值相对不敏感的损失。



GBDT算法超参数评估(二)+https://developer.aliyun.com/article/1544809?spm=a2c6h.13148508.setting.21.22454f0e4mZEBN

相关实践学习
基于MSE实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
相关文章
|
1月前
|
算法 决策智能
基于禁忌搜索算法的VRP问题求解matlab仿真,带GUI界面,可设置参数
该程序基于禁忌搜索算法求解车辆路径问题(VRP),使用MATLAB2022a版本实现,并带有GUI界面。用户可通过界面设置参数并查看结果。禁忌搜索算法通过迭代改进当前解,并利用记忆机制避免陷入局部最优。程序包含初始化、定义邻域结构、设置禁忌列表等步骤,最终输出最优路径和相关数据图表。
|
1月前
|
算法
基于最小二乘递推算法的系统参数辨识matlab仿真
该程序基于最小二乘递推(RLS)算法实现系统参数辨识,对参数a1、b1、a2、b2进行估计并计算误差及收敛曲线,对比不同信噪比下的估计误差。在MATLAB 2022a环境下运行,结果显示了四组误差曲线。RLS算法适用于实时、连续数据流中的动态参数辨识,通过递推方式快速调整参数估计,保持较低计算复杂度。
|
2月前
|
算法 搜索推荐 开发者
别再让复杂度拖你后腿!Python 算法设计与分析实战,教你如何精准评估与优化!
在 Python 编程中,算法的性能至关重要。本文将带您深入了解算法复杂度的概念,包括时间复杂度和空间复杂度。通过具体的例子,如冒泡排序算法 (`O(n^2)` 时间复杂度,`O(1)` 空间复杂度),我们将展示如何评估算法的性能。同时,我们还会介绍如何优化算法,例如使用 Python 的内置函数 `max` 来提高查找最大值的效率,或利用哈希表将查找时间从 `O(n)` 降至 `O(1)`。此外,还将介绍使用 `timeit` 模块等工具来评估算法性能的方法。通过不断实践,您将能更高效地优化 Python 程序。
54 4
|
2月前
|
算法
基于极大似然算法的系统参数辨识matlab仿真
本程序基于极大似然算法实现系统参数辨识,对参数a1、b1、a2、b2进行估计,并计算估计误差及收敛曲线,对比不同信噪比下的误差表现。在MATLAB2022a版本中运行,展示了参数估计值及其误差曲线。极大似然估计方法通过最大化观测数据的似然函数来估计未知参数,适用于多种系统模型。
|
4月前
|
算法 搜索推荐 开发者
别再让复杂度拖你后腿!Python 算法设计与分析实战,教你如何精准评估与优化!
【7月更文挑战第23天】在Python编程中,掌握算法复杂度—时间与空间消耗,是提升程序效能的关键。算法如冒泡排序($O(n^2)$时间/$O(1)$空间),或使用Python内置函数找最大值($O(n)$时间),需精确诊断与优化。数据结构如哈希表可将查找从$O(n)$降至$O(1)$。运用`timeit`模块评估性能,深入理解数据结构和算法,使Python代码更高效。持续实践与学习,精通复杂度管理。
64 9
|
3月前
|
机器学习/深度学习 算法 搜索推荐
支付宝商业化广告算法问题之在DNN模型中,特征的重要性如何评估
支付宝商业化广告算法问题之在DNN模型中,特征的重要性如何评估
|
3月前
|
算法 搜索推荐
支付宝商业化广告算法问题之基于pretrain—>finetune范式的知识迁移中,finetune阶段全参数训练与部分参数训练的效果如何比较
支付宝商业化广告算法问题之基于pretrain—>finetune范式的知识迁移中,finetune阶段全参数训练与部分参数训练的效果如何比较
|
4月前
|
算法 数据安全/隐私保护
基于GA遗传优化算法的Okumura-Hata信道参数估计算法matlab仿真
在MATLAB 2022a中应用遗传算法进行无线通信优化,无水印仿真展示了算法性能。遗传算法源于Holland的理论,用于全局优化,常见于参数估计,如Okumura-Hata模型的传播损耗参数。该模型适用于150 MHz至1500 MHz的频段。算法流程包括选择、交叉、变异等步骤。MATLAB代码执行迭代,计算目标值,更新种群,并计算均方根误差(RMSE)以评估拟合质量。最终结果比较了优化前后的RMSE并显示了SNR估计值。
68 7
|
3月前
|
算法
基于EM期望最大化算法的GMM模型参数估计matlab仿真
此程序在MATLAB 2022a中实现了基于EM算法的GMM参数估计,用于分析由多个高斯分布组成的混合数据。程序通过迭代优化各高斯组件的权重、均值与协方差,直至收敛,并输出迭代过程的收敛曲线及最终参数估计结果。GMM假设数据由K个高斯分布混合而成,EM算法通过E步计算样本归属概率,M步更新参数,循环迭代直至收敛。
|
4月前
|
机器学习/深度学习 数据采集 算法
Python实现GBDT(梯度提升树)分类模型(GradientBoostingClassifier算法)并应用网格搜索算法寻找最优参数项目实战
Python实现GBDT(梯度提升树)分类模型(GradientBoostingClassifier算法)并应用网格搜索算法寻找最优参数项目实战
170 3