Hi all,
I’m trying to fit a basic version of a more complex model and am running into trouble constraining a (pair of) parameter(s) in the model. The R script I’m using is:
library(rstan)
library(ggplot2)
true_fun = function(a_1, a_2, tau, gamma, x){
lambda = numeric(length(x))
lambda[x <= gamma] = exp(a_1 * (gamma - x[x <= gamma]) ^ 2 + tau)
lambda[x > gamma] = exp(a_2 * (x[x > gamma] - gamma) ^ 2 + tau)
y = rpois(length(x), lambda)
}
a_1 = -0.05
a_2 = -0.001
gamma = 15
tau = 3
set.seed(1)
df = c()
n_obs = 5
for(i in seq_len(n_obs)){
x = 1:100
y = true_fun(a_1, a_2, tau, gamma, x)
df = rbind(df, data.frame(x = x, y = y, obs = rep(i, length(x))))
}
ggplot(df, aes(x = x, y = y, color = as.factor(obs))) + geom_point()
stan_d <- list(y = df$y,
x = df$x,
n = nrow(df))
set.seed(2)
minit1 <- stan("Code/model.stan",
data = stan_d,
chains = 1,
iter = 2)
set.seed(3)
mfit1 <- stan(fit = minit1,
iter = 1250,
warmup = 250,
data = stan_d,
chains = 4,
cores = 4)
plot(mfit1, pars = c('alpha', 'tau', 'gamma'))
traceplot(mfit1, pars = c('alpha', 'tau', 'gamma'))
where model.stan is:
data {
int<lower = 1> n;
vector[n] x;
int<lower = 0> y[n];
}
parameters {
real alpha[2];
real<lower = 0> tau;
real<lower = 0> gamma;
}
transformed parameters {
real<lower = 0> mu[n];
vector[n] ID; // indicator variable for whether x_i < gamma
for(i in 1:n){
if (x[i] <= gamma) {
ID[i] = 1;
} else {
ID[i] = 0;
}
mu[i] = exp((alpha[1] * (gamma - x[i]) ^ 2 + tau) * ID[i] + (alpha[2] * (x[i] - gamma) ^ 2 + tau) * (1 - ID[i]));
}
}
model {
alpha ~ normal(0, 1);
gamma ~ uniform(2, 99); //fixed to 2nd and (n-1)th (ordered) observations of x
tau ~ normal(0, 1);
y ~ poisson(mu);
}
The example data is being simulated under the assumed data generating mechanism. For this particular model, it only makes sense for alpha to be negative. Unfortunately, when I try to constrain it either via
real<upper = 0> alpha[2];
or
real<lower = 0> alpha[2];
and changing
mu[i] = exp((-alpha[1] * (gamma - x[i]) ^ 2 + tau) * ID[i] + (-alpha[2] * (x[i] - gamma) ^ 2 + tau) * (1 - ID[i]));
I’m struck with the “Initialization between (-2, 2) failed after 100 attempts.” error. Additionally, adding an appropriate init argument does not resolve the issue (as expected). If you actually fit the model with unconstrained alpha per the code above and examine the traceplots, 3 of the chains appear to converge quickly to the expected values, while the fourth chain is doomed to non-sense due to positive values for alpha. I don’t quite understand why adding such a seemingly simple constraint to this model is completely breaking it. Any input would be greatly appreciated!
Thank you!
EDIT: (Steve) fixed code formatting