Um mergulho profundo no glmnet: predict.glmnet

cupom com desconto - o melhor site de cupom de desconto cupomcomdesconto.com.br


Estou escrevendo uma série de postagens em várias opções de função do glmnet (do pacote com o mesmo nome), na esperança de fornecer mais detalhes e insights além da documentação de R.

Neste post, em vez de olhar para uma das opções de função de glmnet, veremos o predict método para um glmnet objeto em vez disso. O objeto retornado por glmnet (chame-o fit) tem classe "glmnet"; quando corremos predict(fit), executa o predict método para classe "glmnet" objetos, ou seja, predict.glmnet(fit).

Para referência, aqui está a assinatura completa do predict.glmnet função / método (v3.0-2):

predict(object, newx, s = NULL, type = c("link",
  "response", "coefficients", "nonzero", "class"), exact = FALSE,
  newoffset, ...)

No acima, object é um equipado "glmnet" objeto (chame-o fit) Lembre-se de que todo glmnet fit tem uma sequência lambda associada: isso será importante para entender o que se segue. (Esta sequência pode ser acessada via fit$lambda.)

Para o restante desta postagem, usaremos o seguinte exemplo de dados:

set.seed(1)
n 

Function option: newx

newx is simply the new x matrix at which we want predictions for. So for example, if we want predictions for the training x matrix, we would do

predict(fit, x)

Se nenhum outro argumento for passado, obteremos uma matriz de previsões, cada coluna correspondendo às previsões para cada valor de  lambda

no fit$lambda. Para o nosso exemplo, fit$lambda tem comprimento 68 e x consiste em 100 linhas / observações, então predict(fit, x) retorna um 100  vezes 68 matriz.

length(fit$lambda)
# [1] 68
dim(predict(fit, x))
# [1] 100  68

newx deve ser fornecido, exceto quando type="coefficients" ou type="nonzero" (mais sobre esses tipos posteriormente).

Opção de função: newoffset

Se o original glmnet chamada foi ajustada com um deslocamento, então um deslocamento deve ser incluído no predict ligar sob o newoffset opção. Se não incluído, um erro será gerado.

set.seed (2)
Deslocamento 

O inverso é verdadeiro, pois se o original glmnet a chamada NÃO coubera com um deslocamento, então predict não permitirá que você inclua um deslocamento na previsão, MESMO se você passar o newoffset opção. Não lança um aviso ou erro, mas simplesmente ignora o newoffset opção. Você foi avisado! Isso é demonstrado no snippet de código abaixo.

pred_no_offset 

Opção de função: s e exact

s indica o  lambda

valores para os quais queremos previsões. Se o usuário não especificar s, predict dará previsões para cada um dos  lambda valores em fit$lambda.

(Por que essa opção é chamada s e não o mais intuitivo lambda? Na página 5 desta vinheta, os autores dizem que fizeram essa escolha "caso mais tarde desejemos permitir que se especifique o tamanho do modelo de outras maneiras". lambda controla o tamanho do modelo no sentido de que quanto maior, mais coeficientes serão forçados a zero. Existem outras maneiras de especificar o tamanho do modelo. Por exemplo, pode-se imaginar uma opção de função em que especificamos o número de coeficientes diferentes de zero que queremos no modelo ou onde especificamos o valor máximo  ell_1

norma que o vetor de coeficiente pode ter. Nenhuma dessas outras opções foi implementada no momento.)

Se o usuário especificado s todos os valores pertencem fit$lambda, então predict extrai os coeficientes correspondentes a esses valores e retorna previsões. Nesse caso, o exact opção não tem efeito.

Se o usuário especificado s valor NÃO pertence a fit$lambda, as coisas ficam interessantes. E se exact=FALSE (o padrão), predict usa interpolação linear para fazer previsões. (Mais precisamente, ele faz interpolação linear dos coeficientes, o que se traduz em interpolação linear das previsões.) Como declarado na documentação: “embora essa seja uma boa aproximação, às vezes pode ser um pouco grossa”.

Como demonstração: no snippet abaixo, analisamos as previsões com um valor de  lambda

que se encontra entre os dois maiores valores em fit$lambda. Se a função funcionar como a documentação diz, a última linha deve fornecer um valor 0 (para precisão da máquina).
b1 

O que acontece se tivermos valores em s que não estão dentro da faixa de fit$lambda? Primeiro, eu recomendaria usar exact=TRUE porque extrapolação além da faixa de fit$lambda é perigoso em geral. Nos meus pequenos experimentos, parece predict simplesmente retorna as previsões para o  lambda

valor em fit$lambda que é o mais próximo s.

E se exact=TRUE, predict mescla s com fit$lambda para conseguir um único (decrescente)  lambda

