The relevant formula for glmnet can be found at
Trevor Hastie's website
Scroll down to the section on multinomial models.
The probability for each class is just the sum of the coefficients times
the covariates, exponentiated, and normalized by the sum of that thing
for all classes. What are the probabilities for an average size setosa?
Get the mean length and width, and add a 1 for the intercept
meansetosa <- iris %>% group_by(Species) %>%
summarize(msl = mean(Sepal.Length), msw = mean(Sepal.Width)) %>%
select(-1) %>% slice(1) %>% c(1., ., recursive = TRUE)
# matrix multiply to get the vector of numerators
numerators <- cf.glmnet2 %*% meansetosa
numerators <- exp(numerators)
p <- numerators / sum(numerators)
As expected, the probability for setosa is very high, and the other two
are very low. Which is exactly what the predict method gives us.
predict(mod.glmnet, newx = matrix(meansetosa[2:3], nrow=1), type = "response")
#> , , s0
#>
#> setosa versicolor virginica
#> [1,] 0.9999992 6.958413e-07 8.245742e-08
For nnet, we do the same thing, but insert a row of 0 for the reference class coefficients.
cf.nnet2 <- matrix(c(0,0,0, t(cf.nnet)), nrow=3, byrow = TRUE)
numerators <- cf.nnet2 %*% meansetosa
numerators <- exp(numerators)
p <- numerators / sum(numerators)
p
#> [,1]
#> [1,] 1.000000e+00
#> [2,] 2.609031e-13
#> [3,] 3.093541e-14
predict(mod.nnet, newdata = data.frame(Sepal.Length = 5.006, Sepal.Width = 3.428), type = "prob")
#> setosa versicolor virginica
#> 1.000000e+00 2.609031e-13 3.093541e-14
So nnet is doing the same thing, but insert 0 for the coefficients in the reference case.
Created on 2020-02-07 by the reprex package (v0.2.1)