Nonlinear syntax with a multinomial model?

Is it possible to use the non-linear syntax to fit a multinomial model? Here’s an example of a simple intercepts-only model for a 3-category response variable that works fine with conventional brms syntax.

library(brms)

dat <- data.frame(y = rep(letters[1:3], times = 100))

fit_1 <-
  brm(data = dat, 
      family = categorical(link = logit),
      y ~ 1,
      prior = c(prior(normal(0, 1), class = Intercept, dpar = mub),
                prior(normal(0, 1), class = Intercept, dpar = muc))) 

I’d like to fit to fit the same model using the nonlinear syntax. My first naïve attempt is incorrect in that it returns a single intercept.

fit_2 <-
  brm(data = dat, 
      family = categorical(link = logit),
      bf(y ~ a,
         a ~ 1,
         nl = TRUE),
      prior(normal(0, 1), class = b, nlpar = a)) 

My second naïve attempt is rejected by brms out of hand.

fit_3 <-
  brm(data = dat, 
      family = categorical(link = logit),
      bf(y ~ a,
         a ~ 1,
         nl = TRUE),
      prior = c(prior(normal(0, 1), class = b, dpar = mub, nlpar = a),
                prior(normal(0, 1), class = b, dpar = muc, nlpar = a))) 

All I get from this is an error:

Error: The following priors do not correspond to any model parameter: 
b_mub_a ~ normal(0, 1)
b_muc_a ~ normal(0, 1)
Function 'get_prior' might be helpful to you.

Is there a way to mix the nonlinear syntax with family = categorical?

Perhaps the models I discuss in https://github.com/paul-buerkner/brms/issues/560 could be helpful to you.

1 Like

Thanks for the nudge, @paul.buerkner. I think I have it. For the sake of continuity, I’m going to switch to the Fishing data used in GitHub issue #560. For anyone else following, that example was based on a conditional logistic model, which I’m not totally up on but I believe is an alternative parameterization of what I’m calling the multinomial model. Anyway, the code below fits an intercepts-only multinomial model for the 4-category response variable mode. In this example, the reference category will be "boat". I’ll show how to fit the model with three styles of syntax, what I’m going to call

  • the conventional syntax (fish1a),
  • the verbose syntax (fish1b), and
  • the nonlinear syntax (fish1c).
library(brms)
data("Fishing", package = "mlogit")

# conventional syntax
fish1a <-
  brm(data = Fishing, 
      family = categorical(link = logit, refcat = "boat"),
      mode ~ 1,
      prior = c(prior(normal(0, 1), class = Intercept, dpar = mubeach),
                prior(normal(0, 1), class = Intercept, dpar = mucharter),
                prior(normal(0, 1), class = Intercept, dpar = mupier)))

# verbose syntax
fish1b <-
  brm(data = Fishing, 
      family = categorical(link = logit, refcat = "boat"),
      bf(mode ~ 1,
         mubeach ~ 1,
         mucharter ~ 1,
         mupier ~ 1),
      prior = c(prior(normal(0, 1), class = Intercept, dpar = mubeach),
                prior(normal(0, 1), class = Intercept, dpar = mucharter),
                prior(normal(0, 1), class = Intercept, dpar = mupier)))

# nonlinear syntax 
fish1c <-
  brm(data = Fishing, 
      family = categorical(link = logit, refcat = "boat"),
      bf(mode ~ 1,
         nlf(mubeach ~ abeach),
         nlf(mucharter ~ acharter),
         nlf(mupier ~ apier),
         abeach + acharter + apier ~ 1),
      prior = c(prior(normal(0, 1), class = b, nlpar = abeach),
                prior(normal(0, 1), class = b, nlpar = acharter),
                prior(normal(0, 1), class = b, nlpar = apier)))

The results are the same for all.

                    Estimate Est.Error  Q2.5 Q97.5
mubeach_Intercept      -1.13      0.10 -1.32 -0.94
mupier_Intercept       -0.85      0.09 -1.02 -0.67
mucharter_Intercept     0.08      0.07 -0.05  0.21
                    Estimate Est.Error  Q2.5 Q97.5
mubeach_Intercept      -1.13      0.10 -1.32 -0.94
mupier_Intercept       -0.85      0.09 -1.02 -0.67
mucharter_Intercept     0.08      0.07 -0.05  0.21
                   Estimate Est.Error  Q2.5 Q97.5
abeach_Intercept      -1.13      0.10 -1.33 -0.94
acharter_Intercept     0.08      0.07 -0.04  0.22
apier_Intercept       -0.85      0.09 -1.02 -0.68