Gratregression implementieren: Intelligentes Gitter für ?

17

Ich implementiere Ridge Regression in einem Python / C-Modul und bin auf dieses "kleine" Problem gestoßen. Die Idee ist, dass ich die effektiven Freiheitsgrade mehr oder weniger gleichmäßig verteilt abtasten möchte (wie die grafische Darstellung auf Seite 65 unter "Elemente des statistischen Lernens" ), dh Beispiel: wobei die Eigenwerte der Matrix aus bis \ mathrm {df} (\ lambda _ {\ min}) = p . Eine einfache Möglichkeit, die erste Grenze festzulegen, besteht darin, \ lambda _ {\ max} = \ sum_i ^ p d_i ^ 2 / c (unter der Annahme von \ lambda _ {\ max} \ gg d_i ^ 2 ) zu lassen, wobei c

df(λ)=i=1pdi2di2+λ,
di2XTXd f ( λ min ) = p λ max = p i d 2 i / c λ maxd 2 i cdf(λmax)0df(λmin)=pλmax=ipdi2/cλmaxdi2cist eine kleine Konstante und repräsentiert ungefähr den Mindestfreiheitsgrad, den Sie abtasten möchten (z. B. c=0.1 ). Die zweite Grenze ist natürlich λmin=0 .

Wie aus dem Titel hervorgeht, muss ich λ von λmin bis λmax in einer gewissen Skala abtasten, sodass df(λ) (ungefähr) abgetastet wird, z 0.1 Intervalle von c bis p ... gibt es eine einfache Möglichkeit, dies zu tun? Ich dachte, die Gleichung df(λ) für jedes λ mit einer Newton-Raphson-Methode zu lösen , aber dies fügt zu viele Iterationen hinzu, insbesondere wenn p groß ist. Irgendwelche Vorschläge?

Néstor
quelle
1
Diese Funktion ist eine abnehmende konvexe rationale Funktion von λ0 . Wurzeln sollten, besonders wenn sie über einem dyadischen Gitter ausgewählt werden, sehr schnell zu finden sein.
Kardinal
@ Cardinal, Sie haben wahrscheinlich Recht. Wenn möglich, würde ich gerne wissen, ob es ein "Standard" -Raster gibt. Ich habe zum Beispiel versucht, ein Gitter zu erhalten, indem ich λ=log(s)λmax/log(smax) , wobei s=(1,2,...,smax) und funktionierte für einige Freiheitsgrade ziemlich gut, aber als df(λ)p , blies es aus. Das ließ mich wundern, dass es vielleicht eine gute Möglichkeit gab, das Gitter für die Lambda zu wählen λ, was ich frage . Wenn dies nicht existiert, würde ich es auch gerne wissen (da ich die Newton-Rapson-Methode gerne in meinem Code belassen könnte, wenn ich wüsste, dass es keinen besseren Weg gibt).
Néstor
Was sind typische und Worst-Case-Werte für um sich ein Bild von den möglichen Schwierigkeiten zu machen, auf die Sie stoßen ? Wissen Sie a priori etwas über die Eigenwertverteilung? p
Kardinal
@ Kardinal, typische Werte von in meiner Anwendung reichen von bis , aber ich möchte es so allgemein wie möglich machen. Über die Eigenwertverteilung eigentlich nicht viel. ist eine Matrix, deren Spalten Prädiktoren enthalten, die nicht immer orthogonal sind. 15 40 Xp1540X
Néstor
1
Newton-Raphson findet in der Regel Wurzeln mit einer Genauigkeit von innerhalb von bis Schritten für und kleine Werte von ; fast nie mehr als Schritte. Bei größeren Werten sind gelegentlich bis zu Schritte erforderlich. Da für jeden Schritt -Berechnungen erforderlich sind , ist der gesamte Rechenaufwand ohne Belang. Tatsächlich scheint die Anzahl der Schritte nicht von abzuhängen, wenn ein guter Startwert gewählt wird (ich wähle denjenigen, den Sie verwenden würden, wenn alle dem Mittelwert entsprechen). 3 4 p = 40 d f ( λ ) 6 30 O ( p ) p d i101234p=40df(λ)630O(p)pdi
Whuber

Antworten:

19

Das ist eine lange Antwort . Lassen Sie uns hier eine Kurzgeschichtenversion davon geben.

  • Es gibt keine gute algebraische Lösung für dieses Problem, also brauchen wir einen numerischen Algorithmus.
  • Die Funktion hat viele schöne Eigenschaften. Wir können diese nutzen, um eine spezialisierte Version von Newtons Methode für dieses Problem mit garantierter monotoner Konvergenz für jede Wurzel zu erstellen .df(λ)
  • Sogar gehirntoter RCode ohne Optimierungsversuche kann in wenigen Sekunden ein Raster der Größe 100 mit 100.000 berechnen . Sorgfältig geschriebener Code würde dies um mindestens 2–3 Größenordnungen reduzieren.p=100000C

