Verwendung von LASSO aus dem Paket lars (oder glmnet) in R zur Variablenauswahl

39

Tut mir leid, wenn diese Frage etwas grundlegend ist.

Ich möchte die LASSO-Variablenauswahl für ein Modell mit mehreren linearen Regressionen in R verwenden. Ich habe 15 Prädiktoren, von denen einer kategorisch ist (wird das ein Problem verursachen?). Nach dem Setzen von und ich die folgenden Befehle:yxy

model = lars(x, y)
coef(model)

Mein Problem ist, wenn ich benutze coef(model). Dies gibt eine Matrix mit 15 Zeilen zurück, wobei jedes Mal ein zusätzlicher Prädiktor hinzugefügt wird. Es gibt jedoch keinen Vorschlag, welches Modell gewählt werden soll. Habe ich etwas verpasst Gibt es eine Möglichkeit, mit dem LARS-Paket nur ein " bestes " Modell zurückzugeben?

Es gibt andere Beiträge, die glmnetstattdessen die Verwendung vorschlagen, aber dies scheint komplizierter zu sein. Ein Versuch ist wie folgt, wobei das gleiche und . Habe ich hier etwas verpasst ?: yxy

cv = cv.glmnet(x, y)
model = glmnet(x, y, type.gaussian="covariance", lambda=cv$lambda.min)
predict(model, type="coefficients")

Der letzte Befehl gibt eine Liste meiner Variablen zurück, die Mehrheit mit einem Koeffizienten, obwohl einige = 0 sind. Ist dies die richtige Wahl des von LASSO ausgewählten " besten " Modells? Wenn ich dann ein lineares Modell mit all meinen Variablen anpasse, die Koeffizienten hatten, not=0erhalte ich sehr ähnliche, aber leicht unterschiedliche Koeffizientenschätzungen. Gibt es einen Grund für diesen Unterschied? Wäre es akzeptabel, das lineare Modell mit diesen von LASSO gewählten Variablen nachzurüsten und dies als mein endgültiges Modell zu verwenden? Ansonsten sehe ich keine p-Werte für die Signifikanz. Habe ich etwas verpasst

Tut

type.gaussian="covariance" 

Stellen Sie sicher, dass glmnetmehrere lineare Regressionen verwendet werden.

Hat die automatische Normalisierung der Variablen überhaupt Einfluss auf die Koeffizienten? Gibt es eine Möglichkeit, Interaktionsbegriffe in ein LASSO-Verfahren einzubeziehen?

Ich möchte dieses Verfahren eher als Demonstration dafür verwenden, wie LASSO verwendet werden kann, als für jedes Modell, das tatsächlich für wichtige Schlussfolgerungen / Vorhersagen verwendet wird, wenn dies etwas ändert.

Vielen Dank, dass Sie sich die Zeit genommen haben, dies zu lesen. Über allgemeine Kommentare zu LASSO / lars / glmnet würden wir uns ebenfalls sehr freuen.

James
quelle
4
Wenn Sie das Ergebnis als Nebenkommentar interpretieren möchten, müssen Sie unbedingt nachweisen, dass der von Lasso ausgewählte Variablensatz stabil ist. Dies kann mithilfe der Monte-Carlo-Simulation oder durch Bootstrapping Ihres eigenen Datensatzes erfolgen.
Frank Harrell

Antworten:

28

Die Bedienung glmnetist dank der hervorragenden Vignette unter http://web.stanford.edu/~hastie/glmnet/glmnet_alpha.html sehr einfach (Sie können auch die CRAN-Paketseite überprüfen). Für das beste Lambda glmnetgilt die Faustregel

cvfit <- glmnet::cv.glmnet(x, y)
coef(cvfit, s = "lambda.1se")

statt lambda.min.

Um dasselbe für larsSie zu tun, müssen Sie es von Hand tun. Hier ist meine Lösung

cv <- lars::cv.lars(x, y, plot.it = FALSE, mode = "step")
idx <- which.max(cv$cv - cv$cv.error <= min(cv$cv))
coef(lars::lars(x, y))[idx,]

Denken Sie daran, dass dies nicht genau dasselbe ist, da dies an einem Lassoknoten (wenn eine Variable eintritt) statt an einem beliebigen Punkt endet.

Bitte beachten Sie, dass dies glmnetdas bevorzugte Paket ist, das derzeit aktiv gewartet wird larsund dass bereits Fragen zu glmnetvs larsbeantwortet wurden (die verwendeten Algorithmen unterscheiden sich).

Was Ihre Frage der Verwendung von Lasso zur Auswahl von Variablen und zur Anpassung an OLS betrifft, so ist dies eine anhaltende Debatte. Google für OLS post Lasso und es gibt einige Artikel, die sich mit dem Thema befassen. Sogar die Autoren der Elemente des statistischen Lernens geben zu, dass dies möglich ist.

Bearbeiten : Hier ist der Code, um genauer zu reproduzieren, was in glmnettutlars

  cv <- lars::cv.lars(x, y, plot.it = FALSE)
  ideal_l1_ratio <- cv$index[which.max(cv$cv - cv$cv.error <= min(cv$cv))]
  obj <- lars::lars(x, y)
  scaled_coefs <- scale(obj$beta, FALSE, 1 / obj$normx)
  l1 <- apply(X = scaled_coefs, MARGIN = 1, FUN = function(x) sum(abs(x)))
  coef(obj)[which.max(l1 / tail(l1, 1) > ideal_l1_ratio),]
