Implementando regressão de cume: Selecionando uma grade inteligente para ?

17

Estou implementando Ridge Regression em um módulo Python / C e me deparei com esse "pequeno" problema. A idéia é que eu queira provar os graus efetivos de liberdade mais ou menos igualmente espaçados (como o gráfico na página 65, nos "Elementos do aprendizado estatístico" ), ou seja, exemplo: que são os autovalores da matriz , de a \ mathrm {df} (\ lambda _ {\ min}) = p . Uma maneira fácil de definir o primeiro limite é deixar \ lambda _ {\ max} = \ sum_i ^ p d_i ^ 2 / c (assumindo que \ lambda _ {\ max} \ gg d_i ^ 2 ), em que c

df(λ)=i=1pdi2di2+λ,
di2XTXdf(λmax)0df(λmin)=pλmax=ipdi2/cλmaxdi2cé uma constante pequena e representa aproximadamente o grau mínimo de liberdade que você deseja amostrar (por exemplo, c=0.1 ). O segundo limite é obviamente λmin=0 .

Como o título sugere, preciso amostrar λ de λmin a λmax em uma escala em que df(λ) seja amostrada (aproximadamente), digamos, em 0.1 intervalos de c para p ... há uma maneira fácil de fazer isso? Eu pensei em resolver a equação df(λ) para cada λ usando o método Newton-Raphson, mas isso adicionará muitas iterações, especialmente quando p for grande. Alguma sugestão?

Néstor
fonte
1
Essa função é uma função racional convexa decrescente de λ0 . As raízes, principalmente se escolhidas em uma grade diádica, devem ser muito rápidas de encontrar.
cardeal
@ cardinal, você provavelmente está certo. No entanto, se possível, eu gostaria de saber se há alguma grade "padrão". Por exemplo, tentei obter uma grade executando , onde e funcionou muito bem para alguns graus de liberdade, mas, como , explodiu. Isso me fez pensar que talvez houvesse uma maneira legal de escolher a grade para os 's, é o que estou perguntando. Se isso não existir, eu também ficaria feliz em saber (como eu poderia deixar o método Newton-Rapson feliz em meu código, sabendo que "não existe melhor maneira"). λ=log(s)λmax/log(smax)s=(1,2,...,smax)df(λ)pλ
Néstor
Para ter uma idéia melhor das possíveis dificuldades que você está enfrentando, quais são os valores típicos e os piores casos de ? Existe algo que você sabe a priori sobre a distribuição de autovalores? p
cardeal
@ cardinal, os valores típicos de no meu aplicativo variam de a , mas quero torná-lo o mais geral possível. Sobre a distribuição de autovalores, não muito. é uma matriz que contém preditores em suas colunas, que nem sempre são ortogonais. p1540X
Néstor
1
Newton-Raphson normalmente encontra raízes com precisão de dentro de a etapas para e pequenos valores de ; quase nunca mais de etapas. Para valores maiores, ocasionalmente são necessários até passos. Como cada etapa requer cálculos de , a quantidade total de computação é inconseqüente. De fato, o número de etapas parece não depender de se um bom valor inicial for escolhido (eu escolho o que você usaria se todos os iguais à média). 101234p=40df(λ)630O(p)pdi
whuber

Respostas:

19

Esta é uma resposta longa . Então, vamos dar uma versão resumida dela aqui.

  • Não há uma boa solução algébrica para esse problema de busca de raiz, por isso precisamos de um algoritmo numérico.
  • A função possui muitas propriedades agradáveis. Podemos utilizá-los para criar uma versão especializada do método de Newton para esse problema, com convergência monotônica garantida para cada raiz.df(λ)
  • Mesmo o Rcódigo de morte encefálica, ausente de qualquer tentativa de otimização, pode calcular uma grade de tamanho 100 com em alguns segundos. Umcódigocuidadosamente escritoreduziria isso em pelo menos 2 a 3 ordens de magnitude.p=100000C

Existem dois esquemas abaixo para garantir a convergência monotônica. Um usa os limites mostrados abaixo, que parecem ajudar a salvar um ou dois passos de Newton ocasionalmente.

Exemplo : e uma grade uniforme para os graus de liberdade de tamanho 100. Os valores próprios são distribuídos por Pareto e, portanto, altamente distorcidos. Abaixo estão as tabelas do número de etapas de Newton para encontrar cada raiz.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 

Não haverá uma solução em forma fechada para esta , em geral, mas não é muito de estrutura presente, que pode ser usado para produzir soluções muito eficazes e seguros, utilizando métodos de determinação de raiz padrão.

Antes de aprofundar as coisas, vamos coletar algumas propriedades e conseqüências da função

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

Propriedade 0 : é uma função racional de . (Isso é aparente na definição.) Consequência 0 : Nenhuma solução algébrica geral existirá para encontrar a raiz . Isso ocorre porque existe um problema equivalente de busca de raiz polinomial de grau e, portanto, se não for extremamente pequeno (ou seja, menor que cinco), nenhuma solução geral existirá. Então, precisaremos de um método numérico.dfλ
df(λ)y=0pp

