J'essaie d'adapter un modèle de régression linéaire multivarié avec environ 60 variables de prédicteur et 30 observations. J'utilise donc le package glmnet pour la régression régularisée, car p> n.
J'ai parcouru la documentation et d'autres questions, mais je ne peux toujours pas interpréter les résultats. Voici un exemple de code (avec 20 prédicteurs et 10 observations pour simplifier):
Je crée une matrice x avec num rangs = num observations et num cols = num prédicteurs et un vecteur y qui représente la variable de réponse
> x=matrix(rnorm(10*20),10,20)
> y=rnorm(10)
J'adapte un modèle de glmnet en laissant alpha par défaut (= 1 pour la pénalité de lasso)
> fit1=glmnet(x,y)
> print(fit1)
Je comprends que je reçois des prédictions différentes avec des valeurs décroissantes de lambda (c.-à-d. Une pénalité)
Call: glmnet(x = x, y = y)
Df %Dev Lambda
[1,] 0 0.00000 0.890700
[2,] 1 0.06159 0.850200
[3,] 1 0.11770 0.811500
[4,] 1 0.16880 0.774600
.
.
.
[96,] 10 0.99740 0.010730
[97,] 10 0.99760 0.010240
[98,] 10 0.99780 0.009775
[99,] 10 0.99800 0.009331
[100,] 10 0.99820 0.008907
Maintenant, je prédis mes valeurs bêta en choisissant, par exemple, la plus petite valeur lambda donnée à partir de glmnet
> predict(fit1,type="coef", s = 0.008907)
21 x 1 sparse Matrix of class "dgCMatrix"
1
(Intercept) -0.08872364
V1 0.23734885
V2 -0.35472137
V3 -0.08088463
V4 .
V5 .
V6 .
V7 0.31127123
V8 .
V9 .
V10 .
V11 0.10636867
V12 .
V13 -0.20328200
V14 -0.77717745
V15 .
V16 -0.25924281
V17 .
V18 .
V19 -0.57989929
V20 -0.22522859
Si au lieu de cela je choisis lambda avec
cv <- cv.glmnet(x,y)
model=glmnet(x,y,lambda=cv$lambda.min)
Toutes les variables seraient (.).
Doutes et questions:
- Je ne suis pas sûr de savoir comment choisir lambda.
- Devrais-je utiliser les variables non (.) Pour s’adapter à un autre modèle? Dans mon cas, j'aimerais garder autant de variables que possible.
- Comment connaître la valeur p, c'est-à-dire quelles variables prédisent de manière significative la réponse?
Je m'excuse pour ma faible connaissance statistique! Et merci pour toute aide.
la source
Réponses:
Voici un fait peu intuitif: vous n'êtes pas censé donner à glmnet une valeur unique de lambda. De la documentation ici :
cv.glmnet
vous aidera à choisir lambda, comme vous l'avez mentionné dans vos exemples. Les auteurs du paquet glmnet suggèrentcv$lambda.1se
au lieu decv$lambda.min
, mais en pratique, j'ai eu du succès avec ce dernier.Après avoir exécuté cv.glmnet, vous n'avez pas besoin de réexécuter glmnet! Chaque lambda de la grille (
cv$lambda
) a déjà été exécuté. Cette technique s'appelle "Warm Start" et vous pouvez en lire plus ici . En reprenant l’introduction, la technique de démarrage à chaud réduit le temps d’exécution des méthodes itératives en utilisant la solution d’un problème d’optimisation différent (par exemple, glmnet avec un lambda plus grand) comme valeur de départ pour un problème d’optimisation ultérieur (par exemple, un glmnet avec un système de lambda plus petit) ).Pour extraire le cycle souhaité
cv.glmnet.fit
, essayez ceci:Révision (28/01/2017)
Pas besoin de pirater l'objet glmnet comme je l'ai fait ci-dessus; prendre @ conseils de alex23lemm ci - dessous et passer le
s = "lambda.min"
,s = "lambda.1se"
ou vers un autre numéro (par exemples = .007
) à la foiscoef
etpredict
. Notez que vos coefficients et vos prévisions dépendent de cette valeur définie par validation croisée. Utilisez une graine pour la reproductibilité! Et ne pas oublier que si vous ne fournissez pas"s"
danscoef
etpredict
, vous utiliserez la valeur par défauts = "lambda.1se"
. Je me suis préparé à ce défaut après l'avoir constaté qu'il fonctionnait mieux dans une petite situation de données.s = "lambda.1se"
tend également à fournir plus de régularisation, donc si vous travaillez avec alpha> 0, cela tendra également vers un modèle plus parcimonieux. Vous pouvez également choisir une valeur numérique de s à l'aide de plot.glmnet pour vous rendre quelque part entre les deux (n'oubliez pas d'exposer les valeurs de l'axe x!).la source
small.lambda.betas <- coef(cv, s = "lambda.min")
Q1) Je ne sais pas trop comment choisir Lambda. Q2) Devrais-je utiliser les variables non (.) Pour s’adapter à un autre modèle? Dans mon cas, j'aimerais garder autant de variables que possible.
Conformément à l'excellente réponse de @BenOgorek, vous laissez généralement l'appareillage utiliser une séquence lambda complète, puis, lors de l'extraction des coefficients optimaux, utilisez la valeur lambda.1se (contrairement à ce que vous avez fait).
Tant que vous suivez les trois mises en garde ci-dessous, ne vous opposez pas à la régularisation et ne modifiez pas le modèle: si une variable a été omise, c'est que la pénalité globale a été réduite. Les mises en garde sont les suivantes:
Pour que les coefficients régularisés soient significatifs, assurez-vous d'avoir préalablement normalisé explicitement les valeurs moyenne et standard de la variable avec
scale()
; ne comptez pas surglmnet(standardize=T)
. Pour justification, voir Est-ce que la normalisation avant Lasso est vraiment nécessaire? ; fondamentalement, une variable avec de grandes valeurs peut être injustement punie dans la régularisation.Pour être reproductible, utilisez
set.seed
plusieurs semences aléatoires et vérifiez la stabilité des coefficients régularisés.Si vous voulez une régularisation moins sévère, c’est-à-dire plus de variables incluses, utilisez alpha <1 (c’est-à-dire un filet élastique approprié) plutôt qu’une simple arête. Je suggère que vous balayiez l'alpha de 0 à 1. Si vous voulez le faire, pour éviter de surcharger l'hyperparamètre alpha et l'erreur de régression, vous devez utiliser la validation croisée, c'est-à-dire utiliser
cv.glmnet()
plutôt que simpleglmnet()
:.
Si vous souhaitez automatiser une telle recherche gridsearch avec CV, vous pouvez le coder vous-même ou utiliser le paquet d’ caret au-dessus de glmnet; caret le fait bien. Pour la
cv.glmnet nfolds
valeur du paramètre, choisissez 3 (minimum) si votre jeu de données est petit, ou 5 ou 10 s'il est grand.Q3) Comment connaître la valeur p, c’est-à-dire quelles variables prédisent de manière significative la réponse?
Non, ils n'ont pas de sens . Comme expliqué en détail dans Pourquoi est-il déconseillé d'obtenir des informations de synthèse statistique sur les coefficients de régression à partir du modèle glmnet?
Laissez simplement
cv.glmnet()
faire la sélection de variable automatiquement. Avec les mises en garde ci-dessus. Et bien sûr, la distribution de la variable de réponse devrait être normale (en supposant que vous utilisezfamily='gaussian'
).la source