2016-02-26 10 views
5

Ich versuche XGBoost zu modellieren, um die Häufigkeit von Daten aus ungleichen Belichtungszeiten zu modellieren, konnte aber das Modell nicht korrekt behandeln. Normalerweise würde ich das tun, indem ich log (Belichtung) als Offset setze - können Sie das in XGBoost machen?XGBoost - Poisson-Verteilung mit variierender Belichtung/Offset

(Eine ähnliche Frage wurde hier gepostet: xgboost, offset exposure?)

Um das Problem zu veranschaulichen, unter dem R-Code generiert einige Daten mit den Feldern:

  • x1, x2 - Faktoren (entweder 0 oder 1)
  • Exposition - Länge der Vertragslaufzeit auf den beobachteten Daten
  • Frequenz - mittlere Anzahl der pro Einheitsbelichtungs Ansprüche
  • Ansprüche - Anzahl der beobachteten Anspruch s ~ Poisson (Häufigkeit * Exposition)

Ziel ist es Frequenz vorherzusagen mit x1 und x2 - das wahre Modell ist: Frequenz = 2, wenn x1 = x2 = 1, Frequenz = 1 sonst.

Die Exposition kann nicht zur Vorhersage der Häufigkeit verwendet werden, da sie zu Beginn einer Richtlinie nicht bekannt ist. Der einzige Weg, wie wir es nutzen können, ist zu sagen: erwartete Anzahl von Ansprüchen = Häufigkeit * Exposition.

  1. Einstellen Belichtung als Gewicht in der Modellmatrix
  2. Einstellung log (Belichtung) als Offset

Unter diesen sind I: durch

Der Code versucht, diese unter Verwendung von XGBoost vorherzusagen habe gezeigt, wie ich mit der Situation für einen Baum (rpart) oder gbm umgehen würde.

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") 

Antwort

1

Zumindest bei der glm Funktion in R ist mit count ~ x1 + x2 + offset(log(exposure))family=poisson(link='log') Modellierung entspricht Modellierung I(count/exposure) ~ x1 + x2 mit family=poisson(link='log') und weight=exposure. Das heißt, normalisieren Sie Ihre Zählung durch Belichtung, um die Frequenz zu erhalten, und modellieren Sie die Frequenz mit der Belichtung als Gewicht. Ihre geschätzten Koeffizienten sollten in beiden Fällen gleich sein, wenn Sie glm für die Poisson-Regression verwenden. Probieren Sie es selbst ein Beispieldatum gesetzt

Ich bin mir nicht ganz sicher, was objective='count:poisson' entspricht, aber ich würde erwarten, dass Ihr Zielvariable als Frequenzeinstellung (Anzahl/Exposition) und unter Verwendung von Belichtung als das Gewicht in xgboost wäre die Weg zu gehen, wenn die Expositionen variieren.

+0

Dank Vinh. Dies ist eine der Optionen, die ich ausprobiert habe, aber in einfachen Fällen nicht wie erwartet funktioniert. Ich glaube, ich habe jetzt die Lösung gefunden und habe sie hier gepostet. –

1

Ich habe jetzt herausgearbeitet, wie diese setinfo mit tun, um das base_margin Attribut zu ändern, der Offset (als lineare Prädiktor) zu sein, das heißt:

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