Propriedade 1 : a função é convexa e diminui em . (Pegue derivadas.) Consequência 1 (a) : O algoritmo de busca de raiz de Newton se comportará muito bem nessa situação. Seja os graus de liberdade desejados e a raiz correspondente, ou seja, . Em particular, se começarmos com qualquer valor inicial (então, ), a sequência de iterações da etapa Newton convergirá monotonicamente para o solução únicadfλ0
yλ0y=df(λ0)λ1<λ0df(λ1)>yλ1,λ2,λ0 .
Consequência 1 (b) : Além disso, se com , o primeiro passo renderia , de onde aumentará monotonicamente para a solução pela consequência anterior (consulte a advertência abaixo). Intuitivamente, esse último fato se segue porque, se começarmos à direita da raiz, a derivada é "rasa" demais devido à convexidade de e, portanto, o primeiro passo de Newton nos levará a algum lugar à esquerda da raiz. NB Como d f não éλ1>λ0λ2λ0dfdf geralmente convexo para λ negativoλ, isso fornece um forte motivo para preferir começar à esquerda da raiz desejada. Caso contrário, precisamos verificar novamente se o passo de Newton não resultou em um valor negativo para a raiz estimada, o que pode nos colocar em algum lugar em uma porção não-convexa de . Consequência 1 (c) : depois de encontrarmos a raiz para alguns y 1 e, em seguida, procurarmos a raiz de alguns , usandodf
y1y2<y1λ1 modo que como nosso palpite inicial garante que começamos à esquerda da segunda raiz. Portanto, nossa convergência é garantida para ser monotônica a partir daí.df(λ1)=y1

Propriedade 2 : Existem limites razoáveis ​​para fornecer pontos de partida "seguros". Usando argumentos de convexidade e desigualdade de Jensen, temos os seguintes limites Consequência 2 : Isso nos diz que a raiz satisfazendo obedece 1

p1+λpdi2df(λ)pidi2idi2+pλ.
d f ( λ 0 ) = yλ0df(λ0)=y Assim, até uma constante comum, imprensamos a raiz entre os meios harmônicos e aritméticos dod 2 i .
()11pEudEu-2(p-yy)λ0 0(1pEudEu2)(p-yy).
dEu2

Isso pressupõe que para todos i . Se este não for o caso, então o mesmo limite detém por considerar unicamente o positivo d i e substituindo p pelo número de positiva d i . NB : Como d f ( 0 ) = p assumindo todos os d idEu>0 0EudEupdEudf(0 0)=p , então y ( 0 , p ] , de onde os limites são sempre não triviais (por exemplo, o limite inferior é sempre não negativo).dEu>0 0y(0,p]

Aqui está um gráfico de um exemplo "típico" de com p = 400 . Sobrepusemos uma grade de tamanho 10 aos graus de liberdade. Estas são as linhas horizontais no gráfico. As linhas verdes verticais correspondem ao limite inferior em ( ) .df(λ)p=400()

Exemplo de gráfico de DOF com grade e limites

Um algoritmo e algum exemplo de código R

Um algoritmo muito eficiente, dada uma grade dos graus de liberdade desejados em ( 0 , p ], é classificá-los em ordem decrescente e, em seguida,encontrarsequencialmentea raiz de cada um, usando a raiz anterior como ponto de partida para o Podemos refinar isso ainda mais, verificando se cada raiz é maior que o limite inferior para a próxima raiz e, se não, podemos iniciar a próxima iteração no limite inferior.y1,yn(0,p]

Aqui está um exemplo de código R, sem nenhuma tentativa de otimizá-lo. Como visto abaixo, ainda é bastante rápido, embora Rseja - para ser educado - horrivelmente, terrivelmente, terrivelmente lento nos loops.

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

Abaixo está o algoritmo completo final, que recebe uma grade de pontos e um vetor de ( não d 2 i !).di 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
}

Exemplo de chamada de função

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)
cardeal
fonte
Favorecendo a pergunta para que eu possa voltar a esta resposta. Obrigado por postar esta análise detalhada, cardeal.
Macro
Resposta incrível :-), muito obrigado cardeal pelas sugestões e pela resposta.
Néstor
1

Além disso, existem alguns métodos que calcularão o caminho completo da regularização com eficiência:

  1. GPS
  2. glmnet
  3. gcdnet

Os pacotes acima são todos R, como você está usando Python, o scikit-learn contém implementações para cume, laço e rede elástica.

sebp
fonte
1
A olsfunção no rmspacote R pode usar otimização numérica para encontrar a penalidade ideal usando AIC eficaz. Mas você deve aplicar a penalidade máxima que nem sempre é fácil.
31812 Frank Harrell
0

Uma alternativa possível, de acordo com a fonte abaixo, parece ser:

df(λ)=tr(X(XX+λIp)1X)

(XX+λIp)1λ .

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

José Bayoán Santiago Calderón
fonte