Come interpretare glmnet?


36

Sto cercando di adattare un modello di regressione lineare multivariata con circa 60 variabili predittive e 30 osservazioni, quindi sto usando il pacchetto glmnet per la regressione regolarizzata perché p> n.

Ho esaminato la documentazione e altre domande ma non riesco ancora a interpretare i risultati, ecco un codice di esempio (con 20 predittori e 10 osservazioni per semplificare):

Creo una matrice x con num righe = num osservazioni e num cols = num predittori e un vettore y che rappresenta la variabile di risposta

> x=matrix(rnorm(10*20),10,20)
> y=rnorm(10)

Adatto un modello glmnet lasciando alfa come impostazione predefinita (= 1 per penalità lazo)

> fit1=glmnet(x,y)
> print(fit1)

Capisco di ottenere diverse previsioni con valori decrescenti di lambda (cioè penalità)

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

Ora prevedo i miei valori Beta scegliendo, ad esempio, il valore lambda più piccolo dato da 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

Se invece scelgo lambda con

cv <- cv.glmnet(x,y)
model=glmnet(x,y,lambda=cv$lambda.min)

Tutte le variabili sarebbero (.).

Dubbi e domande:

  1. Non sono sicuro di come scegliere lambda.
  2. Devo usare le variabili non (.) Per adattarsi a un altro modello? Nel mio caso, vorrei mantenere quante più variabili possibili.
  3. Come faccio a sapere il valore p, ovvero quali variabili prevedono in modo significativo la risposta?

Mi scuso per la mia scarsa conoscenza statistica! E grazie per l'aiuto.


Forse dai un'occhiata al pacchetto CRAN hdi , che si fornisce inferenza per i modelli ad alta dimensione ...
Tom Wenseleers,

Per la spiegazione completa dei metodi utilizzati vi rimando a questo documento: projecteuclid.org/euclid.ss/1449670857
Tom Wenseleers,

Risposte:


40

Ecco un fatto non intuitivo: in realtà non dovresti dare a glmnet un singolo valore di lambda. Dalla documentazione qui :

Non fornire un singolo valore per lambda (per le previsioni dopo l'uso CV predict () invece). Fornire invece una sequenza decrescente di valori lambda. glmnet fa affidamento sui suoi riscaldamenti inizia per la velocità, e spesso è più veloce per percorrere un intero percorso piuttosto che calcolare un singolo tratto.

cv.glmnetti aiuterà a scegliere lambda, come hai accennato nei tuoi esempi. Gli autori del pacchetto glmnet suggeriscono cv$lambda.1seinvece di cv$lambda.min, ma in pratica ho avuto successo con quest'ultimo.

Dopo aver eseguito cv.glmnet, non è necessario rieseguire glmnet! Ogni lambda nella griglia ( cv$lambda) è già stato eseguito. Questa tecnica si chiama "Warm Start" e puoi leggere di più qui . Parafrasando dall'introduzione, la tecnica Warm Start riduce il tempo di esecuzione dei metodi iterativi utilizzando la soluzione di un diverso problema di ottimizzazione (ad es. Glmnet con un lambda più grande) come valore iniziale per un successivo problema di ottimizzazione (ad es. Glmnet con un lambda più piccolo ).

Per estrarre la corsa desiderata da cv.glmnet.fit, provare questo:

small.lambda.index <- which(cv$lambda == cv$lambda.min)
small.lambda.betas <- cv$glmnet.fit$beta[, small.lambda.index]

Revisione (28/01/2017)

Non c'è bisogno di hackerare l'oggetto glmnet come ho fatto sopra; prendi i consigli di @ alex23lemm qui sotto e passa il s = "lambda.min", s = "lambda.1se"o qualche altro numero (es. s = .007) a entrambi coefe predict. Si noti che i coefficienti e le previsioni dipendono da questo valore impostato per convalida incrociata. Usa un seme per la riproducibilità! E non dimenticare che se non fornisci un "s"in coefe predict, utilizzerai il valore predefinito di s = "lambda.1se". Mi sono riscaldato a quell'impostazione predefinita dopo averlo visto funzionare meglio in una situazione di piccoli dati.s = "lambda.1se"tende anche a fornire una maggiore regolarizzazione, quindi se lavori con alpha> 0, tenderà anche verso un modello più parsimonioso. Puoi anche scegliere un valore numerico di s con l'aiuto di plot.glmnet per raggiungere un punto intermedio (semplicemente non dimenticare di esponenziare i valori dall'asse x!).


1
Grazie! Questo aiuta ... hai forse una risposta per le domande 2 e 3?
Alice

3
Non ha preoccupazioni. I (.) Rappresentano zeri. Da quando sei andato con Lasso, hai specificato che vuoi una soluzione "sparsa" (cioè molti zeri). Se vuoi che abbiano tutti dei valori, imposta alpha = 0. Ora sei passato dalla regressione Lasso a Ridge. i valori di p per glmnet sono concettualmente difficili. Se cerchi su Google "valori-p per il lazo", ad esempio, vedrai molte ricerche e dibattiti recenti. Ho anche letto un resoconto (fonte di amnesia) in cui l'autore ha sostenuto che i valori di p non hanno senso per regressioni distorte come la regressione del lasso e della cresta.
Ben Ogorek,

6
Un modo alternativo per estrarre i coefficienti associati al valore di lambda che fornisce il minimo cvm è il seguente:small.lambda.betas <- coef(cv, s = "lambda.min")
alex23lemm

1
@BenOgorek, eccellente aggiornamento! Un altro riferimento utile è Friedman J, Hastie T, Hoefling H, Tibshirani R. Ottimizzazione delle coordinate Pathwise. Annali di statistiche applicate. 2007; 2 (1): 302-332. ( arxiv.org/pdf/0708.1485.pdf )
dv_bn

1
@erosennin, controlla l'argomento lambda di cv.glmnet: "Sequenza lambda facoltativa fornita dall'utente; il valore predefinito è NULL e glmnet sceglie la propria sequenza." Ti consigliamo di utilizzare il principio di avvio a caldo e iniziare la sequenza con alcuni valori più grandi di lambda prima di ridurre l'intervallo che ti interessa.
Ben Ogorek,

2

Q1) Non sono sicuro di come scegliere lambda. Q2) Devo usare le variabili non (.) Per adattarsi a un altro modello? Nel mio caso, vorrei mantenere quante più variabili possibili.

