2016-02-26 35 views
5

Sto tentando di utilizzare XGBoost per modellare la frequenza di reclami dei dati generati da periodi di esposizione di lunghezza non uguale, ma non è stato possibile ottenere il modello per trattare correttamente l'esposizione. Lo farei normalmente impostando il log (esposizione) come offset - sei in grado di farlo in XGBoost?XGBoost - Distribuzione di Poisson con variazione dell'esposizione/offset

(Una domanda simile è stato postato qui: xgboost, offset exposure?)

Per illustrare il problema, il codice R sotto genera alcuni dati con i campi:

  • x1, x2 - Fattori (0 o 1)
  • esposizione - durata del periodo di politica su dati osservati
  • frequenza - numero di rivendicazione osservato - numero dei sinistri per esposizione unità
  • sinistri significare s ~ Poisson (frequenza * esposizione)

L'obiettivo è di predire la frequenza utilizzando x1 e x2 - il modello vero è: frequenza = 2 se x1 = x2 = 1, frequenza = 1 altrimenti.

L'esposizione non può essere utilizzata per prevedere la frequenza poiché non è nota all'inizio di una politica. L'unico modo in cui possiamo usarlo è dire: numero previsto di reclami = frequenza * esposizione.

il codice tenta di prevedere questo utilizzando XGBoost da:

  1. impostazione dell'esposizione come un peso nel modello a matrice
  2. registro Setting (esposizione) come offset

Sotto questi, Ho mostrato come gestirò la situazione per un albero (rpart) o 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") 

risposta

1

Almeno con la funzione glm in R, modellando count ~ x1 + x2 + offset(log(exposure)) con family=poisson(link='log') è equivalente alla modellazione I(count/exposure) ~ x1 + x2 con family=poisson(link='log') e weight=exposure. Cioè, normalizza il tuo conteggio per ottenere la frequenza e la frequenza del modello con esposizione come peso. I tuoi coefficienti stimati dovrebbero essere gli stessi in entrambi i casi quando si utilizza glm per la regressione di Poisson. Provare per credere utilizzando una connessione dati di esempio impostare

Non sono esattamente sicuro di cosa objective='count:poisson' corrisponde, ma mi aspetterei impostando la variabile di destinazione come frequenza (conteggio/esposizione) e utilizzando l'esposizione come il peso in xgboost sarebbe il strada da percorrere quando le esposizioni sono variabili.

+0

Grazie Vinh. Questa è una delle opzioni che ho provato ma non sembra funzionare come previsto in casi semplici. Credo di aver trovato la soluzione e l'ho postata qui. –

1

Ora ho trovato il modo di fare questo usando SetInfo per modificare l'attributo base_margin di essere l'offset (come predittore lineare), vale a dire:

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