GBDT算法超参数评估(一)

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
云原生网关 MSE Higress,422元/月
注册配置 MSE Nacos/ZooKeeper,118元/月
简介: 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实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
相关文章
|
5天前
|
算法 数据安全/隐私保护
基于GA遗传优化算法的Okumura-Hata信道参数估计算法matlab仿真
在MATLAB 2022a中应用遗传算法进行无线通信优化,无水印仿真展示了算法性能。遗传算法源于Holland的理论,用于全局优化,常见于参数估计,如Okumura-Hata模型的传播损耗参数。该模型适用于150 MHz至1500 MHz的频段。算法流程包括选择、交叉、变异等步骤。MATLAB代码执行迭代,计算目标值,更新种群,并计算均方根误差(RMSE)以评估拟合质量。最终结果比较了优化前后的RMSE并显示了SNR估计值。
20 7
|
9天前
|
机器学习/深度学习 数据采集 算法
Python实现GBDT(梯度提升树)回归模型(GradientBoostingRegressor算法)项目实战
Python实现GBDT(梯度提升树)回归模型(GradientBoostingRegressor算法)项目实战
|
8天前
|
机器学习/深度学习 数据采集 算法
Python实现GBDT(梯度提升树)分类模型(GradientBoostingClassifier算法)并应用网格搜索算法寻找最优参数项目实战
Python实现GBDT(梯度提升树)分类模型(GradientBoostingClassifier算法)并应用网格搜索算法寻找最优参数项目实战
|
8天前
|
机器学习/深度学习 数据采集 算法
Python实现贝叶斯岭回归模型(BayesianRidge算法)并使用K折交叉验证进行模型评估项目实战
Python实现贝叶斯岭回归模型(BayesianRidge算法)并使用K折交叉验证进行模型评估项目实战
|
8天前
|
机器学习/深度学习 数据采集 监控
算法金 | DL 骚操作扫盲,神经网络设计与选择、参数初始化与优化、学习率调整与正则化、Loss Function、Bad Gradient
**神经网络与AI学习概览** - 探讨神经网络设计,包括MLP、RNN、CNN,激活函数如ReLU,以及隐藏层设计,强调网络结构与任务匹配。 - 参数初始化与优化涉及Xavier/He初始化,权重和偏置初始化,优化算法如SGD、Adam,针对不同场景选择。 - 学习率调整与正则化,如动态学习率、L1/L2正则化、早停法和Dropout,以改善训练和泛化。
9 0
算法金 | DL 骚操作扫盲,神经网络设计与选择、参数初始化与优化、学习率调整与正则化、Loss Function、Bad Gradient
|
9天前
|
机器学习/深度学习 人工智能 分布式计算
算法金 | 最难的来了:超参数网格搜索、贝叶斯优化、遗传算法、模型特异化、Hyperopt、Optuna、多目标优化、异步并行优化
机器学习中的超参数调优是提升模型性能的关键步骤,包括网格搜索、随机搜索、贝叶斯优化和遗传算法等方法。网格搜索通过穷举所有可能的超参数组合找到最优,但计算成本高;随机搜索则在预设范围内随机采样,降低计算成本;贝叶斯优化使用代理模型智能选择超参数,效率高且适应性强;遗传算法模拟生物进化,全局搜索能力强。此外,还有多目标优化、异步并行优化等高级技术,以及Hyperopt、Optuna等优化库来提升调优效率。实践中,应结合模型类型、数据规模和计算资源选择合适的调优策略。
13 0
算法金 | 最难的来了:超参数网格搜索、贝叶斯优化、遗传算法、模型特异化、Hyperopt、Optuna、多目标优化、异步并行优化
|
18天前
|
算法 索引
基于Prony算法的系统参数辨识matlab仿真
Prony算法在MATLAB2022a中用于信号分析,识别复指数信号成分。核心程序通过模拟信号X1,添加不同SNR的噪声,应用Prony方法处理并计算误差。算法基于离散序列的复指数叠加模型,通过构建矩阵并解线性方程组估计参数,实现LTI系统动态特性的辨识。
|
26天前
|
机器学习/深度学习 算法
GBDT算法超参数评估(二)
GBDT算法超参数评估关注决策树的不纯度指标,如基尼系数和信息熵,两者衡量数据纯度,影响树的生长。默认使用基尼系数,计算快速,而信息熵更敏感但计算慢。GBDT的弱评估器默认最大深度为3,限制了过拟合,不同于随机森林。由于Boosting的内在机制,过拟合控制更多依赖数据和参数如`max_features`。相比Bagging,Boosting通常不易过拟合。评估模型常用`cross_validate`和`KFold`交叉验证。
|
10天前
|
机器学习/深度学习 数据采集 算法
Python实现GA(遗传算法)对SVM分类模型参数的优化
Python实现GA(遗传算法)对SVM分类模型参数的优化
|
19天前
|
算法
基于PSO粒子群优化的PID控制器参数整定算法matlab仿真
该文探讨了使用PSO(粒子群优化)算法优化PID控制器参数的方法。通过PSO迭代,不断调整PID控制器的Kp、Ki、Kd增益,以减小控制误差。文中提供了MATLAB2022a版本的核心代码,展示了参数优化过程及结果。系统仿真图像显示了参数随迭代优化的变化。PID控制器结合PSO算法能有效提升控制性能,适用于复杂系统的参数整定,未来研究可关注算法效率提升和应对不确定性。