XGBoost - 具有不同曝光/偏移的泊松分布

时间:2016-02-26 19:56:52

标签: r offset poisson xgboost

我正在尝试使用XGBoost来模拟从不等长曝光时间段生成的数据的声明频率,但是无法让模型正确地处理曝光。我通常会通过将log(曝光)设置为偏移量来实现此目的 - 您是否可以在XGBoost中执行此操作?

(类似的问题发布在这里:xgboost, offset exposure?

为了说明这个问题,下面的R代码使用以下字段生成一些数据:

  • x1,x2 - 因子(0或1)
  • 暴露 - 观察数据的保单期限
  • 频率 - 每单位曝光的平均索赔数
  • 声明 - 观察到的声明数量〜泊松(频率*暴露)

目标是使用x1和x2预测频率 - 真实模型是:如果x1 = x2 = 1则频率= 2,否则频率= 1。

曝光不能用于预测频率,因为政策一开始就不知道。我们可以使用它的唯一方法是:预期的索赔数量=频率*曝光。

代码尝试使用XGBoost通过以下方式预测:

  1. 将曝光设置为模型矩阵中的权重
  2. 将日志(曝光)设置为偏移量
  3. 在下面,我已经展示了如何处理树(rpart)或gbm的情况。

    set.seed(1)
    size<-10000
    d <- data.frame(
      x1 = sample(c(0,1),size,replace=T,prob=c(0.5,0.5)),
      x2 = sample(c(0,1),size,replace=T,prob=c(0.5,0.5)),
      exposure = runif(size, 1, 10)*0.3
    )
    d$frequency <- 2^(d$x1==1 & d$x2==1)
    d$claims <- rpois(size, lambda = d$frequency * d$exposure)
    
    #### Try to fit using XGBoost
    require(xgboost)
    param0 <- list(
      "objective"  = "count:poisson"
      , "eval_metric" = "logloss"
      , "eta" = 1
      , "subsample" = 1
      , "colsample_bytree" = 1
      , "min_child_weight" = 1
      , "max_depth" = 2
    )
    
    ## 1 - set weight in xgb.Matrix
    
    xgtrain = xgb.DMatrix(as.matrix(d[,c("x1","x2")]), label = d$claims, weight = d$exposure)
    xgb = xgb.train(
      nrounds = 1
      , params = param0
      , data = xgtrain
    )
    
    d$XGB_P_1 <- predict(xgb, xgtrain)
    
    ## 2 - set as offset in xgb.Matrix
    xgtrain.mf  <- model.frame(as.formula("claims~x1+x2+offset(log(exposure))"),d)
    xgtrain.m  <- model.matrix(attr(xgtrain.mf,"terms"),data = d)
    xgtrain  <- xgb.DMatrix(xgtrain.m,label = d$claims)
    
    xgb = xgb.train(
      nrounds = 1
      , params = param0
      , data = xgtrain
    )
    
    d$XGB_P_2 <- predict(model, xgtrain)
    
    #### Fit a tree
    require(rpart)
    d[,"tree_response"] <- cbind(d$exposure,d$claims)
    tree <- rpart(tree_response ~ x1 + x2,
                  data = d,
                  method = "poisson")
    
    d$Tree_F <- predict(tree, newdata = d)
    
    #### Fit a GBM
    
    gbm <- gbm(claims~x1+x2+offset(log(exposure)), 
               data = d,
               distribution = "poisson",
               n.trees = 1,
               shrinkage=1,
               interaction.depth=2,
               bag.fraction = 0.5)
    
    d$GBM_F <- predict(gbm, newdata = d, n.trees = 1, type="response")
    

2 个答案:

答案 0 :(得分:1)

至少使用R中的glm函数,使用count ~ x1 + x2 + offset(log(exposure))建模family=poisson(link='log')相当于使用I(count/exposure) ~ x1 + x2family=poisson(link='log')建模weight=exposure。也就是说,通过暴露于获得频率来标准化您的计数,并将曝光的模型频率标准化为重量。在使用glm进行泊松回归时,两种情况下的估计系数应相同。使用示例数据集

自行尝试

我不确定objective='count:poisson'对应的是什么,但我希望将目标变量设置为频率(计数/曝光)并使用曝光,因为xgboost中的权重将是当曝光变化时去。

答案 1 :(得分:1)

我现在已经研究了如何使用setinfo将base_margin属性更改为偏移量(作为线性预测器),即:

setinfo(xgtrain, "base_margin", log(d$exposure))