Regressione logistica bayesiana regolarizzata in JAGS


13

Esistono diversi documenti matematici che descrivono il lazo bayesiano, ma voglio un codice JAGS testato e corretto che posso usare.

Qualcuno potrebbe pubblicare un codice BUGS / JAGS di esempio che implementa la regressione logistica regolarizzata? Qualsiasi schema (L1, L2, Elasticnet) sarebbe fantastico, ma è preferito Lasso. Mi chiedo anche se ci sono interessanti strategie di implementazione alternative.

Risposte:


19

Poiché la regolarizzazione L1 equivale a un Laplace (doppio esponenziale) prima dei relativi coefficienti, è possibile farlo come segue. Qui ho tre variabili indipendenti x1, x2 e x3 e y è la variabile di destinazione binaria. La selezione del parametro di regolarizzazione viene fatta inserendo un hyperprior su di esso, in questo caso appena uniforme su un intervallo di buone dimensioni.λ

model {
  # Likelihood
  for (i in 1:N) {
    y[i] ~ dbern(p[i])

    logit(p[i]) <- b0 + b[1]*x1[i] + b[2]*x2[i] + b[3]*x3[i]
  }

  # Prior on constant term
  b0 ~ dnorm(0,0.1)

  # L1 regularization == a Laplace (double exponential) prior 
  for (j in 1:3) {
    b[j] ~ ddexp(0, lambda)  
  }

  lambda ~ dunif(0.001,10)
  # Alternatively, specify lambda via lambda <- 1 or some such
}

Proviamolo usando il dclonepacchetto in R!

library(dclone)

x1 <- rnorm(100)
x2 <- rnorm(100)
x3 <- rnorm(100)

prob <- exp(x1+x2+x3) / (1+exp(x1+x2+x3))
y <- rbinom(100, 1, prob)

data.list <- list(
  y = y,
  x1 = x1, x2 = x2, x3 = x3,
  N = length(y)
)

params = c("b0", "b", "lambda")

temp <- jags.fit(data.list, 
                 params=params, 
                 model="modela.jags",
                 n.chains=3, 
                 n.adapt=1000, 
                 n.update=1000, 
                 thin=10, 
                 n.iter=10000)

Ed ecco i risultati, rispetto a una regressione logistica non regolamentata:

> summary(temp)

<< blah, blah, blah >> 

1. Empirical mean and standard deviation for each variable,
   plus standard error of the mean:

          Mean     SD Naive SE Time-series SE
b[1]   1.21064 0.3279 0.005987       0.005641
b[2]   0.64730 0.3192 0.005827       0.006014
b[3]   1.25340 0.3217 0.005873       0.006357
b0     0.03313 0.2497 0.004558       0.005580
lambda 1.34334 0.7851 0.014333       0.014999

2. Quantiles for each variable: << deleted to save space >>

> summary(glm(y~x1+x2+x3, family="binomial"))

  << blah, blah, blah >>

Coefficients:
            Estimate Std. Error z value Pr(>|z|)    
(Intercept)  0.02784    0.25832   0.108   0.9142    
x1           1.34955    0.32845   4.109 3.98e-05 ***
x2           0.78031    0.32191   2.424   0.0154 *  
x3           1.39065    0.32863   4.232 2.32e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1 

<< more stuff deleted to save space >>

E possiamo vedere che i tre bparametri sono stati effettivamente ridotti a zero.

Non so molto sui priori per l'iperparametro della distribuzione di Laplace / il parametro di regolarizzazione, mi dispiace dirlo. Tendo a usare distribuzioni uniformi e guardo il posteriore per vedere se sembra ragionevolmente ben educato, ad esempio, non ammucchiato vicino a un endpoint e quasi al massimo nel mezzo senza orribili problemi di asimmetria. Finora, in genere è stato così. Considerarlo come un parametro di varianza e usare le raccomandazioni di Gelman Le distribuzioni precedenti per i parametri di varianza nei modelli gerarchici funzionano anche per me.


1
Sei il migliore! Lascerò la domanda aperta per un po 'nel caso in cui qualcuno abbia un'altra implementazione. Per uno, sembra che gli indicatori binari possano essere usati per imporre l'inclusione / esclusione variabile. Ciò compensa il fatto che sotto la selezione del lazo bayesiano non si verifica effettivamente, poiché le beta con il doppio precedente esponenziale non avranno posteriori esattamente zero.
Jack Tanner,

Bene, lo faccio anche io. È simile alla creazione di un precedente con una massa in punti a 0, quindi usando il trucco degli zero per campionare da esso (il precedente in poiBiodiventa quindi una miscela di una massa di punti a 0 e un esponenziale doppio), sebbene il codice sia diverso. Sarò interessato a vedere cosa fanno gli altri, +1 alla domanda.
jbowman,
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.