I think I solved it:
So annoyingly, while tighter priors like lognormal(0,1) do a bit better, I still got low E-BFMI warnings and very low ESS for my variance parameters sigma and tau - so the problem really seemed to be something inherent to the model. Simpler models such as the one I copied from here worked fine, until x_obs and y_obs get separate variances. I realized that with the data given, the two variance components of the model remain unidentifiable unless I give them very different scales and very different priors to go with those scales (see here).
I validated this by changing to a repeated measures design, which instantly fixes it as tau can now be estimated from the data:
N <- 100
reps <- 3
sigma <- 0.5
tau <- 0.3
alpha <- 1.3
beta <- -0.4
# true covariate values
x <- runif(n, -3, 3)
#repeatedly sampling true x
idxs <- rep(1:n,each=reps)
x_obs <- rnorm(idxs, x[idxs], tau)
y <- rnorm(idxs, alpha + beta*x[idxs], sigma)
and the model:
data {
int<lower=0> N;
int<lower=0> reps;
vector[N*reps] x_obs;
vector[N*reps] y;
array[N*reps] int<lower=0,upper=N> idxs;
}
parameters {
vector[N] x;
real alpha;
real beta;
real<lower=0> sigma;
real<lower=0> tau;
}
model {
//priors
alpha ~ normal(0, 5);
beta ~ normal(0, 5);
sigma ~ lognormal(0,1);
tau ~ lognormal(0,1);
x ~ normal(0,5);
//likelihood
for(i in 1:N*reps){
x_obs[i] ~ normal(x[idxs[i]],tau);
y[i] ~ normal(alpha + beta * x[idxs[i]], sigma);
}
}
In hindsight, I missed that tau is data, not a parameter, in the example here.
Solved thanks to the forum history!