glmnet: ¿Cómo dar sentido a la parametrización multinomial?

11

Siguiente problema: Quiero predecir una variable de respuesta categórica con una (o más) variables categóricas usando glmnet ().

Sin embargo, no puedo entender el resultado que me da glmnet.

Ok, primero generemos dos variables categóricas relacionadas:

Generar datos

p <- 2 #number variables
mu <- rep(0,p)
sigma <- matrix(rep(0,p^2), ncol=p)
sigma[1,2] <- .8 #some relationship ..
diag(sigma) <- 1
sigma <- pmax(sigma, t(sigma))
n <- 100
set.seed(1)
library(MASS)
dat <- mvrnorm(n, mu, sigma)
#discretize
k <- 3 # number of categories
d <- apply(dat, 2, function(x) {
  q <- quantile(x, probs=seq(0,1, 1/k))[-c(1, k+1)]
  out <- numeric(length(x))
  for(i in 1:(k-1))
  {  out[x<q[k-i]] <- i } 
  return(out)
})
d <- data.frame(apply(d, 2, as.factor))
d[,2] <- relevel(d[,2], ref="0")
d[,1] <- relevel(d[,1], ref="0")
colnames(d) <- c("X1", "X2")

Obtenemos:

> table(d)
   X2
X1   0  1  2
  0 22 11  1
  1  9 14 10
  2  3  8 22

Predicción: multinom ()

Entonces pronostiquemos X1 por X2 usando el multinom () del paquete nnet:

library(nnet)
mod1 <- multinom(X1~X2, data=d)
mod1

lo que nos da:

Call:
multinom(formula = X1 ~ X2, data = d)

Coefficients:
  (Intercept)      X21      X22
1  -0.8938246 1.134993 3.196476
2  -1.9924124 1.673949 5.083518

Control manual

Ahora verifiquemos si podemos reproducirlo manualmente:

tb <- table(d)
log(tb[2,1] / tb[1,1]) #intercept category1
[1] -0.8938179
log(tb[3,1] / tb[1,1]) #intercept category2
[1] -1.99243
log((tb[1,1]*tb[2,2]) / (tb[1,2]*tb[2,1])) #logodds-ratio cat X1 0vs1 in X2 0vs1
[1] 1.13498
#same for the three remaining log odds ratios

Producimos los mismos números, ¡bien!

Predicción: glmnet ()

Ahora hagamos lo mismo con glmnet:

library(glmnet)
y <- d[,1]
X <- model.matrix(X1~X2, data=d)[,-1]
mod2 <- glmnet(X, y, family="multinomial", lambda=c(0))
coef(mod2, s=0) #meaning of coefficients unclear!
$`0`
3 x 1 sparse Matrix of class "dgCMatrix"
                     1
(Intercept)  0.9620216
X21         -1.1349130
X22         -3.1958293   

$`1`
3 x 1 sparse Matrix of class "dgCMatrix"
                     1
(Intercept) 0.06825755
X21         .         
X22         .         

$`2`
3 x 1 sparse Matrix of class "dgCMatrix"
                     1
(Intercept) -1.0302792
X21          0.5388814
X22          1.8870363

Tenga en cuenta que configuro s = 0, por lo tanto, no hay regularización y los parámetros deben contener exactamente la misma información que los parámetros de la función multinom ().

Aún así, obtenemos parámetros muy diferentes. Esto se debe a la diferente parametrización que usan en glmnet, ver por ejemplo:

http://web.stanford.edu/~hastie/glmnet/glmnet_alpha.html (encabezado: modelos multinomiales) o el documento correspondiente: http://www.jstatsoft.org/v33/i01/paper (encabezado: 4. Regularizado regresión multinomial)

Pero no importa cómo exactamente se parametrice, uno debe obtener la misma , la probabilidad de la categoría k condicional en X.P(Y=k|X)

Probabilidades condicionales: multinom ()

Entonces, primero calculo estas probabilidades a partir de multinom ():

p.fit <- predict(mod1, type="probs")
head(d)
head(p.fit)
ccp <- matrix(0,3,3)
ccp[,3] <- p.fit[1,]
ccp[,2] <- p.fit[2,]
ccp[,1] <- p.fit[4,]
ccp
           [,1]      [,2]       [,3]
