GBDT算法超参数评估(二)

简介: GBDT算法超参数评估关注决策树的不纯度指标,如基尼系数和信息熵,两者衡量数据纯度,影响树的生长。默认使用基尼系数,计算快速,而信息熵更敏感但计算慢。GBDT的弱评估器默认最大深度为3,限制了过拟合,不同于随机森林。由于Boosting的内在机制,过拟合控制更多依赖数据和参数如`max_features`。相比Bagging,Boosting通常不易过拟合。评估模型常用`cross_validate`和`KFold`交叉验证。

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


评估器的不纯度衡量指标:参数criterion


GBDT算法的弱评估器为决策树(确切地说是回归树),我们已经熟悉各种剪枝参数对模型的影响。因此,我们对于Boosting算法中控制弱评估器的参数应该也不陌生:



这些参数在GBDT中的用法与默认值与决策树类DecisionTreeRegressor中基本上一致(除了GBDT中max_depth=3),专门用于对决策树进行剪枝、控制单个弱评估器的结构,考虑到大家在决策树中已经充分掌握这些参数,我们不再对这些参数一一进行详细说明了。在这里,需要重点说明的有两部分内容,一部分梯度提升树中默认的弱评估器复杂度所带来的问题,另一部分则是梯度提升树独有的不纯度衡量指标。


  1. 基尼系数(Gini Impurity):
  • 表示为gini。
  • 计算公式:(gini = 1 - p2 - (1-p)2),其中p是样本属于某一类的概率。
  • 基尼系数越小,表示数据集的不纯度越低,即数据的纯度越高。
  • 基尼系数的计算不涉及对数,因此相对于信息熵来说,计算速度更快。
  1. 信息熵(Entropy):
  • 表示为entropy。
  • 计算公式:(entropy = -\sum_{i=1}^{n} p_i \log_2(p_i)),其中(p_i)是样本属于第i类的概率,n是类别总数。
  • 信息熵用于表示数据的不确定性或混乱程度;熵值越高,数据的不确定性越大。
  • 信息熵对不纯度更加敏感,因此它作为指标时,决策树的生长可能会更加“精细”。然而,在高维数据或噪音较多的情况下,这可能导致过拟合。
  • 信息熵的计算涉及对数运算,因此相对于基尼系数来说,计算速度可能稍慢。


梯度提升树中的弱评估器复杂度:max_depth

在随机森林中,控制过拟合的参数基本都处于“关闭状态”,比如:max_depth的默认值为None,表示弱评估器不限制深度,因此随机森林中长出的树基本上都是剪枝前的树,如果随机森林算法出现过拟合现象,那么我们就可以通过对弱评估器进行剪枝来限制集成算法的过拟合。然而,这种情况并不适用于Boosting算法一族。


从GBDT的默认参数我们可以看到,对GBDT来说,无论是分类器还是回归器,默认的弱评估器最大深度都为3,这说明GBDT默认就对弱评估器进行了剪枝操作。所以当GBDT等Boosting算法处于过拟合状态时,很难再通过剪枝的手段来控制过拟合,只能从数据上下手控制过拟合了(例如,使用参数max_features,在GBDT中其默认值为None)。


也因此,通常认为Boosting算法比Bagging算法更不容易过拟合,也就是说在相似的数据上,Boosting算法表现出的过拟合程度会较轻。


cross_validate和KFold:


from sklearn.datasets import load_iris  
from sklearn.model_selection import cross_validate, KFold  
from sklearn.svm import SVC  
  
# 加载数据集  
iris = load_iris()  
X = iris.data  
y = iris.target  
  
# 初始化SVM分类器  
clf = SVC(kernel='linear', C=1, random_state=42)  
  
# 初始化KFold对象,进行5折交叉验证  
kf = KFold(n_splits=5, shuffle=True, random_state=42)  
  
# 使用cross_validate函数进行交叉验证  
scoring = ['accuracy', 'precision_macro', 'recall_macro']  
cv_results = cross_validate(clf, X, y, cv=kf, scoring=scoring)  
  
# 打印交叉验证结果  
print(cv_results)
 