sequência, reposiciona o modelo glmnet e retorna as previsões no  lambda valores em s. Se seus dados de treinamento forem muito grandes, essa remessa poderá demorar muito tempo.

Uma nota ao usar exact=TRUE é que você precisa passar argumentos adicionais para que a instalação ocorra. Isso porque o equipado glmnet O objeto não contém todos os ingredientes necessários para a remontagem. Para o nosso exemplo, prever para fit precisamos fornecer x e y também. Para chamadas glmnet mais complicadas, mais opções precisam ser fornecidas.

cupom com desconto - o melhor site de cupom de desconto cupomcomdesconto.com.br
prever (ajuste, x, s = ajuste $ lambda[68] / 2, exato = TRUE)
# Erro: usado coef.glmnet () ou prediz.glmnet () com `exact = TRUE`
# também deve fornecer o (s) argumento (s) original (is) x e y para
# execute novamente o glmnet com segurança
prever (ajuste, x, s = ajuste $ lambda[68] / 2, exato = VERDADEIRO, x = x, y = y)
# glmnet retorna corretamente as previsões ...

Opção de função: type

o type A opção determina o tipo de previsão retornada. type="coefficients" retorna os coeficientes do modelo para o  lambda

valores em s como uma matriz esparsa. type="nonzero" retorna uma lista, com cada elemento sendo um vetor dos recursos que possuem recursos diferentes de zero. Por exemplo, o trecho de código abaixo mostra que, para o segundo e terceiro  lambda valores em fit$lambda, os recursos que possuem coeficientes diferentes de zero são o recurso 5 e os recursos 3 e 5, respectivamente.

predict(fit, type = "nonzero", s = fit$lambda[2:3])
# $`1`
# [1] 5
# 
# $`2`
# [1] 3 5

Para type="coefficients" e type="nonzero", o usuário não precisa fornecer um newx argumento, já que o valor de retorno não depende de onde queremos as previsões. Nos demais valores possíveis de type, newx É necessário.

Para type="link" (o padrão) e type="response" ajuda a conhecer um pouco da teoria GLM. Para uma observação com valores x  in  mathbb {R} ^ p

, type="link" retorna x ^ T  beta, Onde beta é o vetor de coeficiente correspondente a um  lambda valor em s.

Para type="response", x ^ T  beta

é passado pela função de link inverso do GLM para retornar previsões no y escala. Para a família "gaussiana" ainda é x ^ T  beta. Para famílias “binomiais” e “poisson”, é  exp (x ^ T  beta) / (1 +  exp (x ^ T  beta)) e  exp (x ^ T  beta) respectivamente. Para "multinomial", ele retorna probabilidades ajustadas e, para "cox", retorna risco relativo ajustado.

A possibilidade final, type="class", aplica-se apenas às famílias "binomial" e "multinomial". Para cada observação, simplesmente retorna a classe com a maior probabilidade prevista.

Bônus: O coef método

o coef O método para glmnet é na verdade apenas um caso especial do predict método. Isso pode ser visto no código-fonte:

coef.glmnet
# function (object, s = NULL, exact = FALSE, ...) 
#     predict(object, s = s, type = "coefficients", exact = exact, 
#             ...)
# 
# 

Bônus: predict.elnet, predict.lognet,…

Se você inspecionar a classe do objeto retornado por um glmnet chamada, você perceberá que há mais de uma classe. No código abaixo, vemos que a família "gaussiana" resulta em um objeto de classe "elnet". (A família "binomial" retorna um objeto "lognet", a família "poisson" retorna um objeto "fishnet", etc.)

class(fit)
# [1] "elnet"  "glmnet"

Essas classes têm seus próprios predict métodos também, mas eles se baseiam nessa base predict.glmnet ligar. Como exemplo, aqui está o código para predict.fishnet:

glmnet:::predict.fishnet
# function (object, newx, s = NULL, type = c("link", "response", 
#        "coefficients", "nonzero"), exact = FALSE, newoffset, ...) 
# {
#     type = match.arg(type)
#     nfit = NextMethod("predict")
#     switch(type, response = exp(nfit), nfit)
# }
# 
# 

O que acontece aqui é que predict.glmnet é chamado pela primeira vez. E se type não é "response", simplesmente retornamos o que quer predict.glmnet teria retornado. No entanto, se type="response", então (i) chamamos predict.glmnete (ii) as previsões são passadas através da função x  mapsto  exp (x)

antes de ser devolvido.

É assim predict é capaz de fornecer a saída de retorno correta nos diferentes family e type opções



Se você chegou até aqui, por que não inscreva-se para atualizações do site? Escolha seu sabor: e-mail, Twitter, RSS ou facebook ...



cupom com desconto - o melhor site de cupom de desconto cupomcomdesconto.com.br
Leia Também  O que é regressão isotônica? | R-bloggers