I’m trying to update some ode Stan code. My updated Stan code looks like this
functions {
vector sir(real t, vector y, real beta, real gamma, array[] int x_i) {
real S = y[1];
real I = y[2];
real R = y[3];
real N = x_i[1];
vector[3] dydt;
dydt[1] = -beta * I * S / N; // dS_dt
dydt[2] = beta * I * S / N - gamma * I; // dI_dt
dydt[3] = gamma * I; // dR_dt
return dydt;
}
}
data {
int<lower=1> n_days;
array[n_days] real t;
vector[3] y0;
int N;
array[n_days] int cases;
}
transformed data {
real t0 = 0;
array[0] real x_r;
array[1] int x_i = { N };
}
parameters {
real<lower=0> beta;
real<lower=0> gamma;
real<lower=0> phi_inv_sqrt;
}
transformed parameters {
real phi = 1. / (square(phi_inv_sqrt));
array[n_days] vector[3] y = ode_rk45(sir, y0, t0, t,
beta, gamma, x_i);
}
model {
beta ~ normal(1.7, 1.4);
gamma ~ normal(0.2, 0.53);
phi_inv_sqrt ~ normal(0, 1);
cases ~ neg_binomial_2(y[ : , 3], phi);
}
generated quantities {
real R0 = beta / gamma;
real recovery_time = 1 / gamma;
array[n_days] real pred_cases;
pred_cases = neg_binomial_2_rng(y[ : , 3], phi);
}
This runs but when I try to fit it I get many of these errors (from cmdstanr):
Chain 2 Informational Message: The current Metropolis proposal is about to be rejected because of the following issue:
Chain 2 Exception: ode_rk45: ode parameters and data is inf, but must be finite! (in ‘C:/…/.stan’, line 40, column 2 to line 41, column 57)
Chain 2 If this warning occurs sporadically, such as for highly constrained variable types like covariance matrices, then the sampler is fine,
Chain 2 but if this warning occurs often then your model may be either severely ill-conditioned or misspecified.
In total I get 185 of 2000 (9.0%) transitions ended with a divergence.
The relevant R code with data is given below.
library(outbreaks) # for dataset
library(rstan)
cases <- influenza_england_1978_school$in_bed
# total count
N <- 763;
# times
n_days <- length(cases)
t <- seq(0, n_days, by = 1)
t <- t[-1]
# initial conditions
i0 <- 1
s0 <- N - i0
r0 <- 0
y0 = c(S = s0, I = i0, R = r0)
# data for Stan
data_sir <- list(n_days = n_days, y0 = y0, t = t, N = N,
cases = cases)
fit_sir_negbin <- sampling(model,
data = data_sir,
seed = 0)
I’m not sure where I messed up when trying to convert syntax of Stan model? I’m using rstan version 2.32.6 / cmdstanr version 2.35.0. I have attached the marginal posteriors I get (compare to posterior at the bottom from old code).
Old stan code
If its any help here is stan code using old syntax which runs fine.
// Code for ODE
functions {
real[] sir(real t, real[] y, real[] theta,
real[] x_r, int[] x_i) {
real S = y[1];
real I = y[2];
real R = y[3];
real N = x_i[1];
real beta = theta[1];
real gamma = theta[2];
real dS_dt = -beta * I * S / N;
real dI_dt = beta * I * S / N - gamma * I;
real dR_dt = gamma * I;
return {dS_dt, dI_dt, dR_dt};
}
}
data {
int<lower=1> n_days;
real y0[3];
real t[n_days];
int N;
int cases[n_days];
}
// Track status of individuals in SIR model in x
transformed data {
real t0 = 0;
real x_r[0];
int x_i[1] = { N };
}
// Truncated prior using <lower=...>
parameters {
real<lower=0> beta;
real<lower=0> gamma;
real<lower=0> phi_inv_sqrt;
}
transformed parameters{
real y[n_days, 3];
real phi = 1. / (square(phi_inv_sqrt));
{
real theta[2];
theta[1] = beta;
theta[2] = gamma;
y = integrate_ode_rk45(sir, y0, t0, t, theta, x_r, x_i);
}
}
model {
//priors
beta ~ normal(1.7, 1.4);
gamma ~ normal(0.2, 0.53);
phi_inv_sqrt ~ normal(0, 1);
// sampling distribution
// col(matrix x, int n) - The n-th column of matrix x.
// Here the number of infected people
cases ~ neg_binomial_2(col(to_matrix(y), 2), phi);
}
// Quantities of interest
generated quantities {
real R0 = beta / gamma;
real recovery_time = 1 / gamma;
real pred_cases[n_days];
pred_cases = neg_binomial_2_rng(col(to_matrix(y), 2), phi);
}
And here is the marginal posteriors I get from this code