# cross_validate函数会返回一个字典,其中包含了每次迭代的评分、拟合时间和评分时间等信息


  • cross_validate:这是一个用于评估模型性能的函数,它执行交叉验证并返回每次迭代的评分以及其他相关信息。
  • KFold:这是一个类,用于实现k折交叉验证的数据划分。它本身不进行评估,而是为交叉验证提供数据划分的机制。
  • GridSearchCV:这是一个类,用于执行网格搜索和交叉验证,以找到模型的最佳超参数组合。它不仅进行数据划分和模型评估,还搜索参数空间以找到最优配置。


from sklearn.model_selection import cross_validate,KFold
 
#定义所需的交叉验证方式
cv = KFold(n_splits=5,shuffle=True,random_state=12)
 
# 分类数据
X_c,y_c = load_breast_cancer(return_X_y=True,as_frame=True)
 
modelname = ["GBDT","RF"]
colors = ["green","orange"]
clf_models = [GBC(random_state=12),RFC(random_state=12)]
 
xaxis = range(1,6)
plt.figure(figsize=(10,6),dpi=65)
 
for name,model,color in zip(modelname,clf_models,colors):
    result = cross_validate(model,X_c,y_c,cv=cv
                            ,return_train_score=True)
    plt.plot(xaxis,result["train_score"], color=color, label = name+"_Train")
    plt.plot(xaxis,result["test_score"], color=color, linestyle="--",label = name+"_Test")
 
plt.xticks([1,2,3,4,5])
plt.xlabel("CVcounts",fontsize=12)
plt.ylabel("Accuracy",fontsize=12)
plt.title("GBDT vs RF")
plt.legend()
plt.show()


  • cross_validateKFold是两个用于模型选择和评估的工具



# 回归数据
X_r,y_r = fetch_california_housing(return_X_y=True,as_frame=True)
 
# modelname = ["GBDT","RF"]
# colors = ["green","orange"]
reg_models = [GBR(random_state=12),RFR(random_state=12)]
 
xaxis = range(1,6)
plt.figure(figsize=(10,6),dpi=65)
 
for name,model,color in zip(modelname,reg_models,colors):
    result = cross_validate(model,X_r,y_r,cv=cv,scoring="neg_mean_squared_error"
                            ,return_train_score=True)
    plt.plot(xaxis,result["train_score"], color=color, label = name+"_Train")
    plt.plot(xaxis,result["test_score"], color=color, linestyle="--",label = name+"_Test")
 
plt.xticks([1,2,3,4,5])
plt.xlabel("CVcounts",fontsize=12)
plt.ylabel("MSE",fontsize=12)
plt.title("GBDT vs RF")
plt.legend()
plt.show()



对GBDT来说,不纯度的衡量指标有2个:


  • friedman_mse:弗里德曼均方误差
  • squared_error:平方误差


其中平方误差我们非常熟悉,就是直接计算父节点的平方误差与子节点平方误差的加权求和之间的差异。弗里德曼均方误差是由Friedman在论文《贪婪函数估计:一种梯度提升机器》(GREEDY FUNCTION APPROXIMATION: A GRADIENT BOOSTING MACHINE)中提出的全新的误差计算方式。根据论文中的描述,弗里德曼均方误差使用调和平均数来控制左右叶子节点上的样本数量,相比普通地求均值,调和平均必须在左右叶子节点上的样本量/样本权重相差不大的情况下才能取得较大的值(F1 score也是用同样的方式来调节Precision和recall)。这种方式可以令不纯度的下降得更快,让整体分枝的效率更高  


  • 大部分时候,使用弗里德曼均方误差可以让梯度提升树得到很好的结果,因此GBDT的默认参数就是Friedman_mse。不过许多时候,我们会发现基于平方误差的分割与基于弗里德曼均方误差的分割会得到相同的结果。


梯度提升树的提前停止


在学习机器学习理论与方法时,我们极少提及迭代的提前停止问题。在机器学习中,依赖于迭代进行工作的算法并不算多,同时课程中的数据量往往也比较小,因此难以预见需要提前停止迭代以节省计算资源或时间的情况。但对于工业界使用最广泛的GBDT而言,提前停止是需要考虑的关键问题。


