Multinomial Logit
<- function(data, formula) {
mnlogit
<- model.frame(formula, data, na.action=na.exclude)
mf <- model.response(mf)
y <- model.matrix(formula, mf)
X
<- nrow(X)
N <- ncol(X)
K <- unique(y) |> sort()
levels <- length(levels)
M
<- matrix(N*M, nrow=N, ncol=M)
Y for (m in 1:M) {
<- ifelse(y==levels[m], 1, 0)
Y[,m]
}<- numeric(K*(M-1))
b
<- function(param) {
mnlogitLL
<- matrix(param, nrow=K, ncol=M-1)
b <- cbind(rep(0, N), X %*% b)
Xb <- numeric(N)
lli
for (m in 1:M) {
<- lli + Y[,m]*Xb[,m] - Y[,m]*log(rowSums(exp(Xb)))
lli
}
return(-sum(lli))
}
<- optim(b, mnlogitLL, method="BFGS")
out <- matrix(out$par, nrow=K, ncol=M-1)
est rownames(est) <- colnames(X)
colnames(est) <- paste0(levels[1], "/", levels[2:M])
return(est)
}
Testing the function:
library(mclogit)
## Loading required package: Matrix
<- MASS::housing #has an ordinal outcome but we'll ignore that for our purposes
housing <- Sat ~ Infl + Freq + Type
f
t(mblogit(f, data = housing)$coefmat)
##
## Iteration 1 - deviance = 150.7444 - criterion = 0.5116897
## Iteration 2 - deviance = 150.511 - criterion = 0.001549817
## Iteration 3 - deviance = 150.5107 - criterion = 1.965799e-06
## Iteration 4 - deviance = 150.5107 - criterion = 3.804011e-12
## converged
## Response categories
## Predictors Medium High
## (Intercept) 1.1352190 -0.740346318
## InflMedium 0.1291512 0.005033149
## InflHigh -0.4256812 0.282489556
## Freq -0.0501481 0.026990219
## TypeApartment 0.8092387 -0.644372087
## TypeAtrium -0.4053420 0.264568900
## TypeTerrace -0.3689781 0.189799430
mnlogit(housing, f)
## Low/Medium Low/High
## (Intercept) 1.13582927 -0.740243313
## InflMedium 0.12920635 0.005028019
## InflHigh -0.42591879 0.282447109
## Freq -0.05017388 0.026985033
## TypeApartment 0.80963960 -0.644298089
## TypeAtrium -0.40569533 0.264391915
## TypeTerrace -0.36904115 0.189905490