Un critère de sélection de la valeur optimale de avec un filet élastique ou une régression pénalisée similaire consiste à examiner un tracé de la déviance par rapport à la plage de et à sélectionner lorsque la déviance est minimisée (ou dans une erreur standard de la le minimum).
Cependant, j'ai du mal à comprendre avec quoi exactement glmnet
s'affiche plot.cv.glmnet
, car le tracé affiché ne ressemble pas du tout aux résultats du tracé de la déviance contre .
set.seed(4567)
N <- 500
P <- 100
coefs <- NULL
for(p in 1:P){
coefs[p] <- (-1)^p*100*2^(-p)
}
inv.logit <- function(x) exp(x)/(1+exp(x))
X <- matrix(rnorm(N*P), ncol=P, nrow=N)
Y <- rbinom(N, size=1, p=inv.logit(cbind(1, X)%*%c(-4, coefs)))
plot(test <- cv.glmnet(x=X, y=Y, family="binomial", nfolds=10, alpha=0.8))
plot(log(test$lambda), deviance(test$glmnet.fit))
Il semble que le deuxième tracé n'incorpore pas la pénalité nette élastique et est également incorrectement mis à l'échelle verticalement. Je fonde l'affirmation sur la base que la forme de la courbe pour des valeurs plus élevées de ressemble à celle de la sortie. Cependant, lorsque j'ai tenté de calculer la pénalité par moi-même, ma tentative semble également extrêmement inexacte.glmnet
penalized.dev.fn <- function(lambda, alpha=0.2, data, cv.model.obj){
dev <- deviance(cv.model.obj$glmnet.fit)[seq_along(cv.model.obj$lambda)[cv.model.obj$lambda==lambda]]
beta <- coef(cv.model.obj, s=lambda)[rownames(coef(cv.model.obj))!="(Intercept)"]
penalty <- lambda * ( (1-alpha)/2*(beta%*%beta) + alpha*sum(abs(beta)) )
penalized.dev <- penalty+dev
return(penalized.dev)
}
out <- sapply(test$lambda, alpha=0.2, cv.model.obj=test, FUN=penalized.dev.fn)
plot(log(test$lambda), out)
Ma question est: comment calculer manuellement la déviance signalée dans le plot.cv.glmnet
diagramme par défaut ? Quelle est sa formule et qu'ai-je fait de mal dans ma tentative de calcul?
cv.glmnet
validation croisée est multipliée par 10, non? Donc, il trace la moyenne de l'erreur standard +/- 1 de la déviance sur les données de maintien de 10%?Réponses:
Je voulais juste ajouter quelque chose, mais pour le moment je n'ai pas de réponse concise et c'est trop long pour un commentaire. Espérons que cela donne plus d'informations.
Il semble que la fonction qui nous intéresse se trouve dans la bibliothèque glmnet non compressée et s'appelle cv.lognet.R Il est difficile de tout tracer explicitement, tout comme dans le code S3 / S4, mais la fonction ci-dessus est répertoriée comme une `` fonction glmnet interne », utilisé par les auteurs et semble correspondre à la façon dont le cv.glmnet calcule la déviance binomiale.
Bien que je ne l'ai vu nulle part dans le document, du traçage du code glmnet à cv.lognet, ce que je comprends, c'est qu'il utilise quelque chose appelé la déviance binomiale plafonnée décrite ici .
predmat est une matrice des valeurs de probabilité plafonnées (E, 1-E) produites pour chaque lambda, qui sont comparées aux valeurs de complément de y et y résultant en lp. Ils sont ensuite placés sous la forme de déviance 2 * (ly-lp) et moyennés sur les plis de maintien validés de manière croisée pour obtenir cvm - l'erreur moyenne de validation croisée - et les plages de cv que vous avez tracées dans la première image.
Je pense que la fonction de déviation manuelle (2e tracé) n'est pas calculée de la même manière que celle interne (1er tracé).
la source
J'ai donc visité le site du CRAN et téléchargé ce que je pense être la source du paquet glmnet . Dans ./glmnet/R/plot.cv.glmnet.R, il semble que vous trouverez le code source que vous recherchez. C'est assez bref, donc je vais coller ici, mais il est probablement préférable de le vérifier vous-même pour vous assurer que c'est bien le code qui est en cours d'exécution.
la source
getS3method('plot', 'cv.glmnet')
sans vous soucier de télécharger le paquet source. (En interne,glmnet
vient de définir une fonction appeléeplot.cv.glmnet
mais ne l'a pas exportée. Vous pouvez toujours la voir en jetant un œil à l'intérieur de l'espace de nom avec l':::
opérateur :)glmnet:::plot.cv.glmnet
.