Juancentro
quelle
+1 Tolle Antwort! Könnten Sie oder jemand erläutern, warum Lambda.1se anstelle von Lambda.min die Faustregel ist?
Erosennin
Nachdem ich dies 4 Jahre lang geschrieben habe (und eine Weile kein Lasso mehr benutzt habe), ist meine Erinnerung einfach verschwunden. Es tut uns leid!
Juancentro
8

Ich komme vor einiger Zeit auf diese Frage zurück, da ich glaube, die richtige Lösung gefunden zu haben.

Hier ist eine Replik, die den mtcars-Datensatz verwendet:

library(glmnet)
`%ni%`<-Negate(`%in%')
data(mtcars)

x<-model.matrix(mpg~.,data=mtcars)
x=x[,-1]

glmnet1<-cv.glmnet(x=x,y=mtcars$mpg,type.measure='mse',nfolds=5,alpha=.5)

c<-coef(glmnet1,s='lambda.min',exact=TRUE)
inds<-which(c!=0)
variables<-row.names(c)[inds]
variables<-variables[variables %ni% '(Intercept)']

'variables' gibt Ihnen die Liste der Variablen, die die beste Lösung lösen.

Jason
quelle
1
Ich habe nach dem Code gesucht und festgestellt, dass "testing" noch nicht definiert wurde. Daher gibt der Code "final.list <-testing [-removed] #removing variables" den Fehler aus: object not found Angenommen, anstelle von "testing" sollte "cp.list" verwendet werden, damit der Code wie folgt lautet: final.list <-cp.list [-removed] #removing variables final.list <-c (final.list, duplicates) #adding in jenen vars, die beide entfernt und später hinzugefügt wurden. Lassen Sie mich wissen, ob dies korrekt ist. Mit freundlichen Grüßen
3
`% ni%` <-Negate (`% ni%`); ## sieht falsch aus. Während `% ni%` <-Negate (`% in%`); ## sieht richtig aus. Ich denke, der Stackexchange-Formatierer hat es durcheinander gebracht ...
Chris
Können Sie erläutern, wie Sie die Parameter nfolds=5und gewählt haben alpha=0.5?
Colin
7

Vielleicht hilft der Vergleich mit der schrittweisen Regression der Vorauswahl (siehe den folgenden Link zu einer Website eines der Autoren http://www-stat.stanford.edu/~tibs/lasso/simple.html). Dies ist der in Kapitel 3.4.4 der Elemente des statistischen Lernens verwendete Ansatz (kostenlos online verfügbar). Ich dachte, dass Kapitel 3.6 in diesem Buch dazu beitrug, die Beziehung zwischen den kleinsten Quadraten, der besten Teilmenge und dem Lasso (plus einige andere Verfahren) zu verstehen. Ich finde es auch hilfreich, die Transponierte des Koeffizienten t (coef (model)) und write.csv zu nehmen, damit ich sie in Excel zusammen mit einer Kopie des Plots (model) an der Seite öffnen kann. Sie können nach der letzten Spalte sortieren, die die Schätzung der kleinsten Quadrate enthält. Dann können Sie deutlich sehen, wie jede Variable bei jedem Stückschritt hinzugefügt wird und wie sich die Koeffizienten dadurch ändern. Natürlich ist das nicht die ganze Geschichte, aber es wird hoffentlich ein Anfang.

Joel Cadwell
quelle
3

larsund glmnetarbeiten auf Rohmatrizen. Um Interaktionsterme einzuschließen, müssen Sie die Matrizen selbst konstruieren. Das bedeutet eine Spalte pro Interaktion (bei Faktoren pro Ebene pro Faktor). Sehen Sie nach lm(), wie es funktioniert (Warnung: Es gibt Drachen).

Tut es jetzt, so etwas wie: Um eine Interaktion Begriff manuell zu machen, man könnte (aber vielleicht sollte nicht , weil es langsam ist) zu tun:

int = D["x1"]*D["x2"]
names(int) = c("x1*x2")
D = cbind(D, int)

Dann, um dies in lars zu verwenden (vorausgesetzt, Sie haben einen yKick um):

lars(as.matrix(D), as.matrix(y))

Ich wünschte, ich könnte Ihnen bei den anderen Fragen weiterhelfen. Ich habe diese gefunden, weil Lars mir Kummer bereitet und die Dokumentation darin und im Internet sehr dünn ist.

kousu
quelle
2
"Achtung, es gibt Drachen" Mit ist das ganz einfach model.matrix().
Gregor
2

LARS löst den GESAMTEN Lösungspfad. Der Lösungsweg ist stückweise linear - es gibt eine endliche Anzahl von "Kerben" -Punkten (dh Werte des Regularisierungsparameters), bei denen sich die Lösung ändert.

Die Matrix der Lösungen, die Sie erhalten, sind also alle möglichen Lösungen. In der Liste, die zurückgegeben wird, sollten auch die Werte des Regularisierungsparameters angegeben werden.

Adam
quelle
Vielen Dank für Ihre Antwort. Gibt es eine Möglichkeit, die Werte des Regularisierungsparameters anzuzeigen? Gibt es zusätzlich eine Möglichkeit, anhand dieses Parameters zwischen den Lösungen zu wählen? (Ist auch der Parameter Lambda?)
James
Beachten Sie, dass stückweise Linearität nicht bedeutet, dass die Linien horizontal sind, und daher ändert sich die Lösung mit Lambda ständig. Beispielsweise würde man für Vorhersagezwecke ein Gitter von Lambda-Werten nicht nur an, sondern auch zwischen den Knoten haben. Es ist durchaus möglich, dass irgendwann zwischen den Knoten die beste Prognoseleistung erzielt.
Richard Hardy