对于任意需要迭代的算法,迭代的背后往往是损失函数的最优化问题。例如在逻辑回归中,我们在进行梯度下降的迭代时,是希望找到交叉熵损失函数的最小值;而在梯度提升树中,我们在一轮轮建立弱评估器过程中,也是希望找到对应损失函数的最小值。理想状态下,无论使用什么算法,只要我们能够找到损失函数上真正的最小值,那模型就达到“收敛”状态,迭代就应该被停止。


然而遗憾的是,我们和算法都不知道损失函数真正的最小值是多少,而算法更不会在达到收敛状态时就自然停止。在机器学习训练流程中,我们往往是通过给出一个极限资源来控制算法的停止,比如,我们通过超参数设置允许某个算法迭代的最大次数,或者允许建立的弱评估器的个数。因此无论算法是否在很短时间内就锁定了足够接近理论最小值的次小值、或者算法早已陷入了过拟合状态、甚至学习率太低导致算法无法收敛,大多数算法都会持续(且无效地)迭代下去,直到我们给与的极限资源全部被耗尽。对于复杂度较高、数据量较大的Boosting集成算法来说,无效的迭代常常发生,因此作为众多Boosting算法的根基算法,梯度提升树自带了提前停止的相关超参数。另外,逻辑回归看起来会自然停止,是因为逻辑回归内置提前停止机制。


我们根据以下原则来帮助梯度提升树实现提前停止:


  • 当GBDT已经达到了足够好的效果(非常接近收敛状态),持续迭代下去不会有助于提升算法表现
  • GBDT还没有达到足够好的效果(没有接近收敛),但迭代过程中呈现出越迭代算法表现越糟糕的情况
  • 虽然GBDT还没有达到足够好的效果,但是训练时间太长/速度太慢,我们需要重新调整训练


在实际数据训练时,我们往往不能动用真正的测试集进行提前停止的验证,因此我们需要从训练集中划分出一小部分数据,专用于验证是否应该提前停止。那我们如何找到这个验证集损失不再下降、准确率不再上升的“某一时间点”呢?此时,我们可以规定一个阈值,例如,当连续n_iter_no_change次迭代中,验证集上损失函数的减小值都低于阈值tol,或者验证集的分数提升值都低于阈值tol的时候,我们就令迭代停止。此时,即便我们规定的n_estimators或者max_iter中的数量还没有被用完,我们也可以认为算法已经非常接近“收敛”而将训练停下。这种机制就是提前停止机制Early Stopping。这种机制中,需要设置阈值tol,用于不断检验损失函数下降量的验证集,以及损失函数连续停止下降的迭代轮数n_iter_no_change。在GBDT当中,这个流程刚好由以下三个参数控制:


  • validation_fraction:从训练集中提取出、用于提前停止的验证数据占比,值域为[0,1]。
  • n_iter_no_change:当验证集上的损失函数值连续n_iter_no_change次没有下降或下降量不达阈值时,则触发提前停止。平时则设置为None,表示不进行提前停止。
  • tol:损失函数下降的阈值,默认值为1e-4,也可调整为其他浮点数来观察提前停止的情况。


