暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Xgboost模型调参实验——Kaggle项目GiveMeSomeCredit实战

数据风控学习笔记 2022-02-18
1909
Xgboost模型调参实验

Kaggle项目GiveMeSomeCredit实战

逮噶猴,在上一次实战(详见上篇推送:Xgboost简单建模)中,我们初步得到了一个Xgboost模型,和一个还不错的AUC结果。可以看到,在建立模型的过程中Xgboost为我们提供了很多可以调试的入参项,那么问题来了,如何通过不同的入参取值使模型达到更好的预测效果呢?


在实际工作中,我们发现虽然部分参数在入参时存在所谓的“经验值”,但对于不同量级、不同特征,还有不同样本浓度的数据,如果想训练出效果更优的模型,往往需要通过对参数值进行反复调试,以观测不同入参取值对模型效果的影响。今天,我们就来进行一次Xgboost模型调参实验,详细瞧瞧参数调优的力量。

数据源:give me some credit数据集

数据源介绍:

来源于kaggle官网,主要为个人在银行的基本信息及信贷信息。

数据源地址:https://www.kaggle.com/c/GiveMeSomeCredit/data

建模目标:通过某客户在过去的个人信息及信贷信息信贷信息预测该客户在未来两年经理财务困境的概率,为银行的授信决策提供依据。

评价标准:AUC

关注重点:Xgboost模型调参效果

01

