Rstanarm stan_lmer making implicit prior_intercept explicit no longer centers it?

Hi all,

I’m currently using rstanarm::stan_lmer to fit a model, and I’m abiding by the the guidance to state the priors explicitly, even if I’m going to use the default priors. Somehow I’m not getting prior_intercept correct, though. If I leave it implicit, then it gets centered where it should be. If I use prior_intercept = normal(location = 0, scale= 2.5, autoscale=TRUE) , then the prior_intercept remains centered at 0. Is there something wrong with the way I’m specifying the prior_intercept in the code?
Thanks

Operating system: Windows 10
R version: 4.0.3
rstanarm version: 2.21.1

# Operating system: Windows 10
# R version: 4.0.3
# rstanarm version: 2.21.1

library(rstanarm)  # 2.21.1

# create dataset
set.seed(123)
s_levels <- 1:5
m_levels <- c("A", "B", "C")  # three years
v_levels <- c("L2", "L3", "L4") # three fields per year
reps <- 1:3
df <- expand.grid(s=s_levels, m=m_levels, v=v_levels, rep=reps)
df$y <- 10 + as.numeric(as.factor(df$v))*0.5 + rnorm(nrow(df), mean=0, sd=0.1)
df$subunit <- as.factor(paste(df$v,"-",df$m,"-",df$s, sep=""))

# default priors
mod_stanlmer_implicit_priors <- stan_lmer(
  formula = y ~ 1 + v + m + s + m:s + (1|subunit),
  data=df)

# the default priors stated explicitly, except for prior_covariance
mod_stanlmer <- stan_lmer(
  formula = y ~ 1 + v + m + s + m:s + (1|subunit) ,
  prior_intercept = normal(location = 0, scale= 2.5, autoscale=TRUE) ,
  prior = normal(location = 0, scale= 2.5, autoscale=TRUE) ,
  prior_aux = exponential(rate=1, autoscale=TRUE) ,
  data=df)

posterior_vs_prior(
  object = mod_stanlmer_implicit_priors ,
  pars=c("(Intercept)", "s", "v", "m")
)

posterior_vs_prior(
  object = mod_stanlmer ,
  pars=c("(Intercept)", "s", "v", "m")
)

prior_summary(mod_stanlmer_implicit_priors) # adjusted prior location = 11
prior_summary(mod_stanlmer) # adjusted prior location = 0

# how do I extract just the prior samples from the fits?

# Plotting the model, though getting a warning:
# "Note: uncertainty of error terms are not taken into account. You may want to
# use `rstantools::posterior_predict()`."

library(ggplot2)
library(sjPlot)

ggplot(data = df ,
       aes(x = s, y = y)) +
  geom_point () + 
  facet_wrap( ~ v + m)

plot_model(
  model = mod_stanlmer_implicit_priors ,
  type="pred" ,
  terms=c("s", "m", "v") ,
  ci.lvl = 0.95
)

The issue shows up in both prior_summary() and posterior_vs_prior()

1 Like

So, is this considered an appropriate syntax for setting prior_intercept? If it is, then I don’t see how this isn’t a bug in rstanarm. Right?

# the default priors stated explicitly, except for prior_covariance
mod_stanlmer <- stan_lmer(
  formula = y ~ 1 + v + m + s + m:s + (1|subunit) ,
  prior_intercept = normal(location = 0, scale= 2.5, autoscale=TRUE) ,
  prior = normal(location = 0, scale= 2.5, autoscale=TRUE) ,
  prior_aux = exponential(rate=1, autoscale=TRUE) ,
  data=df)
1 Like

Can’t rule out a bug unfortunately. Tagging @jonah as he is more involved with rstanarm.

1 Like

Thanks Martin, I had missed this question. @MichiganWater sorry nobody responded sooner!

@MichiganWater At first glance I don’t think this is a bug but rather the issue is that the default prior on the intercept (edit: with X centered internally, so intercept is interpreted as E(y|x=xbar) rather than x=0) for gaussian models with identity link isn’t actually centered at 0 but rather at mean(y). Here’s more info on the current defaults:

This change was made in one of the recent releases so that rstanarm was in line with the new book Regression and Other Stories by @andrewgelman @avehtari and Jennifer Hill (and there should be a message when rstanarm is loaded that default priors changed and to check the vignette I linked to). Do we still have it documented somewhere that it is centered at 0? We may have unfortunately missed a spot when we were making the changes.

(Potential changes to the default priors are one reason we recommend explicitly specifying them, so I’m glad you’re trying to do that!).

I’m not familiar with this warning (it’s not coming from rstanarm itself), so I’m guessing this is coming from the sjPlot package you’re using.

2 Likes

Right, when the default prior_intercept is used, it’s centered at mean(y). That’s good. However, when I try to explicitly define prior_intercept to match the (implied) default, that’s when prior_intercept no longer centers at mean(y), but now centers at 0 instead, even though I used autoscale=TRUE.

I guess I was incorrectly assuming that using autoscale=TRUE would still keep the location centered at mean(y), but it doesn’t. That makes sense, in hindsight, because it’s autoscale=TRUE, not autoscale_and_autolocation=TRUE. Oops. Well, glad I can laugh at myself.

So, to be sure, to replicate the behavior of the implied default, I should do this, correct?

prior_intercept = normal(location = mean(y), scale= 2.5, autoscale=TRUE)

Edit: Oh, right, the “#Note:…” at the bottom was just an unrelated piece of code.

1 Like

Yeah it rescales but doesn’t relocate, so to speak. There’s lots of info to keep track of though so it’s easy to get confused by this stuff. Happens to me all the time, even with the packages I develop!

Yeah that looks right! I think if you change it to that the posterior vs prior plots you made should look similar for both models.

2 Likes

I tried it, and you are correct, that does change the location and the posterior vs prior plots now look the same. Thanks for all your help.

2 Likes