Im Folgenden werden zwei Schemata angegeben, um eine monotone Konvergenz zu gewährleisten. Man verwendet die unten gezeigten Grenzen, die gelegentlich helfen, ein oder zwei Newton-Schritte zu sparen.

Beispiel : und ein einheitliches Gitter für die Freiheitsgrade der Größe 100. Die Eigenwerte sind paretoverteilt und daher stark verzerrt. Unten finden Sie Tabellen mit der Anzahl der Newton-Schritte, um die einzelnen Wurzeln zu finden.p=100000

# Table of Newton iterations per root.
# Without using lower-bound check.
  1  3  4  5  6 
  1 28 65  5  1 
# Table with lower-bound check.
  1  2  3 
  1 14 85 

Es wird im Allgemeinen keine geschlossene Lösung dafür geben , aber es ist eine Menge Struktur vorhanden, die verwendet werden kann, um sehr effektive und sichere Lösungen unter Verwendung von Standardmethoden zum Auffinden von Wurzeln zu erzeugen.

Bevor wir uns zu sehr mit Dingen , wollen wir einige Eigenschaften und Konsequenzen der Funktion

df(λ)=i=1pdi2di2+λ.

Eigenschaft 0 : ist eine rationale Funktion von . (Dies geht aus der Definition hervor.) Konsequenz 0 : Es gibt keine allgemeine algebraische Lösung zum Finden der Wurzel . Dies liegt daran, dass es ein äquivalentes Polynomwurzelfindungsproblem des Grades Wenn also nicht extrem klein ist (dh weniger als fünf), gibt es keine allgemeine Lösung. Wir brauchen also eine numerische Methode. λ d f ( λ ) - y = 0 p pdfλ
df(λ)y=0pp

Eigenschaft 1 : Die Funktion ist konvex und nimmt bei . (Nehmen Sie Derivate.) Konsequenz 1 (a) : Newtons Algorithmus zum Auffinden von Wurzeln wird sich in dieser Situation sehr gut verhalten . Sei die gewünschten Freiheitsgrade und die entsprechende Wurzel, dh . Insbesondere wenn wir mit einem Anfangswert (also ) beginnen, konvergiert die Folge von Newton-Schritt-Iterationen monoton gegen einzigartige Lösung λ 0 y λ 0 y = d f ( λ 0 ) λ 1 < λ 0 d f ( λ 1 ) > y λ 1 , λ 2 , λ 0 λ 1 > λ 0 λ 2λ 0 d f d f λ d f y 1 y 2 < ydfλ0
yλ0y=df(λ0)λ1<λ0df(λ1)>yλ1,λ2,λ0 .
Konsequenz 1 (b) : Wenn wir mit , würde der erste Schritt , von wo aus er sich durch die vorherige Konsequenz monoton zur Lösung erhöht (siehe Warnung) unten). Intuitiv folgt diese letzte Tatsache, denn wenn wir rechts von der Wurzel beginnen, ist die Ableitung aufgrund der Konvexität von "zu" flach, und so führt uns der erste Newton-Schritt irgendwo links von der Wurzel. NB Da ist nicht im allgemeinen konvexen für negativeλ1>λ0λ2λ0dfdfλDies ist ein wichtiger Grund, lieber links von der gewünschten Wurzel zu beginnen. Andernfalls müssen wir noch einmal überprüfen, ob der Newton-Schritt zu keinem negativen Wert für die geschätzte Wurzel geführt hat, was dazu führen kann, dass wir uns irgendwo in einem nicht konvexen Teil von . Konsequenz 1 (c) : Sobald wir die Wurzel für ein und dann von einem nach der Wurzel suchen , verwenden wir so dass unsere anfängliche Vermutung ist das links von der zweiten Wurzel. Somit ist unsere Konvergenz von dort aus garantiert monoton.df
y1λ 1 d f ( λ 1 ) = y 1y2<y1λ1df(λ1)=y1

Eigenschaft 2 : Es gibt vernünftige Grenzen, um "sichere" Startpunkte zu geben. Unter Verwendung von Konvexitätsargumenten und Jensens Ungleichung ergeben sich folgende Grenzen: Consequence 2 : Dies sagt uns , dass die Wurzel erfüllt gehorcht Wir haben also bis auf eine gemeinsame Konstante die Wurzel zwischen dem harmonischen und dem arithmetischen Mittel von eingeklemmt .λ 0 d f ( λ 0 ) = y 1

p1+λpdi2df(λ)pidi2idi2+pλ.
λ0df(λ0)=yd 2 i
()11pidi2(pyy)λ0(1pidi2)(pyy).
di2

Dies setzt voraus, dass für alle . Ist dies nicht der Fall, so gilt dieselbe Schranke, indem nur das positive und durch die Anzahl des positiven . Anmerkung : Da Annahme von , ist , von wo aus die Grenzen immer nichttrivial sind (z. B. ist die untere Grenze immer nichtnegativ).i d i p d i d f ( 0 ) = p d i > 0 y ( 0 , p ]di>0idipdidf(0)=pdi>0y(0,p]

