Implementazione della regressione della cresta: selezione di una griglia intelligente per


17

Sto implementando Ridge Regression in un modulo Python / C, e ho riscontrato questo "piccolo" problema. L'idea è che voglio campionare i gradi di libertà effettivi più o meno equamente distanziati (come la trama a pagina 65 su "Elementi di apprendimento statistico" ), cioè campione:

df(λ)=i=1pdi2di2+λ,
di2XTXdf(λmax)0df(λmin)=pλmax=ipdi2/cλmaxdi2cc=0.1λmin=0

Come suggerisce il titolo, quindi, ho bisogno di campionare λ da λmin a λmax in una scala tale che df(λ) sia campionato (approssimativamente), diciamo, in 0.1 intervalli da c a p ... c'è un modo semplice per farlo? Ho pensato di risolvere l'equazione df(λ) per ogni λ usando un metodo Newton-Raphson, ma questo aggiungerà troppe iterazioni, specialmente quando p è grande. Eventuali suggerimenti?


1
Questa funzione è una funzione razionale convessa decrescente di λ0 . Le radici, in particolare se scelte su una griglia diadica, dovrebbero essere molto veloci da trovare.
cardinale il

@cardinale, probabilmente hai ragione. Tuttavia, se possibile, vorrei sapere se esiste una griglia "predefinita". Ad esempio, ho provato a ottenere una griglia facendo , dove e ha funzionato abbastanza bene per alcuni gradi di libertà, ma come , è saltato fuori. Questo mi ha fatto pensare che forse c'era un modo preciso per scegliere la griglia per 's, che è quello che sto chiedendo. Se questo non esiste, sarei anche felice di saperlo (poiché potrei lasciare felicemente il metodo Newton-Rapson nel mio codice sapendo che "non esiste un modo migliore"). λ=log(s)λmax/log(smax)s=(1,2,...,smax)df(λ)pλ
Néstor,

Per avere una migliore idea delle potenziali difficoltà che si incontrano, quali sono i valori tipici e nel caso peggiore di ? C'è qualcosa che conosci a priori sulla distribuzione degli autovalori? p
cardinale il

@cardinal, i valori tipici di nella mia applicazione vanno da a , ma voglio renderlo il più generale possibile. A proposito della distribuzione degli autovalori, non molto. è una matrice che contiene predittori nelle sue colonne, che non sono sempre ortogonali. p1540X
Néstor,

1
Newton-Raphson tipicamente trova radici per precisione entro a passaggi per e piccoli valori di ; quasi mai più di passaggi. Per valori più grandi, occasionalmente sono necessari fino a passaggi. Poiché ogni passaggio richiede calcoli , la quantità totale di calcolo è irrilevante. In effetti, il numero di passaggi non sembra dipendere da se viene scelto un buon valore iniziale ( quello che se tutti i uguali alla loro media). 3 4 p = 40 d f ( λ ) 6 30 O ( p ) p d i101234p=40df(λ)630O(p)pdi
whuber

Risposte:


19

Si tratta di una risposta lunga . Quindi, diamo una versione breve di questo qui.

  • Non esiste una buona soluzione algebrica a questo problema di ricerca delle radici, quindi abbiamo bisogno di un algoritmo numerico.
  • La funzione ha molte belle proprietà. Possiamo sfruttarli per creare una versione specializzata del metodo di Newton per questo problema con una convergenza monotonica garantita a ciascuna radice.df(λ)
  • Perfino il Rcodice morto in assenza di qualsiasi tentativo di ottimizzazione può calcolare una griglia di dimensioni 100 con in pochi secondi. Un codice scritto con cura ridurrebbe questo di almeno 2-3 ordini di grandezza.p=100000C

Di seguito sono riportati due schemi per garantire la convergenza monotonica. Uno usa i limiti mostrati di seguito, che sembrano aiutare a salvare uno o due passi di Newton a volte.

Esempio : e una griglia uniforme per i gradi di libertà di dimensione 100. Gli autovalori sono distribuiti da Pareto, quindi fortemente inclinati. Di seguito sono riportate le tabelle del numero di passaggi di Newton per trovare ciascuna radice.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 

Non ci sarà una soluzione in forma chiusa per questo , in generale, ma v'è un sacco di struttura attuale che può essere utilizzato per produrre soluzioni molto efficaci e sicure con metodi radice-finding standard.

Prima di scavare troppo a fondo nelle cose, raccogliamo alcune proprietà e conseguenze della funzione

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

La proprietà 0 : è una funzione razionale di . (Ciò è evidente dalla definizione.) Conseguenza 0 : non esiste una soluzione algebrica generale per trovare la radice . Questo perché esiste un equivalente problema di individuazione delle radici polinomiali di grado e quindi se non è estremamente piccolo (cioè meno di cinque), non esisterà una soluzione generale. Quindi, avremo bisogno di un metodo numerico. λdfλ
df(λ)y=0ppp