[1,] 0.64705896 0.3333332 0.03030114
[2,] 0.26470416 0.4242450 0.30303140
[3,] 0.08823688 0.2424218 0.66666746
colSums(ccp) #sum to 1, ok; sorry for the awful code ...
[1] 1 1 1

Como tenemos un modelo saturado aquí, esto debería ser lo mismo que podemos calcular a partir de los datos:

emp <- table(d)/100
cemp <- apply(emp, 2, function(x) {
  x / sum(x)
})
cemp 
   X2
             0         1          2
  0 0.64705882 0.3333333 0.03030303
  1 0.26470588 0.4242424 0.30303030
  2 0.08823529 0.2424242 0.66666667

que es de hecho el caso.

Probabilidades condicionales: glmnet ()

Ahora lo mismo de glmnet:

c1 <- coef(mod2, s=0)
c <-matrix(rapply(c1, function(x) { as.matrix(x)}, how="unlist"), 3,3, byrow=T)

ccp2 <- matrix(0,3,3)
config <- rbind(c(0,0), c(1,0), c(0,1))

for(l in 1:3) #loop through categories
{
  denom <- numeric(3)
  for(i in 1:3) # loop through possible predictor combinations
  { 
    x1 <- config[i, 1]
    x2 <- config[i, 2]
    denom[i] <- exp(c[l,1] + x1 * c[l,2]  + x2 * c[l,3])
  }
  ccp2[l,1] <- denom[1] / sum(denom)
  ccp2[l,2] <- denom[2] / sum(denom)
  ccp2[l,3] <- denom[3] / sum(denom)
}
ccp2
          [,1]      [,2]       [,3]
[1,] 0.7340082 0.2359470 0.03004484
[2,] 0.3333333 0.3333333 0.33333333
[3,] 0.1073668 0.1840361 0.70859708
colSums(ccp2)
[1] 1.1747083 0.7533165 1.0719753

Las probabilidades condicionales de la celda están algo relacionadas pero son diferentes. Además, no suman uno.

Entonces tenemos dos problemas aquí:

a) las probabilidades condicionales no suman 1 y

b) los parámetros no describen lo que vemos en los datos: por ejemplo, en la fila 2 hay diferencias entre las columnas, pero glmnet estima que ambos coeficientes (no la intersección) son cero.

Utilicé un problema de regresión lineal y comparé glm y glmnet con s = 0 para asegurarme de que s = 0 significa cero regularización (las soluciones eran casi idénticas).

Cualquier ayuda e ideas serán muy apreciadas!

jmb
fuente

Respuestas:

5

Acerca de los parámetros de multinom y glmnet, esta respuesta me pareció beneficiosa. ¿Puedo usar algoritmos glm para hacer una regresión logística multinomial?

especialmente, "Sí, con un Poisson GLM (modelo lineal de registro) puede ajustar modelos multinomiales. Por lo tanto, los modelos logísticos multinomiales o log lineales de Poisson son equivalentes".

Entonces mostraré la reparametrización de los coeficientes glmnet a coeficientes multinom.

n.subj=1000
x1 <- rnorm(n.subj)
x2 <- rnorm(n.subj)
prob <- matrix(c(rep(1,n.subj), exp(3+2*x1+x2), exp(-1+x1-3*x2)), , ncol=3)
prob <- sweep(prob, 1, apply(prob, 1, sum), "/")

y = c()
for (i in 1:n.subj)
  y[i] <- sample(3, 1, replace = T, prob = prob[i,])

multinom(y~x1+x2)

x <- cbind(x1,x2); y2 <- factor(y)
fit <- glmnet(x, y2, family="multinomial", lambda=0, type.multinomial =     "grouped")
cf <- coef(fit)

cf[[2]]@x - cf[[1]]@x   # for the category 2
cf[[3]]@x - cf[[1]]@x   # for the category 3

Espero que esto ayude. Pero no creo entender la equivalencia del modelo lineal generalizado (Poisson) y el modelo logístico multinomial dentro y fuera.

Dime si hay una fuente buena, legible y "fácilmente" comprensible.

KH Kim
fuente
1
¿Tiene alguna explicación adicional para "por qué" este es el caso? Es decir, por qué el glment produce coeficientes que son una combinación de los coeficientes multinomiales más típicos y los coeficientes 'base'. ¿Esto nos permite interpretar cada conjunto de coeficientes como un modelo log-lineal ?
samplesize1