Hier ist eine Darstellung eines "typischen" Beispiels für mit . Für die Freiheitsgrade haben wir ein Raster der Größe 10 eingeblendet. Dies sind die horizontalen Linien im Plot. Die vertikalen grünen Linien entsprechen der unteren Grenze in .p = 400 ( )df(λ)p=400()

Beispiel dof Grundstück mit Raster und Grenzen

Ein Algorithmus und ein Beispiel für einen R-Code

Ein sehr effizienter Algorithmus, der ein Gitter gewünschter Freiheitsgrade in besteht darin, sie in absteigender Reihenfolge zu sortieren und dann nacheinander die Wurzel von jedem zu finden, wobei die vorherige Wurzel als Ausgangspunkt für die folgenden verwendet wird Wir können dies weiter verfeinern, indem wir prüfen, ob jede Wurzel größer als die Untergrenze für die nächste Wurzel ist, und wenn nicht, können wir die nächste Iteration stattdessen an der Untergrenze beginnen. ( 0 , p ]y1,yn(0,p]

Hier ist ein Beispielcode, in dem Rkeine Optimierungsversuche unternommen wurden. Wie unten zu sehen, ist es immer noch ziemlich schnell, obwohl Res - höflich ausgedrückt - entsetzlich, schrecklich, schrecklich langsam in Schleifen ist.

# Newton's step for finding solutions to regularization dof.

dof <- function(lambda, d) { sum(1/(1+lambda / (d[d>0])^2)) }
dof.prime <- function(lambda, d) { -sum(1/(d[d>0]+lambda / d[d>0])^2) }

newton.step <- function(lambda, y, d)
{ lambda - (dof(lambda,d)-y)/dof.prime(lambda,d) }

# Full Newton step; Finds the root of y = dof(lambda, d).
newton <- function(y, d, lambda = NA, tol=1e-10, smart.start=T)
{
    if( is.na(lambda) || smart.start )
        lambda <- max(ifelse(is.na(lambda),0,lambda), (sum(d>0)/y-1)/mean(1/(d[d>0])^2))
    iter <- 0
    yn   <- Inf
    while( abs(y-yn) > tol )
    {
        lambda <- max(0, newton.step(lambda, y, d)) # max = pedantically safe
        yn <- dof(lambda,d)
        iter = iter + 1
    }
    return(list(lambda=lambda, dof=y, iter=iter, err=abs(y-yn)))
}

Unten ist der endgültige vollständige Algorithmus, der ein Gitter von Punkten und einen Vektor von ( nicht !) .d 2 idi di2

newton.grid <- function(ygrid, d, lambda=NA, tol=1e-10, smart.start=TRUE)
{
    p <- sum(d>0)
    if( any(d < 0) || all(d==0) || any(ygrid > p) 
        || any(ygrid <= 0) || (!is.na(lambda) && lambda < 0) )
        stop("Don't try to fool me. That's not nice. Give me valid inputs, please.")
    ygrid <- sort(ygrid, decreasing=TRUE)
    out    <- data.frame()
    lambda <- NA
    for(y in ygrid)
    {
        out <- rbind(out, newton(y,d,lambda, smart.start=smart.start))
        lambda <- out$lambda[nrow(out)]
    }
    out
}

Beispiel Funktionsaufruf

set.seed(17)
p <- 100000
d <- sqrt(sort(exp(rexp(p, 10)),decr=T))
ygrid <- p*(1:100)/100
# Should take ten seconds or so.
out <- newton.grid(ygrid,d)
Kardinal
quelle
Ich bevorzuge die Frage, damit ich auf diese Antwort zurückgreifen kann. Vielen Dank für die Veröffentlichung dieser detaillierten Analyse, Kardinal.
Makro
Erstaunliche Antwort :-), vielen Dank Kardinal für die Vorschläge und die Antwort.
Néstor
1

Darüber hinaus gibt es eine Reihe von Methoden, mit denen der vollständige Regularisierungspfad effizient berechnet werden kann:

  1. Geographisches Positionierungs System
  2. glmnet
  3. gcdnet

Die obigen sind alle R-Pakete, da Sie Python verwenden, enthält scikit-learn Implementierungen für Ridge, Lasso und Elastic Net.

sebp
quelle
1
Die olsFunktion in dem R- rmsPaket kann die numerische Optimierung verwenden, um die optimale Strafe unter Verwendung eines effektiven AIC zu finden. Aber Sie müssen die maximale Strafe bereitstellen, die nicht immer einfach ist.
Frank Harrell
0

Eine mögliche Alternative nach der folgenden Quelle scheint zu sein:

Die Lösung in geschlossener Form: df(λ)=tr(X(XX+λIp)1X)

Wenn Sie die normale Gleichung als Löser verwenden oder die Varianz-Kovarianz-Schätzung berechnen, sollten Sie bereits berechnet haben . Dieser Ansatz funktioniert am besten, wenn Sie die Koeffizienten bei den verschiedenen schätzen . λ(XX+λIp)1λ

Quelle: https://onlinecourses.science.psu.edu/stat857/node/155

José Bayoán Santiago Calderón
quelle