相关文章
|
5天前
|
算法 搜索推荐 开发者
别再让复杂度拖你后腿!Python 算法设计与分析实战,教你如何精准评估与优化!
在 Python 编程中,算法的性能至关重要。本文将带您深入了解算法复杂度的概念,包括时间复杂度和空间复杂度。通过具体的例子,如冒泡排序算法 (`O(n^2)` 时间复杂度,`O(1)` 空间复杂度),我们将展示如何评估算法的性能。同时,我们还会介绍如何优化算法,例如使用 Python 的内置函数 `max` 来提高查找最大值的效率,或利用哈希表将查找时间从 `O(n)` 降至 `O(1)`。此外,还将介绍使用 `timeit` 模块等工具来评估算法性能的方法。通过不断实践,您将能更高效地优化 Python 程序。
20 4
|
14天前
|
算法
基于极大似然算法的系统参数辨识matlab仿真
本程序基于极大似然算法实现系统参数辨识,对参数a1、b1、a2、b2进行估计,并计算估计误差及收敛曲线,对比不同信噪比下的误差表现。在MATLAB2022a版本中运行,展示了参数估计值及其误差曲线。极大似然估计方法通过最大化观测数据的似然函数来估计未知参数,适用于多种系统模型。
|
2月前
|
算法 搜索推荐 开发者
别再让复杂度拖你后腿!Python 算法设计与分析实战,教你如何精准评估与优化!
【7月更文挑战第23天】在Python编程中,掌握算法复杂度—时间与空间消耗,是提升程序效能的关键。算法如冒泡排序($O(n^2)$时间/$O(1)$空间),或使用Python内置函数找最大值($O(n)$时间),需精确诊断与优化。数据结构如哈希表可将查找从$O(n)$降至$O(1)$。运用`timeit`模块评估性能,深入理解数据结构和算法,使Python代码更高效。持续实践与学习,精通复杂度管理。
53 9
|
1月前
|
机器学习/深度学习 算法 搜索推荐
支付宝商业化广告算法问题之在DNN模型中,特征的重要性如何评估
支付宝商业化广告算法问题之在DNN模型中,特征的重要性如何评估
|
1月前
|
算法 搜索推荐
支付宝商业化广告算法问题之基于pretrain—>finetune范式的知识迁移中,finetune阶段全参数训练与部分参数训练的效果如何比较
支付宝商业化广告算法问题之基于pretrain—>finetune范式的知识迁移中,finetune阶段全参数训练与部分参数训练的效果如何比较
|
1月前
|
算法
基于EM期望最大化算法的GMM模型参数估计matlab仿真
此程序在MATLAB 2022a中实现了基于EM算法的GMM参数估计,用于分析由多个高斯分布组成的混合数据。程序通过迭代优化各高斯组件的权重、均值与协方差,直至收敛,并输出迭代过程的收敛曲线及最终参数估计结果。GMM假设数据由K个高斯分布混合而成,EM算法通过E步计算样本归属概率,M步更新参数,循环迭代直至收敛。
|
2月前
|
算法 数据安全/隐私保护
基于GA遗传优化算法的Okumura-Hata信道参数估计算法matlab仿真
在MATLAB 2022a中应用遗传算法进行无线通信优化,无水印仿真展示了算法性能。遗传算法源于Holland的理论,用于全局优化,常见于参数估计,如Okumura-Hata模型的传播损耗参数。该模型适用于150 MHz至1500 MHz的频段。算法流程包括选择、交叉、变异等步骤。MATLAB代码执行迭代,计算目标值,更新种群,并计算均方根误差(RMSE)以评估拟合质量。最终结果比较了优化前后的RMSE并显示了SNR估计值。
49 7
|
2月前
|
机器学习/深度学习 数据采集 算法
Python实现GBDT(梯度提升树)分类模型(GradientBoostingClassifier算法)并应用网格搜索算法寻找最优参数项目实战
Python实现GBDT(梯度提升树)分类模型(GradientBoostingClassifier算法)并应用网格搜索算法寻找最优参数项目实战
108 3
|
2月前
|
机器学习/深度学习 数据采集 算法
Python实现贝叶斯岭回归模型(BayesianRidge算法)并使用K折交叉验证进行模型评估项目实战
Python实现贝叶斯岭回归模型(BayesianRidge算法)并使用K折交叉验证进行模型评估项目实战
|
2月前
|
机器学习/深度学习 数据采集 监控
算法金 | DL 骚操作扫盲,神经网络设计与选择、参数初始化与优化、学习率调整与正则化、Loss Function、Bad Gradient
**神经网络与AI学习概览** - 探讨神经网络设计,包括MLP、RNN、CNN,激活函数如ReLU,以及隐藏层设计,强调网络结构与任务匹配。 - 参数初始化与优化涉及Xavier/He初始化,权重和偏置初始化,优化算法如SGD、Adam,针对不同场景选择。 - 学习率调整与正则化,如动态学习率、L1/L2正则化、早停法和Dropout,以改善训练和泛化。
30 0
算法金 | DL 骚操作扫盲,神经网络设计与选择、参数初始化与优化、学习率调整与正则化、Loss Function、Bad Gradient