Proprietà 1 : la funzione è convessa e decrescente su . (Prendi i derivati.) Conseguenza 1 (a) : l'algoritmo di ricerca delle radici di Newton si comporterà molto bene in questa situazione. Sia il grado desiderato di libertà e la radice corrispondente, cioè . In particolare, se iniziamo con qualsiasi valore iniziale (quindi, ), allora la sequenza di iterazioni di Newton convergeranno monotonicamente al soluzione unica λ 0dfλ0
yλ0y=df(λ0)λ1<λ0df(λ1)>yλ1,λ2,λ0 .
Conseguenza 1 (b) : Inoltre, se dovessimo iniziare con , il primo passo produrrebbe e quindi il primo passo di Newton ci porterà da qualche parte a sinistra della radice. NB Poiché non è generalmente convesso per negativoλ1>λ0λ2λ0, da cui aumenterà monotonicamente alla soluzione dalla conseguenza precedente (vedi avvertenza di seguito). Intuitivamente, questo ultimo fatto segue perché se iniziamo a destra della radice, la derivata è "troppo" superficiale a causa della convessità di , questo fornisce un motivo forte per preferire iniziare a sinistra della radice desiderata. Altrimenti, dobbiamo ricontrollare che il passaggio di Newton non abbia comportato un valore negativo per la radice stimata, che potrebbe posizionarci da qualche parte in una porzione non convessa di . Conseguenza 1 (c) : una volta trovata la radice per alcuni e quindi stiamo cercando la radice da alcunidfdfλdf
y1y2<y1 , usando tale che come la nostra ipotesi iniziale garantiamo che iniziamo a la sinistra della seconda radice. Quindi, la nostra convergenza è garantita per essere monotona da lì.λ1df(λ1)=y1

Proprietà 2 : esistono limiti ragionevoli per dare punti di partenza "sicuri". Utilizzando argomenti di convessità e disuguaglianza di Jensen, abbiamo i seguenti limiti Conseguenza 2 : questo ci dice che la radice soddisfacente

p1+λpdi2df(λ)pidi2idi2+pλ.
λ0df(λ0)=y obbedisce Quindi, fino a una costante comune, abbiamo inserito la radice tra i mezzi armonici e aritmetici di .
()11pidi2(pyy)λ0(1pidi2)(pyy).
di2

Ciò presuppone che per tutti . In caso contrario, lo stesso limite vale considerando solo il positivo e sostituendo con il numero di positivo . NB : da alloradi>0idipdidf(0)=p assumendo tutto , quindi , da cui i limiti sono sempre non banali (ad esempio, il limite inferiore è sempre non negativo).di>0y(0,p]

Ecco un diagramma di un esempio "tipico" di condf(λ)p=400 . Abbiamo sovrapposto una griglia di dimensioni 10 per i gradi di libertà. Queste sono le linee orizzontali nella trama. Le linee verdi verticali corrispondono al limite inferiore in .()

Esempio di trama con griglia e limiti

Un algoritmo e qualche esempio di codice R.

Un algoritmo molto efficiente dato una griglia di gradi di libertà desideratiy1,yn in è quello di ordinarli in ordine decrescente e quindi trovare sequenzialmente la radice di ciascuno, usando la radice precedente come punto di partenza per il seguente 1. Possiamo perfezionarlo ulteriormente controllando se ogni radice è maggiore del limite inferiore per la radice successiva e, in caso contrario, possiamo invece iniziare la successiva iterazione sul limite inferiore.(0,p]

Ecco alcuni esempi di codice R, senza tentativi di ottimizzazione. Come visto di seguito, è ancora abbastanza veloce anche se Rè - per dirla educatamente - terrificante, terribile, terribilmente terribilmente lento agli anelli.

# 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)))
}

Di seguito è riportato l'algoritmo completo finale che accetta una griglia di punti e un vettore di ( nondi 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
}

Chiamata di funzione di esempio

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)

Favorire la domanda in modo da poter fare riferimento a questa risposta. Grazie per aver pubblicato questa analisi dettagliata, cardinale.
Macro,

Risposta incredibile :-), grazie mille cardinale per i suggerimenti E la risposta.
Néstor,

1

Inoltre, esistono un paio di metodi che calcoleranno in modo efficiente l'intero percorso di regolarizzazione:

  1. GPS
  2. glmnet
  3. gcdnet

Quanto sopra sono tutti i pacchetti R, poiché stai usando Python, scikit-learn contiene implementazioni per ridge, lazo e rete elastica.


1
La olsfunzione nel rmspacchetto R può usare l'ottimizzazione numerica per trovare la penalità ottimale usando AIC efficace. Ma devi fornire la massima penalità che non è sempre facile.
Frank Harrell,

0

Una possibile alternativa secondo la fonte qui sotto sembra essere:

La soluzione in forma chiusa: df(λ)=tr(X(XX+λIp)1X)

Se dovessi usare l'equazione normale come solutore o calcolare la stima della varianza-covarianza, dovresti già aver calcolato . Questo approccio funziona meglio se si stanno valutando i coefficienti ai vari λ .(XX+λIp)1λ

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

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.