zoukankan      html  css  js  c++  java
  • Tuning xgboost in R:Part 1

    第一次调整Boosting算法的参数可能是一个非常艰难的任务。
    有很多参数可供选择,调整不同的参数会有不同的结果产生。
    最好的调参可能是取决于数据。
    每当我得到一个新的数据集,我都会学到一些新的东西。
    对分类和回归树(CART)有很好的理解有助于我们理解boosting


    我最喜欢的Boosting包是xgboost,它将在下面的所有示例中使用。
    在讨论数据之前,我们先谈谈一些我认为最重要的参数。
    这些参数大多用于控制模型适合数据的程度。
    我们希望能够捕捉数据的结构,但仅限于真实的结构。
    换句话说,我们不希望模型适合噪音(过拟合)

    eta: 学习(或收缩)参数。
    它控制Boosting中将使用来自新树的多少信息。
    该参数必须大于0并且被限制为1.
    如果它接近零,我们将仅使用来自每个新树的一小部分信息。
    如果我们将eta设置为1,我们将使用新树中的所有信息。
    eta的大值导致更快的收敛和更多的过度拟合问题。
    小数值可能需要许多树来聚合。colsample_bylevel:就像随机森林一样,

    有时候只需要看一些变量就可以增长树中的每个新节点。
    如果我们查看所有变量,算法需要更少的树来收敛。
    但例如,查看2/3的变量可能会导致模型更具鲁棒性以适应过度拟合。
    有一个类似的参数叫做colsample_bytree,它重新采样每个新树中的变量,
    而不是每个新节点。

    max_depth : 控制树木的最大深度。 更深的树有更多的终端节点并且适合更多的数据。 如果我们深入发展,融合也需要更少的树木。 但是,如果树要深一些,我们将使用来自第一棵树的大量信息,算法的最终树对丢失函数的重要性将会降低。 Boosting从使用许多树木的信息中受益。 因此,巨大的树木是不可取的。 较小的树木也会增长得更快,并且因为Boosting在伪剩余中生长新的树木,我们不需要为单个树木进行任何惊人的调整。

    sub_sample : 这个参数决定我们是估计一个Boosting还是一个随机Boosting。 如果我们使用1,我们会获得常规的Boosting。 0和1之间的值是随机的情况。 随机Boosting只使用一小部分数据来增长每棵树。 例如,如果我们使用0.5,每棵树将采样50%的数据增长。 随机增强是非常有用的,如果我们有异常值,因为它限制了它们对最终模型的影响,因为它们被放在几个子样本上。 而且,对于较小的实例,可能会有显着的改进,但它们更易于过度拟合。

    gamma:控制在树中增长新节点所需的损失函数的最小减少量。 此参数对损失函数的规模很敏感,它将与响应变量的规模相关联。 使用不同于0的gamma的主要结果是停止生成无用的树的算法,这些树几乎不会减少样本内误差,并且可能导致过度拟合。 这个参数以后再说。

    min_child_weigth :控制终端节点中观察值(实例)的最小数量。 此参数的最小值为1,这使得树只有一个观测值的终端节点。 如果我们使用更大的值,我们将限制可能的完美拟合。 这个参数也将留给第二部分。

    example:

    数据服从一下等式:

       这里: ,。变量数量K将被设置为10,实例数量将被设置为1000。

    实验将更改每个Boosting参数,使所有其他参数保持不变以尝试隔离其效果。 标准模型将具有以下参数:

    eta:0.1

    colsample_bylevel:2/3

    sub_sample:0.5

    我会将这些参数中的每一个更改为代码中的值。 我们将分析测试样本中的收敛性和均方根误差(RMSE)。 下面的代码将准备一切运行模型。

    library(xgboost)
    library(ggplot2)
    library(reshape2)
    library(Ecdat)
     
    set.seed(1)
    N = 1000
    k = 10
    x = matrix(rnorm(N*k),N,k)
    b = (-1)^(1:k)
    yaux=(x%*%b)^2
    e = rnorm(N)
    y=yaux+e
     
    # = select train and test indexes = #
    train=sample(1:N,800)
    test=setdiff(1:N,train)
     
    # = parameters = #
    # = eta candidates = #
    eta=c(0.05,0.1,0.2,0.5,1)
    # = colsample_bylevel candidates = #
    cs=c(1/3,2/3,1)
    # = max_depth candidates = #
    md=c(2,4,6,10)
    # = sub_sample candidates = #
    ss=c(0.25,0.5,0.75,1)
     
    # = standard model is the second value  of each vector above = #
    standard=c(2,2,3,2)
     
    # = train and test data = #
    xtrain = x[train,]
    ytrain = y[train]
    xtest = x[test,]
    ytest = y[test]
    

      

    eta:我们将开始分析eta参数。 下面的代码估计每个候选eta的Boosting模型。 首先我们得到了收敛图,这表明eta的更大值收敛得更快。 然而,图下方的列车RMSE表明,更快的收敛并不能转化为良好的样本外表现。 较小的eta值如0.05和0.1是产生较小误差的值。 我的观点是,在这种情况下,0.1给我们一个良好的样本外性能和可接受的收敛速度。 请注意,eta = 0.5和1的结果与其他结果相比非常糟糕。

    set.seed(1)
    conv_eta = matrix(NA,500,length(eta))
    pred_eta = matrix(NA,length(test), length(eta))
    colnames(conv_eta) = colnames(pred_eta) = eta
    for(i in 1:length(eta)){
      params=list(eta = eta[i], colsample_bylevel=cs[standard[2]],
                  subsample = ss[standard[4]], max_depth = md[standard[3]],
                  min_child_weigth = 1)
      xgb=xgboost(xtrain, label = ytrain, nrounds = 500, params = params)
      conv_eta[,i] = xgb$evaluation_log$train_rmse
      pred_eta[,i] = predict(xgb, xtest)
    }
    

      

    conv_eta = data.frame(iter=1:500, conv_eta)
    conv_eta = melt(conv_eta, id.vars = "iter")
    ggplot(data = conv_eta) + geom_line(aes(x = iter, y = value, color = variable))
    

      

    (RMSE_eta = sqrt(colMeans((ytest-pred_eta)^2)))
    ## 0.05 0.1 0.2 0.5 1 ## 9.964462 10.052367 10.223738 13.691344 20.929690

      

    colsample_bylevel:下一个参数控制每个新节点中测试的变量(特征)的比例。 回想一下,如果我们使用1,所有变量都经过测试。 小于1的值只测试相应的变量部分。 收敛性表明该模型对colsample_bylevel不太敏感。 具有较小值的曲线略高于具有较大值的曲线。 最准确的模型似乎是每棵树中使用25%样本的模型。 这个结果可能会随着不同类型的数据而改变。 例如,我们生成的数据使用相同的分布来创建所有响应变量,并且测试向变量赋予相似的权重,这使得采样不那么重要。

    set.seed(1)
    conv_cs = matrix(NA,500,length(cs))
    pred_cs = matrix(NA,length(test), length(cs))
    colnames(conv_cs) = colnames(pred_cs) = cs
    for(i in 1:length(cs)){
      params = list(eta = eta[standard[1]], colsample_bylevel = cs[i],
                  subsample = ss[standard[4]], max_depth = md[standard[3]],
                  min_child_weigth = 1)
      xgb=xgboost(xtrain, label = ytrain,nrounds = 500, params = params)
      conv_cs[,i] = xgb$evaluation_log$train_rmse
      pred_cs[,i] = predict(xgb, xtest)
    }
    

      

    conv_cs = data.frame(iter=1:500, conv_cs)
    conv_cs = melt(conv_cs, id.vars = "iter")
    ggplot(data = conv_cs) + geom_line(aes(x = iter, y = value, color = variable))
    

      

    (RMSE_cs = sqrt(colMeans((ytest-pred_cs)^2)))
    
    ## 0.333333333333333 0.666666666666667                 1
    ##          10.29836          10.05237          10.20938
    

      

    max_depth:第三个参数是每棵树中允许的最大深度。 当然,如果我们种植更大的树木,模型会更快地收敛(见下图)。 但是,最好的示例外性能是max_depth = 4。 请记住,更大的树木更可能导致过度贴合。 根据我的经验,不需要使用大于4到6的值,但可能有例外。

    set.seed(1)
    conv_md=matrix(NA,500,length(md))
    pred_md=matrix(NA,length(test),length(md))
    colnames(conv_md)=colnames(pred_md)=md
    for(i in 1:length(md)){
      params=list(eta=eta[standard[1]],colsample_bylevel=cs[standard[2]],
                  subsample=ss[standard[4]],max_depth=md[i],
                  min_child_weigth=1)
      xgb=xgboost(xtrain, label = ytrain,nrounds = 500,params=params)
      conv_md[,i] = xgb$evaluation_log$train_rmse
      pred_md[,i] = predict(xgb, xtest)
    }
    

      

    conv_md=data.frame(iter=1:500,conv_md)
    conv_md=melt(conv_md,id.vars = "iter")
    ggplot(data=conv_md)+geom_line(aes(x=iter,y=value,color=variable))
    

      

      

    (RMSE_md=sqrt(colMeans((ytest-pred_md)^2)))
    
    ##         2         4         6        10
    ## 12.502733  9.374257 10.134965 10.100691
    

      

     sub_sample:下一个参数决定我们是否估计Boosting或Stochastic Boosting。 较小的值会导致样本中的误差更大,但它可能会产生更强大的样本外估计。 但是,如前所述,对于具有许多特征的样本,与观察次数和数据非常嘈杂时相比,您将获得更大的改进。 这里不是这种情况。 尽管如此,与确定性案例相比有一些改进,我相信这主要是由响应变量中的异常值引起的(boxplot变量y可以看到)。

    set.seed(1)
    conv_ss=matrix(NA,500,length(ss))
    pred_ss=matrix(NA,length(test),length(ss))
    colnames(conv_ss)=colnames(pred_ss)=ss
    for(i in 1:length(ss)){
      params=list(eta=eta[standard[1]],colsample_bylevel=cs[standard[2]],
                  subsample=ss[i],max_depth=md[standard[3]],
                  min_child_weigth=1)
      xgb=xgboost(xtrain, label = ytrain,nrounds = 500,params=params)
      conv_ss[,i] = xgb$evaluation_log$train_rmse
      pred_ss[,i] = predict(xgb, xtest)
    }
    

      

    conv_ss=data.frame(iter=1:500,conv_ss)
    conv_ss=melt(conv_ss,id.vars = "iter")
    ggplot(data=conv_ss)+geom_line(aes(x=iter,y=value,color=variable))
    

      

    (RMSE_ss=sqrt(colMeans((ytest-pred_ss)^2)))
    
    ##      0.25       0.5      0.75         1
    ##  9.731273 10.052367 11.119535 11.233855
    

      

    这里的主要结论是,调整Boosting模型没有独特的规则。 最好的方法是测试几种配置。

    请继续关注,如果你喜欢这篇文章,我们会尽快讨论Boosting。

  • 相关阅读:
    面试题汇总--1
    行内元素与块级元素
    前端面试题整理---JS基础
    springmvc处理一个请求的全流程
    反射+动态代理+类加载+JVM
    json注解及序列化
    加密
    Thread setUncaughtExceptionHandler
    RunTime.getRunTime().addShutdownHook 添加钩子
    MySQL日志
  • 原文地址:https://www.cnblogs.com/yuanzhoulvpi/p/9055112.html
Copyright © 2011-2022 走看看