Secondo la grande risposta di @ BenOgorek, in genere si consente al raccordo di utilizzare un'intera sequenza lambda, quindi durante l'estrazione dei coefficienti ottimali utilizzare il valore lambda.1se (a differenza di quello che è stato fatto).

Fintanto che segui le tre avvertenze di seguito, non combattere la regolarizzazione o modificare il modello: se una variabile è stata omessa, è perché ha dato una penalità complessiva inferiore. Le avvertenze sono:

  1. Affinché i coefficienti regolarizzati siano significativi, assicurati di aver esplicitamente normalizzato in anticipo la media e lo stdev della variabile scale(); non fare affidamento glmnet(standardize=T). Per la giustificazione vedi La standardizzazione prima di Lasso è davvero necessaria? ; sostanzialmente una variabile con valori elevati potrebbe essere ingiustamente punita nella regolarizzazione.

  2. Per essere riproducibile, corri con set.seeddiversi semi casuali e controlla la stabilità dei coefficienti regolarizzati.

  3. Se si desidera una regolarizzazione meno rigida, ovvero più variabili incluse, utilizzare alpha <1 (ovvero una rete elastica adeguata) anziché una semplice cresta. Ti suggerisco di spostare l'alfa da 0 a 1. Se hai intenzione di farlo, quindi per evitare di sovralimentare l'iperparametro alfa e l'errore di regressione, devi usare la crossvalidation, cioè usare cv.glmnet()piuttosto che semplice glmnet():

.

for (alpha in c(0,.1,.3,.5,.7,.9,1)) {
  fit <- cv.glmnet(..., alpha=alpha, nfolds=...)
  # Look at the CVE at lambda.1se to find the minimum for this alpha value...
}

Se si desidera automatizzare tale ricerca di gridsearch con CV, è possibile codificarlo da soli o utilizzare il pacchetto di inserimento in cima a glmnet; caret lo fa bene. Per il cv.glmnet nfoldsvalore del parametro, selezionare 3 (minimo) se il set di dati è piccolo o 5 o 10 se è grande.

Q3) Come faccio a sapere il valore p, ovvero quali variabili prevedono in modo significativo la risposta?

No, non sono significativi . Come spiegato in dettaglio in Perché non è consigliabile ottenere informazioni di riepilogo statistiche per i coefficienti di regressione dal modello glmnet?

Lascia cv.glmnet()fare automaticamente la selezione della variabile. Con le avvertenze sopra. E ovviamente la distribuzione della variabile di risposta dovrebbe essere normale (supponendo che tu stia usando family='gaussian').


Grazie per il commento molto utile! Ho anche sperimentato che standardizzare le variabili da solo sembra funzionare piuttosto che usare glmnet (standardize = T).
Michelle,

Ho una domanda @smci, riguardo ai valori beta restituiti da cvglmnet. Comprendo che sono valori beta in ogni punto della griglia dei tentativi di valori lambda. Tuttavia, vengono restituiti i valori beta per ciascun valore lambda (1) i valori medi dei coefficienti delle 10 pieghe (supponendo che io abbia usato 10foldCV), (2) i valori beta della piega che ha dato la migliore precisione, oppure (3) i coefficienti di rieseguire il modello sull'intero set di dati?
Michelle,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.