代码回顾

    # 以下代码为前文代码回顾,本次实验将以此为基础进行
    # 详细代码注释见《Xgboost简单建模——Kaggle项目GiveMeSomeCredit实战》


    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    import seaborn as sns
    from sklearn.model_selection import train_test_split
    from sklearn.model_selection import KFold, cross_validate
    from sklearn.preprocessing import OneHotEncoder
    import imblearn
    import xgboost as xgb
    from sklearn.metrics import roc_curve
    from sklearn.metrics import auc,roc_auc_score
    from sklearn.metrics import accuracy_score,confusion_matrix,f1_score
    from sklearn.model_selection import cross_val_score
    import toad
    from toad.plot import  bin_plot,badrate_plot
    pd.set_option('precision',3)
    pd.set_option('display.float_format',lambda x:'{:.4f}'.format(x))
    sns.set(style='whitegrid',font='Simhei')
    import os
    os.chdir(r'C:\Users\28779\Desktop\GiveMeSomeCredit\GiveMeSomeCredit')
    from IPython.core.interactiveshell import InteractiveShell
    InteractiveShell.ast_node_interactivity = 'all'
    import warnings
    warnings.filterwarnings('ignore')


    data = pd.read_csv('cs-training.csv')
    data.drop(columns='Unnamed: 0',inplace=True)
    column = ['target', 'RevUtilOfUnsecLines', 'age',
          '30-59DPD', 'DebtRatio', 'MonthlyIncome',
          'NumOfOpCreAndLoans', 'NumOf90DPD',
          'NumReaEstLoansOrLines', '60-89DPD',
          'NumberOfDependents']
    data.columns = column
      fea = ['RevUtilOfUnsecLines', 'age',
            '30-59DPD', 'DebtRatio', 'MonthlyIncome',
            'NumOfOpCreAndLoans', 'NumOf90DPD',
            'NumReaEstLoansOrLines', '60-89DPD',
            'NumberOfDependents']
      label = 'target'
      ex_lis = []


      data.target.value_counts()
      print('坏样本浓度为{:.4f}%'.format(100*data.target.mean()))
      data.duplicated().sum()


      missing_num = data.isna().sum()
      missing_rate = data.isnull().sum()/(data.isna().count())
      df_missing = pd.DataFrame({'num':missing_num,'rate':missing_rate})
      df_missing.rate = df_missing.rate.apply(lambda x :'{:.4f}%'.format(100*x))
      df_missing


      X_train,X_test,y_train,y_test = train_test_split(  
         data[fea],data[label],test_size=0.3,random_state=42)
      data_training = pd.concat([X_train,y_train],axis=1)
      data_test = pd.concat([X_test,y_test],axis=1


      02

      评估函数

        def model_evaluate(y_true,y_pre):
           '''
           input:
               y_true,series,样本标签,0或1
               y_pre,series,样本预测值,范围不限
           output:
               ks,auc,float,模型ks,auc指标值
               ROC图
           '''
             
           fpr,tpr,thresholds=roc_curve(y_true,y_pre,pos_label=None,sample_weight=None,drop_intermediate=True)
           ks_cal = abs(fpr-tpr)
           ks = max(ks_cal)
           print('ks:',ks)


           auc = roc_auc_score(y_true,y_pre)
           print('auc:',auc)


           # plot
           plt.figure()
           plt.plot([0,1],[0,1],lw=2,linestyle='--')
           plt.plot(fpr,tpr,label='ROC Curve')
           plt.title('ROC Curve')
           plt.xlabel('False Positive Rate')
           plt.ylabel('True Positive Rate')
           plt.legend()
           plt.show()
           
           return ks,auc

        03

        初始模型

        以下为模型初始参数设定,我们将在此基础上进行参数调优:
          # 参数设定
          model_xgb = xgb.XGBClassifier(
          n_estimators= 200,#评估器数量,也就是生成数的数量
          max_depth= 12,#树的最大深度
          subsample= 0.8,#训练时的采样比例
          eta=0.01,#学习率,控制每次学习的权重缩减
          gamma=10,#叶子节点分裂时的损失减少量下限
          scale_pos_weight=1,#样本权重,通常用于处理样本不均衡的情况
          reg_alpha= 0,#L1正则化项的系数,用于减轻过拟合
          reg_lambda= 1,#L2正则化项的系数,用于减轻过拟合
          min_child_weight= 1,#最小叶子节点样本权重和,用于控制每个节点上的样本数量
          objective='binary:logistic',#训练目标,影响损失函数及输出结果
          seed= 42,#随机数种子
          verbosity=1,#训练日志打印等级
          nthread= -1,#并行线程数
          eval_metric= 'auc'#评估指标
          )
          以下为初始模型的表现,左侧为训练集的表现,右侧为测试集表现,我们将以此作为benchmark:
            # 模型训练
            model_xgb.fit(X_train,y_train)
            # 模型预测
            y_pre_train_xgb = model_xgb.predict_proba(X_train)[:,1]
            y_pre_test_xgb = model_xgb.predict_proba(X_test)[:,1]
            # 模型评估
            print('-----------------------train score----------------------')
            model_evaluate(y_train,y_pre_train_xgb)
            print('-----------------------test score-----------------------')
            model_evaluate(y_test,y_pre_test_xgb)


            04

            n_estimators调参实验

            Xgboost与GBDT和LightGBM共属于集成算法中的Boosting算法,背后的原理可以简单理解为,把许多不同的评估器,也就是不同的树(可以是分类树,也可以是回归树)串联起来,通过不断拟合预测值与真实值之间的残差,使预测值逐步接近真实值。因此树的棵树越多,拟合程度也就越高,同时过拟合的风险也可能越大。n_estimators这个参数在这里代表的就是树的棵树。

            我们尝试为n_estimators取不同的值,比较不同值下训练集和测试集的AUC表现,并将结果绘制成学习曲线,以便更直观地感受这一参数对于模型的影响。

              # n_estimators调参


              # 指定参数的不同取值 
              n_estimators_list = [100,200,300,400,500,600,700,800,900,1000]  
              # 建立列表,储存不同参数取值下训练集和测试集的auc表现
              train_auc_list=[]
              test_auc_list=[]
              # 通过for循环,根据参数的不同取值分别生成模型、训练模型并获得评估结果
              for v in n_estimators_list:
                 # 生成模型                                      
                 model_xgb = xgb.XGBClassifier(
                             n_estimators= v,#评估器数量,也就是生成数的数量
                             max_depth= 12,#树的最大深度            
                             subsample= 0.4,#训练时的采样比例
                             eta=0.01,#学习率,控制每次学习的权重缩减
                             gamma=8,#叶子节点分裂时的损失减少量下限
                             reg_alpha= 0,#L1正则化项的系数,用于减轻过拟合
                             reg_lambda= 1,#L2正则化项的系数,用于减轻过拟合
                             min_child_weight= 1,#最小叶子节点样本权重和,用于控制每个节点上的样本数量  
                             scale_pos_weight=1,#样本权重,通常用于处理样本不均衡的情况
                             objective='binary:logistic',#训练目标,影响损失函数及输出结果              
                             seed= 42,#随机数种子
                             verbosity=1,#训练日志打印等级
                             nthread= -1,#并行线程数
                             eval_metric= 'auc'#评估指标
                 )
                  # 训练模型  
                 model_xgb.fit(X_train,y_train)
                  # 获取预测结果   
                 y_pre_train_xgb = model_xgb.predict_proba(X_train)[:,1]
                 y_pre_test_xgb = model_xgb.predict_proba(X_test)[:,1]  
                  # 计算auc值   
                 y_pre_train_auc = roc_auc_score(y_train,y_pre_train_xgb)
                 y_pre_test_auc = roc_auc_score(y_test,y_pre_test_xgb)
                  # 打印auc值
                  print('train:',y_pre_train_auc,'test:',y_pre_test_auc)
                 # 存储auc结果
                 train_auc_list.append(y_pre_train_auc)
                 test_auc_list.append(y_pre_test_auc)
              # 根据所有参数取值及AUC值绘制学习曲线    
              plt.figure()
              plt.plot(n_estimators_list,train_auc_list,marker='o',label='train_auc')
              plt.plot(n_estimators_list,test_auc_list,marker='o',label='test_score')
              plt.legend()
              plt.xlabel('n_estimators')
              plt.ylabel('auc_score')
              plt.title('n_estimators调参效果图')
              plt.show()


                # 查看不同参数取值下的AUC得分
                test_auc_list
                [0.8517023493127274,
                0.8535354848601977,
                0.8582802692230289,
                0.8610660671332603,
                0.862898120581762,
                0.8640868043022017,
                0.8648704116607943,
                0.8653116005801008,
                0.8655372401764581,
                0.8657046181268747]


                从上图的结果中,我们可以看出,当n_estimators<=600时,模型在训练集和测试集上的效果都有较为明显的提升,而当n_estimators>600时,训练集表现仍在提升,但测试集表现提升放缓,n_estimators>800时,测试集表现就几乎没有提升了。

                考虑n_estimators的增加会影响运行时长,这里我们暂时选定n_estimators=800,此时测试集AUC为0.8653116005801008。

                05

                max_depth调参实

                max_depth代表xgboost算法中每个评估器,也就是每颗树的最大深度。树的深度越深,学习的信息也就越多,对训练数据拟合的更充分,模型也越复杂,也更有可能带来过拟合的风险。

                我们尝试为max_depth取不同的值,比较不同值下训练集和测试集的AUC表现,并将结果绘制成学习曲线。

                  # max_depth调参


                  # 指定参数的不同取值
                  max_depth_list = [4,8,12,16,20]    
                  # 建立列表,储存不同参数取值下训练集和测试集的auc表现
                  train_auc_list=[]
                  test_auc_list=[]
                  # 通过for循环,根据参数的不同取值分别生成模型、训练模型并获得评估结果
                  for v in max_depth_list:
                     # 生成模型                                      
                     model_xgb = xgb.XGBClassifier(
                                 n_estimators= 800,#评估器数量,也就是生成数的数量
                                  max_depth= v,#树的最大深度             
                                 subsample= 0.4,#训练时的采样比例
                                 eta=0.01,#学习率,控制每次学习的权重缩减
                                 gamma=8,#叶子节点分裂时的损失减少量下限
                                 reg_alpha= 0,#L1正则化项的系数,用于减轻过拟合
                                 reg_lambda= 1,#L2正则化项的系数,用于减轻过拟合
                                 min_child_weight= 1,#最小叶子节点样本权重和,用于控制每个节点上的样本数量  
                                 scale_pos_weight=1,#样本权重,通常用于处理样本不均衡的情况
                                 objective='binary:logistic',#训练目标,影响损失函数及输出结果              
                                 seed= 42,#随机数种子
                                 verbosity=1,#训练日志打印等级
                                 nthread= -1,#并行线程数
                                 eval_metric= 'auc'#评估指标
                     )
                     # 训练模型  
                     model_xgb.fit(X_train,y_train)
                     # 获取预测结果  
                     y_pre_train_xgb = model_xgb.predict_proba(X_train)[:,1]
                     y_pre_test_xgb = model_xgb.predict_proba(X_test)[:,1]  
                     # 计算auc值  
                     y_pre_train_auc = roc_auc_score(y_train,y_pre_train_xgb)
                     y_pre_test_auc = roc_auc_score(y_test,y_pre_test_xgb)
                     # 打印auc值
                     print('train:',y_pre_train_auc,'test:',y_pre_test_auc)
                     # 存储auc结果
                     train_auc_list.append(y_pre_train_auc)
                     test_auc_list.append(y_pre_test_auc)
                  # 根据所有参数取值及AUC值绘制学习曲线    
                  plt.figure()
                  plt.plot(max_depth_list,train_auc_list,marker='o',label='train_auc')
                  plt.plot(max_depth_list,test_auc_list,marker='o',label='test_score')
                  plt.legend()
                  plt.xlabel('max_depth')
                  plt.ylabel('auc_score')
                  plt.title('max_depth调参效果图')
                  plt.show()

                    test_auc_list
                    [0.8649096906554565,
                    0.8657547500551032,
                    0.8660379365530636,
                    0.8661812727400502,
                    0.8662658801018371,
                    0.8662136239055228,
                    0.8663374823110759]


                    从上图的结果中,我们可以看出,随着max_depth的逐步增加,模型在训练集上的效果有明显提升,当max_depth<=10时,测试集表现有所提升,max_depth>10时,测试集的表现不再有明显提升,而是在max_depth=12时达到了一个小高峰,随后进入波动状态

                    随着参数的调整,训练集的表现明显提升而测试集却不为所动,甚至出现表现下降的情况,我们通称为过拟合,过拟合也代表着随着参数的调整,模型由于过于适应训练集的数据,而无法在测试集上推广的状态。这种情况下,我们通常考虑降低模型复杂度,以确保模型在测试集上可以有良好的表现。

                    实时上,在实际应用中,max_depth常与n_estimators搭配进行调参,使用大量深度较低的树,与使用少量深度较高的树,可能达到一样的效果。

                    根据上面的实验结果,我们选定max_depth=12,此时测试集AUC为

                    0.8662658801018371。
                    06

                    subsample调参实

                    subsample指对于每棵树,训练时的随机采样比例,如subsample=0.8,也就代表着每次生成一棵新的树时,我们随机抽取训练集中80%的样本对这棵树进行训练。降低subsample取值,可以降低过拟合风险,但如果subsample取值过低,也可能会造成模型学习不足的情况。

                      # subsample调参


                      # 指定参数的不同取值
                      subsample_list = [0.3,0.35,0.4,0.45,0.5,0.6,0.7,0.8]    
                      # 建立列表,储存不同参数取值下训练集和测试集的auc表现
                      train_auc_list=[]
                      test_auc_list=[]
                      # 通过for循环,根据参数的不同取值分别生成模型、训练模型并获得评估结果
                      for v in subsample_list:
                         # 生成模型                                      
                         model_xgb = xgb.XGBClassifier(
                                     n_estimators= 800,#评估器数量,也就是生成数的数量
                                     max_depth= 12,#树的最大深度            
                                     subsample= v,#训练时的采样比例
                                     eta=0.01,#学习率,控制每次学习的权重缩减
                                     gamma=8,#叶子节点分裂时的损失减少量下限
                                     reg_alpha= 0,#L1正则化项的系数,用于减轻过拟合
                                     reg_lambda= 1,#L2正则化项的系数,用于减轻过拟合
                                     min_child_weight= 1,#最小叶子节点样本权重和,用于控制每个节点上的样本数量  
                                     scale_pos_weight=1,#样本权重,通常用于处理样本不均衡的情况
                                     objective='binary:logistic',#训练目标,影响损失函数及输出结果              
                                     seed= 42,#随机数种子
                                     verbosity=1,#训练日志打印等级
                                     nthread= -1,#并行线程数
                                     eval_metric= 'auc'#评估指标
                         )
                         # 训练模型  
                         model_xgb.fit(X_train,y_train)
                         # 获取预测结果  
                         y_pre_train_xgb = model_xgb.predict_proba(X_train)[:,1]
                         y_pre_test_xgb = model_xgb.predict_proba(X_test)[:,1]  
                         # 计算auc值  
                         y_pre_train_auc = roc_auc_score(y_train,y_pre_train_xgb)
                         y_pre_test_auc = roc_auc_score(y_test,y_pre_test_xgb)
                         # 打印auc值
                         print('train:',y_pre_train_auc,'test:',y_pre_test_auc)
                         # 存储auc结果
                         train_auc_list.append(y_pre_train_auc)
                         test_auc_list.append(y_pre_test_auc)
                      # 根据所有参数取值及AUC值绘制学习曲线    
                      plt.figure()
                      plt.plot(subsample_list,train_auc_list,marker='o',label='train_auc')
                      plt.plot(subsample_list,test_auc_list,marker='o',label='test_score')
                      plt.legend()
                      plt.xlabel('subsample')
                      plt.ylabel('auc_score')
                      plt.title('subsample调参效果图')
                      plt.show()

                        test_auc_list
                        [0.8666708007372648,
                        0.866743964203687,
                        0.8667571849774316,
                        0.8666601314810142,
                        0.8663202046644455,
                        0.8664508032288875,
                        0.8662452483477028,
                        0.8661812727400502]


                        从上面的图和数据中可以看出,随着subsample的上升,测试集AUC值呈现先上升后下降的趋势,最高值出现在subsample=0.4时,AUC达到

                        0.8667571849774316。
                        通常情况下,subsample的取值在[0.5,1]较多,主要原因是避免抽取样本不足导致欠拟合,但在本例中,n_estimators取值较高,树的棵树较多,同时0.4的取值偏离0.5不多,因此subsample取为0.4。
                        除了可以用于随机抽取样本的subsample外,Xgboost中还设置了两个参数colsample_bytreecolsample_bylevel,用于随机抽取特征。在本例中,由于特征本来就不多,我们就不再使用这两个参数,有兴趣的小伙伴也可以寻找一些特征量较大的数据集,尝试看下这两个参数的效果。
                        07

                        eta调参实验

                        eta在这里与learning_rate相同,代表着学习速率。我们了解,Xgboost是一种boosting集成算法,可以通过大量的树评估器的串行不断缩小预测值与真实值之间的残差,以达到较好的预测效果。损失函数就是用于度量残差的函数,在求解损失函数最小化的过程中,eta控制着不断迭代的速度,当eta越大时,损失函数能够越快地收敛,越快地接近极小值,但同时也容易错过最佳取值;eta越小时,损失函数收敛速度放慢,需要更多次数的迭代才能靠近极小值,但也有更大的机会接近最佳取值。

                          # eta调参


                          # 指定参数的不同取值
                          eta_list = [0.005,0.01,0.02,0.03,0.05,0.1]  
                          # 建立列表,储存不同参数取值下训练集和测试集的auc表现
                          train_auc_list=[]
                          test_auc_list=[]
                          # 通过for循环,根据参数的不同取值分别生成模型、训练模型并获得评估结果
                          for v in eta_list:
                             # 生成模型                                      
                             model_xgb = xgb.XGBClassifier(
                                         n_estimators= 800,#评估器数量,也就是生成数的数量
                                         max_depth= 12,#树的最大深度            
                                         subsample= 0.4,#训练时的采样比例
                                         eta=v,#学习率,控制每次学习的权重缩减
                                         gamma=8,#叶子节点分裂时的损失减少量下限
                                         reg_alpha= 0,#L1正则化项的系数,用于减轻过拟合
                                         reg_lambda= 1,#L2正则化项的系数,用于减轻过拟合
                                         min_child_weight= 1,#最小叶子节点样本权重和,用于控制每个节点上的样本数量  
                                         scale_pos_weight=1,#样本权重,通常用于处理样本不均衡的情况
                                         objective='binary:logistic',#训练目标,影响损失函数及输出结果              
                                         seed= 42,#随机数种子
                                         verbosity=1,#训练日志打印等级
                                         nthread= -1,#并行线程数
                                         eval_metric= 'auc'#评估指标
                             )
                             # 训练模型  
                             model_xgb.fit(X_train,y_train)
                             # 获取预测结果  
                             y_pre_train_xgb = model_xgb.predict_proba(X_train)[:,1]
                             y_pre_test_xgb = model_xgb.predict_proba(X_test)[:,1]  
                             # 计算auc值  
                             y_pre_train_auc = roc_auc_score(y_train,y_pre_train_xgb)
                             y_pre_test_auc = roc_auc_score(y_test,y_pre_test_xgb)
                             # 打印auc值
                             print('train:',y_pre_train_auc,'test:',y_pre_test_auc)
                             # 存储auc结果
                             train_auc_list.append(y_pre_train_auc)
                             test_auc_list.append(y_pre_test_auc)
                          # 根据所有参数取值及AUC值绘制学习曲线    
                          plt.figure()
                          plt.plot(eta_list,train_auc_list,marker='o',label='train_auc')
                          plt.plot(eta_list,test_auc_list,marker='o',label='test_score')
                          plt.legend()
                          plt.xlabel('eta')
                          plt.ylabel('auc_score')
                          plt.title('eta调参效果图')
                          plt.show()

                            test_auc_list
                            [0.8639474650933241,
                            0.8667571849774316,
                            0.8662389514101626,
                            0.8652206403789823,
                            0.8627386926647266,
                            0.8576478282952509]

                            根据上面的实验结果,可以看出随着eta的上升,测试集的表现呈现先上升后下降的趋势,在eta=0.01时,模型取得AUC最高值0.8667571849774316。

                            08

                            gamma调参实验

                            gamma代表着叶子节点分裂时损失减小量的下限,也就是说,只有当叶子节点分裂后,损失的减小值>=gamma值时,叶子节点才会继续分裂,否则,叶子节点将不再分裂,树评估器也将停止生长。

                            gamma与n_estimators和max_depth一样,都是调节模型拟合程度的重要参数。如果gamma值设定过大,则叶子节点可能过早地停止分裂,造成学习不足,反之,如果gamma值设定过小,则叶子节点会分裂过盛,可能产生过拟合现象。

                              # gamma调参


                              # 指定参数的不同取值
                              gamma_list = [5,7,8,9,10,11,13,15]    
                              # 建立列表,储存不同参数取值下训练集和测试集的auc表现
                              train_auc_list=[]
                              test_auc_list=[]
                              # 通过for循环,根据参数的不同取值分别生成模型、训练模型并获得评估结果
                              for v in gamma_list:
                                 # 生成模型                                      
                                 model_xgb = xgb.XGBClassifier(
                                             n_estimators= 800,#评估器数量,也就是生成数的数量
                                             max_depth= 12,#树的最大深度            
                                             subsample= 0.4,#训练时的采样比例
                                             eta=0.01,#学习率,控制每次学习的权重缩减
                                              gamma=v,#叶子节点分裂时的损失减少量下限
                                             reg_alpha= 0,#L1正则化项的系数,用于减轻过拟合
                                             reg_lambda= 1,#L2正则化项的系数,用于减轻过拟合
                                             min_child_weight= 1,#最小叶子节点样本权重和,用于控制每个节点上的样本数量  
                                              scale_pos_weight= 1,#样本权重,通常用于处理样本不均衡的情况
                                             objective='binary:logistic',#训练目标,影响损失函数及输出结果              
                                             seed= 42,#随机数种子
                                             verbosity=1,#训练日志打印等级
                                             nthread= -1,#并行线程数
                                             eval_metric= 'auc'#评估指标
                                 )
                                 # 训练模型  
                                 model_xgb.fit(X_train,y_train)
                                 # 获取预测结果  
                                 y_pre_train_xgb = model_xgb.predict_proba(X_train)[:,1]
                                 y_pre_test_xgb = model_xgb.predict_proba(X_test)[:,1]  
                                 # 计算auc值  
                                 y_pre_train_auc = roc_auc_score(y_train,y_pre_train_xgb)
                                 y_pre_test_auc = roc_auc_score(y_test,y_pre_test_xgb)
                                 # 打印auc值
                                 print('train:',y_pre_train_auc,'test:',y_pre_test_auc)
                                 # 存储auc结果
                                 train_auc_list.append(y_pre_train_auc)
                                 test_auc_list.append(y_pre_test_auc)
                              # 根据所有参数取值及AUC值绘制学习曲线    
                              plt.figure()
                              plt.plot(gamma_list,train_auc_list,marker='o',label='train_auc')
                              plt.plot(gamma_list,test_auc_list,marker='o',label='test_score')
                              plt.legend()
                              plt.xlabel('gamma')
                              plt.ylabel('auc_score')
                              plt.title('gamma调参效果图')
                              plt.show()

                                test_auc_list
                                [0.8655651231915771,
                                0.8665466308788718,
                                0.8669014475369671,
                                0.866844068340739,
                                0.8667571849774316,
                                0.8668555960887913,
                                0.8662544282205021,
                                0.8654155619407824]


                                从上面的实验结果来看,随着gamma取值的增加,训练集的表现呈现先上升再下降的趋势,在gamma=8时,AUC取得最高值0.8669014475369671,随后由于学习不足,出现欠拟合,训练集和测试集表现同步下降。

                                09

                                min_child_weight

                                调参实

                                min_child_weight通常译为最小叶子节点样本权重和,指的是叶子节点上所有样本的损失函数(不考虑正则项)的二阶导数之和的最小值,主要用于控制叶子节点中的样本数。min_child_weight越大,每个叶子节点中样本数量的最小值就越大,每个叶子节点中的样本就越多,模型就越简单。因此,min_child_weight这一参数也可用于防止过拟合。

                                  # min_child_weight调参


                                  # 指定参数的不同取值
                                  min_child_weight_list = [0.95,1,1.05,1.1]    
                                  # 建立列表,储存不同参数取值下训练集和测试集的auc表现
                                  train_auc_list=[]
                                  test_auc_list=[]
                                  # 通过for循环,根据参数的不同取值分别生成模型、训练模型并获得评估结果
                                  for v in min_child_weight_list:
                                     # 生成模型                                      
                                     model_xgb = xgb.XGBClassifier(
                                                 n_estimators= 800,#评估器数量,也就是生成数的数量
                                                 max_depth= 12,#树的最大深度            
                                                 subsample= 0.4,#训练时的采样比例
                                                 eta=0.01,#学习率,控制每次学习的权重缩减
                                                 gamma=8,#叶子节点分裂时的损失减少量下限
                                                 scale_pos_weight=1,#样本权重,通常用于处理样本不均衡的情况
                                                 reg_alpha= 0,#L1正则化项的系数,用于减轻过拟合
                                                 reg_lambda= 1,#L2正则化项的系数,用于减轻过拟合
                                                 min_child_weight= v,#最小叶子节点样本权重和,用于控制每个节点上的样本数量  
                                                 objective='binary:logistic',#训练目标,影响损失函数及输出结果              
                                                 seed= 42,#随机数种子
                                                 verbosity=1,#训练日志打印等级
                                                 nthread= -1,#并行线程数
                                                 eval_metric= 'auc'#评估指标
                                     )
                                     # 训练模型  
                                     model_xgb.fit(X_train,y_train)
                                     # 获取预测结果  
                                     y_pre_train_xgb = model_xgb.predict_proba(X_train)[:,1]
                                     y_pre_test_xgb = model_xgb.predict_proba(X_test)[:,1]  
                                     # 计算auc值  
                                     y_pre_train_auc = roc_auc_score(y_train,y_pre_train_xgb)
                                     y_pre_test_auc = roc_auc_score(y_test,y_pre_test_xgb)
                                     # 打印auc值
                                     print('train:',y_pre_train_auc,'test:',y_pre_test_auc)
                                     # 存储auc结果
                                     train_auc_list.append(y_pre_train_auc)
                                     test_auc_list.append(y_pre_test_auc)
                                  # 根据所有参数取值及AUC值绘制学习曲线    
                                  plt.figure()
                                  plt.plot(min_child_weight_list,train_auc_list,marker='o',label='train_auc')
                                  plt.plot(min_child_weight_list,test_auc_list,marker='o',label='test_score')
                                  plt.legend()
                                  plt.xlabel('min_child_weight')
                                  plt.ylabel('auc_score')
                                  plt.title('min_child_weight调参效果图')
                                  plt.show()

                                    test_auc_list
                                    [0.8670096614268055,
                                     0.8669014475369671,
                                     0.8667516706649758,
                                     0.866809057847174]


                                    可以看出,经过前面几轮的精调,再去调整min_child_weight的取值时,测试集AUC的变化已经不太显著了。我们此处选取min_child_weight=0.95,此时测试集的AUC表现达到0.8670096614268055。
                                    10

                                    reg_alpha/reg_lambda

                                    简要介绍

                                    reg_alpha与reg_lambda分别为L1正则化项的系数和L2正则化项的系数,都是用于降低模型整体复杂度的的正则项,可以帮助我们更好地避免过拟合。Xgboost由大量的树组成,正则项就可以影响这些树评估器中部分叶子节点的权重,试想,如果一个叶子节点的权重接近于0,这个叶子节点就约等于并没有参与学习,这棵树的复杂度就会降低,模型的复杂度也随之降低了,过拟合的风险也就随之减小了。

                                    在实际操作中,我们很少会通过调整这两个参数来优化模型效果。如需调整,我们可以通过GridSearchCV网格搜索的方法更准确地找到这两个参数的最佳取值,在此附上相关代码,感兴趣的小伙伴可以尝试跑跑看,这一过程可能耗时较长,大家要有耐心哦~

                                      # 导入方法
                                      from sklearn.model_selection import GridSearchCV
                                      # 设置网格搜索参数
                                      params_grid = {'reg_alpha':[1,2,3,4,5],'reg_lambda':[1,2,3,4,5]}
                                      # 设置模型其他固定参数                                
                                      model_xgb = xgb.XGBClassifier(
                                                 n_estimators= 800,#评估器数量,也就是生成数的数量
                                                 max_depth= 12,#树的最大深度            
                                                 subsample= 0.4,#训练时的采样比例
                                                 eta=0.01,#学习率,控制每次学习的权重缩减
                                                 gamma=8,#叶子节点分裂时的损失减少量下限
                                                 scale_pos_weight=1,#样本权重,通常用于处理样本不均衡的情况
                                                  min_child_weight= 0.95,#最小叶子节点样本权重和,用于控制每个节点上的样本数量  
                                                 objective='binary:logistic',#训练目标,影响损失函数及输出结果              
                                                 seed= 42,#随机数种子
                                                 verbosity=1,#训练日志打印等级
                                                 nthread= -1,#并行线程数
                                                  eval_metric= 'auc'#评估指标
                                                  )

                                        # 网格搜索实例化
                                        grid_search = GridSearchCV(model_xgb,params_grid,cv=5,scoring='roc_auc')
                                        # 执行网格搜索
                                        grid_search.fit(X_train,y_train)
                                        # 查看网格搜索得出的最优参数和最优得分
                                        grid_search.best_params_
                                        grid_search.best_score_
                                        11

                                        scale_pos_weight

                                        简要介绍

                                        scale_pos_weight主要用于样本不均衡的调节,调节这个参数的本质是增加了对少数类样本的学习。scale_pos_weight的变换可能引起样本预测概率数值的变化,但并不影响样本正负排序的变化。因此,通常情况下,如果我们以AUC为目标训练模型,可以对这一数进行调节,如果以损失函数最小化为目标训练模型,则不建议对这个参数进行调节。

                                        12

                                        更新模型

                                        经过上述一系列的优化,我们就得到了下面的新模型:

                                          # 模型参数设定
                                          model_xgb = xgb.XGBClassifier(
                                          n_estimators= 800,#评估器数量,也就是生成数的数量
                                          max_depth= 12,#树的最大深度
                                          subsample= 0.4,#训练时的采样比例
                                          eta=0.01,#学习率,控制每次学习的权重缩减
                                          gamma=8,#叶子节点分裂时的损失减少量下线
                                          scale_pos_weight=1,#样本权重,通常用于处理样本不均衡的情况
                                          reg_alpha= 0,#L1正则化项的系数,用于减轻过拟合
                                          reg_lambda= 1,#L2正则化项的系数,用于减轻过拟合
                                          min_child_weight= 0.95,#最小叶子节点样本权重和,用于控制每个节点上的样本数量
                                          objective='binary:logistic',#训练目标,影响损失函数及输出结果
                                          seed= 42,#随机数种子
                                          verbosity=1,#训练日志打印等级
                                          nthread= -1,#并行线程数
                                          eval_metric= 'auc'#评估指标
                                          )


                                          # 模型训练
                                          model_xgb.fit(X_train,y_train)
                                          # 模型预测
                                          y_pre_train_xgb = model_xgb.predict_proba(X_train)[:,1]
                                          y_pre_test_xgb = model_xgb.predict_proba(X_test)[:,1]


                                          # 模型评估
                                          print('-----------------------train score----------------------')
                                          model_evaluate(y_train,y_pre_train_xgb)
                                          print('-----------------------test score-----------------------')
                                          model_evaluate(y_test,y_pre_test_xgb)

                                          并得到了如下效果:


                                          还记得吗,咱们初始模型的表现是这样的:

                                          训练集:ks约为0.583,auc约为0.867

                                          测试集:ks约为0.570,auc约为0.858


                                          经过本次调参后,新模型的表现是这样的:

                                          训练集:ks约为0.626,auc约为0.894

                                          测试集:ks约为0.585,auc约为0.867


                                          通过本次调参实验,我们对Xgboost中的常见参数有了更深入的理解,模型在训练集和测试集也都表现出了一些提升,在以后的实际运用中,小伙伴们也可以参考上述的调参思路,持续优化自己的模型了,不过,如果想要更深入得理解每个参数代表的含义,就需要进一步对Xgboost的原理和公式推导进行学习啦~




                                          数据风控学习笔记
                                          微信公众号:datascience_notebook








                                          文章转载自数据风控学习笔记,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                                          评论