2017-01-15 2 views
4

Je voudrais passer valider un modèle GAM en utilisant caret. Mon modèle GAM a une variable de résultat binaire, un lissage isotrope des paires de coordonnées de latitude et de longitude, puis des prédicteurs linéaires. syntaxe typique lors de l'utilisation mgcv est:package Caret - prédicteurs croisée validation de GAM à la fois lisses et linéaires

gam1 <- gam(y ~ s(lat , long) + x1 + x2, family = binomial(logit)) 

Je ne suis pas tout à fait sûr comment spécifier ce modèle en utilisant la fonction de train caret. Ceci est ma syntaxe plus ou moins:

cv <- train(y ~ lat + long + x1 + x2, 
      data = data, 
      method = "gam", 
      family = "binomial", 
      trControl = trainControl(method = "LOOCV", number=1, repeats=), 
      tuneGrid = data.frame(method = "GCV.Cp", select = FALSE)) 

Le problème est que je ne veux que lat et long à lisser et x1 et x2 à traiter comme linéaire.

Merci!

+0

D'accord avec @ 李哲源 ZheyuanLi mais ne pas 'caret :: train' accepter la régression ou spline de lissage fonctions dans son argument de formule? –

+0

Je ne vois aucune difficulté à utiliser des fonctions splines ou polynomiales dans l'argument de la formule 'train' quand' method = "glm" '. –

Répondre

4

Il est très intéressant de voir quelqu'un en utilisant mgcv en dehors mgcv. Après un peu de recherche, je suis ici pour vous frustrer: utilise mgcv avec caret est une mauvaise idée, au moins avec le soutien actuel de caret.

Permettez-moi de vous poser quelques questions fondamentales, si vous utilisez caret:

  1. Comment pouvez-vous indiquer le nombre de nœuds, ainsi que la classe de base spline pour une fonction lisse?
  2. Comment pouvez-vous spécifier la fonction lisse 2D?
  3. Comment pouvez-vous indiquer spline produit tensoriel avec te ou ti?
  4. Comment pouvez-vous ajuster avec les paramètres de lissage?

Si vous voulez savoir ce que caret::train fait avec method = "gam", consultez son programme d'ajustement:

getModelInfo(model = "gam", regex = FALSE)$gam$fit 

function(x, y, wts, param, lev, last, classProbs, ...) { 
      dat <- if(is.data.frame(x)) x else as.data.frame(x) 
      modForm <- caret:::smootherFormula(x) 
      if(is.factor(y)) { 
       dat$.outcome <- ifelse(y == lev[1], 0, 1) 
       dist <- binomial() 
      } else { 
       dat$.outcome <- y 
       dist <- gaussian() 
      } 
      modelArgs <- list(formula = modForm, 
           data = dat, 
           select = param$select, 
           method = as.character(param$method)) 
      ## Intercept family if passed in 
      theDots <- list(...) 
      if(!any(names(theDots) == "family")) modelArgs$family <- dist 
      modelArgs <- c(modelArgs, theDots)     
      out <- do.call(getFromNamespace("gam", "mgcv"), modelArgs) 
      out  
      } 

Vous voyez la ligne modForm <- caret:::smootherFormula(x)? Cette ligne est la clé, tandis que les autres lignes ne sont que la construction de routine d'un appel de modèle. Donc, nous allons avoir un chèque avec quelle formule GAM caret construit:

caret:::smootherFormula 

function (data, smoother = "s", cut = 10, df = 0, span = 0.5, 
    degree = 1, y = ".outcome") 
{ 
    nzv <- nearZeroVar(data) 
    if (length(nzv) > 0) 
     data <- data[, -nzv, drop = FALSE] 
    numValues <- sort(apply(data, 2, function(x) length(unique(x)))) 
    prefix <- rep("", ncol(data)) 
    suffix <- rep("", ncol(data)) 
    prefix[numValues > cut] <- paste(smoother, "(", sep = "") 
    if (smoother == "s") { 
     suffix[numValues > cut] <- if (df == 0) 
      ")" 
     else paste(", df=", df, ")", sep = "") 
    } 
    if (smoother == "lo") { 
     suffix[numValues > cut] <- paste(", span=", span, ",degree=", 
      degree, ")", sep = "") 
    } 
    if (smoother == "rcs") { 
     suffix[numValues > cut] <- ")" 
    } 
    rhs <- paste(prefix, names(numValues), suffix, sep = "") 
    rhs <- paste(rhs, collapse = "+") 
    form <- as.formula(paste(y, rhs, sep = "~")) 
    form 
} 

En bref, il crée additif, lisse univariée. C'est la forme classique lorsque GAM a été proposé pour la première fois.

À cette fin, vous perdez une quantité importante de contrôle sur mgcv, comme indiqué précédemment.

Pour vérifier cela, permettez-moi de construire un exemple similaire à votre cas:

set.seed(0) 
dat <- gamSim(eg = 2, scale = 0.2)$data[1:3] 
dat$a <- runif(400) 
dat$b <- runif(400) 
dat$y <- with(dat, y + 0.3 * a - 0.7 * b) 

#   y   x   z   a   b 
#1 -0.30258559 0.8966972 0.1478457 0.07721866 0.3871130 
#2 -0.59518832 0.2655087 0.6588776 0.13853856 0.8718050 
#3 -0.06978648 0.3721239 0.1850700 0.04752457 0.9671970 
#4 -0.17002059 0.5728534 0.9543781 0.03391887 0.8669163 
#5 0.55452069 0.9082078 0.8978485 0.91608902 0.4377153 
#6 -0.17763650 0.2016819 0.9436971 0.84020039 0.1919378 

, notre objectif est d'adapter un modèle: y ~ s(x, z) + a + b. Les données y sont gaussiennes, mais cela n'a pas d'importance; cela n'affecte pas la façon dont caret fonctionne avec mgcv.

cv <- train(y ~ x + z + a + b, data = dat, method = "gam", family = "gaussian", 
      trControl = trainControl(method = "LOOCV", number=1, repeats=1), 
      tuneGrid = data.frame(method = "GCV.Cp", select = FALSE)) 

Vous pouvez extraire le modèle final:

fit <- cv[[11]] 

Alors, quelle est la formule à l'aide?

fit$formula 
#.outcome ~ s(x) + s(z) + s(a) + s(b) 

Voir? En plus d'être « additif, univariée », il laisse aussi tout ce qui mgcv::s à sa valeur par défaut: par défaut bs = "tp", par défaut k = 10, etc.

+0

Merci, tous les bons points. Oui si ce que je voulais est de comparer adaptatif à tp aux lisses je ne vois pas comment le faire en caret. Donc, je suppose qu'il doit y avoir un moyen de coder en dur une validation croisée, mais c'est au-delà de mes compétences. Quelqu'un peut-il pointer vers un code où je peux le faire? Merci –

+0

J'ai compris, merci. Nouveau ici :) –