Hello all. I am trying to fit a nonlinear model specified as follows:
y = d + \frac{1-d}{1+\exp(-b(\log(x) - \log(c)))}
which is the 3-parameter log-logistic function for a curve with an upper limit of 1, a lower limit of d, an inflection point of c, and a slope of b. I have placed the following priors:
d\sim \mathcal{N}(0, 0.5) \\
\log(c)\sim \mathcal{N}(0, 5) \\
b\sim \mathcal{N}(0, 20)
where d\in(0, 1) and b\in\mathbb{R}_{\le 0}, enforcing decreasing curves.
In Stan, I have written:
data {
int<lower=1> N;
vector[N] log_x;
vector<lower=0>[N] y;
}
parameters {
real<lower=0, upper=1> d;
real log_c;
real<upper=0> b;
real<lower=0> sigma;
}
model {
d ~ normal(0, 0.5);
log_c ~ normal(0, 5);
b ~ normal(0, 20);
sigma ~ normal(0, 1);
vector[N] mu;
for (i in 1:N) {
mu[i] = d + (1 - d) * inv_logit(b*(log_x[i] - log_c));
}
y ~ normal(mu, sigma);
}
Testing this model, I have simulated data in R that are similar to one of my use cases:
# Simulated data
set.seed(1)
sigmoid_fxn <- function(log_x, d, log_c, b) d + (1 - d) / (1 + exp(-b*(log_x - log_c)))
data <- data.frame(x = rep(10 / 3^(7:0), each = 3))
data["log_x"] <- log(data$x)
data["y"] <- sigmoid_fxn(data[["log_x"]], 0.1, log(5), -10)
data["y"] <- data["y"] + (runif(3 * length(data["y"])) * 0.1 - 0.05)
# Model fit
library(rstan)
fit <- stan(file = "sigmoid.stan",
data = list(N = dim(data)[1],
log_x = data[["log_x"]],
y = data[["y"]]),
control = list(adapt_delta = 0.95),
chains = 4, cores = 4, iter = 10000, seed = 1)
Which fails even with adapt_delta increased to 0.95.
Warning messages:
1: There were 225 divergent transitions after warmup. See
https://mc-stan.org/misc/warnings.html#divergent-transitions-after-warmup
to find out why this is a problem and how to eliminate them.
2: Examine the pairs() plot to diagnose sampling problems
Examining the pairs plot of the unconstrained variables suggests a problem:
library(bayesplot)
color_scheme_set("darkgray")
np <- nuts_params(fit)
mcmc_pairs(fit, pars = c("d", "log_c", "b", "sigma"), np = np,
transformations = list(d = \(d) log(d / (1 - d)),
b = \(b) log(-b),
sigma = log))
It seems to me that the problem is centered on the narrow tip of the lower bound d. However, I am not sure how to move forward from here to solve this problem. Is there a reparameterization I can try to fix this problem, or another technique that I can use? I would appreciate any advice that you have–thank you.