Hi,
I have specified a partial_sum function. The model is hierarchical (patients nested within studies), so I have broken up by study.
It seems to work fine if I specify the likelihood as two separate target += partial_sum(…), as in the commented out code below. However, when I pass the partial_sum function through to reduce_sum, compile, and try to run it I get “chain x finished unexpectedly” errors on all chains.
Any advice would be appreciated.
functions {
real partial_sum(int[,,] y, int start, int end, int nt,
real[,,] u_nd,
real[,,] u_d,
vector p,
matrix[] L_Omega_nd,
matrix[] L_Omega_d,
vector[] d,
vector[] nd,
int[] ns) {
int len = end - start + 1;
int r0 = start - 1;
real log_lik;
vector[len] log_lik_s;
for (s in 1:len) { // loop over studies
vector[ns[s+r0]] log_lik_i;
real lp_bern0;
real lp_bern1;
lp_bern0 = bernoulli_lpmf(0 | p[s+r0]);
lp_bern1 = bernoulli_lpmf(1 | p[s+r0]);
for (n in 1:ns[s+r0]) { // loop over individuals
vector[nt] z_d;
vector[nt] z_nd;
vector[nt] y1dz;
vector[nt] y1ndz;
real lp0;
real lp1;
real prev_d;
real prev_nd;
prev_d = 0;
prev_nd = 0;
for (i in 1:nt) { // loop over each test
real bound_d = inv_logit( 1.7* ( -(d[s+r0,i] + prev_d) / L_Omega_d[s+r0,i,i] ));
real bound_nd = inv_logit( 1.7* ( -(nd[s+r0,i] + prev_nd) / L_Omega_nd[s+r0,i,i] ));
if (y[n,i,s] == 1) {
real u_d1 = u_d[n,i,s+r0];
real u_nd1 = u_nd[n,i,s+r0];
z_d[i] = (1/1.7)*logit(bound_d + (1 - bound_d)*u_d1);
z_nd[i] = (1/1.7)*logit(bound_nd + (1 - bound_nd)*u_nd1);
y1dz[i] = log1m(bound_d); // Jacobian adjustment
y1ndz[i] = log1m(bound_nd); // Jacobian adjustment
}
if (y[n,i,s] == 0) {
real u_d1 = u_d[n,i,s+r0];
real u_nd1 = u_nd[n,i,s+r0];
z_d[i] = (1/1.7)*logit(bound_d*u_d1);
z_nd[i] = (1/1.7)*logit(bound_nd*u_nd1);
y1dz[i] = log(bound_d); // Jacobian adjustment
y1ndz[i] = log(bound_nd); // Jacobian adjustment
}
if (i < nt) prev_d = L_Omega_d[s+r0,i +1,1:i ] * head(z_d ,i);
if (i < nt) prev_nd = L_Omega_nd[s+r0,i +1,1:i ] * head(z_nd ,i);
// Jacobian adjustments imply z is truncated standard normal
// thus utility --- mu + L_Omega * z --- is truncated multivariate normal
}
lp1 = sum(y1dz) + lp_bern1;
lp0 = sum(y1ndz) + lp_bern0;
log_lik_i[n] = log_sum_exp(lp1,lp0);
}
log_lik_s[s] = sum(log_lik_i[1:ns[s+r0]]);
}
log_lik = sum(log_lik_s);
return(log_lik);
}
}
data {
int gr;
real x;
real y1;
real y2;
int<lower=1> nt; // number of tests
int<lower=1> NS; // total # of studies
int<lower=1> ns[NS]; // number of individuals in each study
int<lower=0> y[max(ns),nt, NS]; // N individuals and nt tests, NS studies
int r[NS,4]; // data in summary (2x2 tables) format for generated quantities block
}
parameters {
ordered[2] a1_m;
ordered[2] a2_m;
vector<lower=0>[nt] d_sd;
vector<lower=0>[nt] nd_sd;
vector[4] z1[NS];
real<lower=0,upper=1> p[NS];
real<lower=0,upper=1> u_d[max(ns),nt, NS]; // nuisance that absorbs inequality constraints
real<lower=0,upper=1> u_nd[max(ns),nt, NS]; // nuisance that absorbs inequality constraints
cholesky_factor_corr[nt] L_Omega_nd[NS];
cholesky_factor_corr[nt] L_Omega_d[NS];
}
transformed parameters {
vector[nt] d_m;
vector[nt] nd_m;
vector[nt] d[NS];
vector[nt] nd[NS];
vector[NS] y1dz[4,nt];
vector[NS] y1ndz[4,nt];
d_m[1] = a1_m[2];
d_m[2] = a2_m[2];
nd_m[1] = a1_m[1];
nd_m[2] = a2_m[1];
for (s in 1:NS) {
d[s,1] = d_m[1] + d_sd[1]*z1[s,1]*y1;
d[s,2] = d_m[2] + d_sd[2]*z1[s,2]*y2;
nd[s,1] = nd_m[1] + nd_sd[1]*z1[s,3]*y1;
nd[s,2] = nd_m[2] + nd_sd[2]*z1[s,4]*y2;
}
}
model {
// p ~ beta(1,5);
d_sd ~ std_normal();
nd_sd ~ std_normal();
for (s in 1:NS)
z1[s,] ~ std_normal();
for (s in 1:NS) {
L_Omega_nd[s,] ~ lkj_corr_cholesky(x);
L_Omega_d[s,] ~ lkj_corr_cholesky(x); }
// sens
a1_m[2] ~ normal(1, 0.4);
a2_m[2] ~ normal(1, 0.4);
// spec
a1_m[1] ~ normal(-1, 0.4);
a2_m[1] ~ normal(-1, 0.4);
// target += partial_sum( y[, ,1:2], 1, 2, nt, u_nd[,,], u_d[,,], to_vector(p),
// L_Omega_nd[,,], L_Omega_d[,,], d[,], nd[,], ns);
// target += partial_sum( y[, ,3:4], 3, 4, nt, u_nd[,,], u_d[,,], to_vector(p),
// L_Omega_nd[,,], L_Omega_d[,,], d[,], nd[,], ns);
target += reduce_sum(partial_sum, y, gr , nt, u_nd[,,], u_d[,,], to_vector(p),
L_Omega_nd[,,], L_Omega_d[,,], d[,], nd[,], ns);
}
R code :
num ← 15
T1 ← c(1,2,2,2,2,3,2,3,2,2,2,2,1,3,3)
T2 ← rep(4, times = 15)
T ← matrix(c(T1, T2), ncol=2, nrow=15)
r1 ← c(97, 1,20,14,93, 31, 132, 305, 17, 44, 54, 39, 64, 7, 25) ; length(r1) #tp
r2 ← c(20, 0 ,3, 1 ,30 ,6,23,9,19,5,22,4, 0, 4,44) ; length(r2) #fn
r3 ← c(14,9,2,44,183, 3,54,98,31,61,63,536, 612 , 31, 3) ; length(r3) #fp. gs=0. ind=1
r4 ← c(297, 45, 231, 285, 1845, 248, 226, 256, 580, 552, 980, 227, 2051, 98, 170) ; length(r4) # tn, ind=0, gs = 0
ns ← c()
for (i in 1:num) {ns[i] ← r1[i] + r2[i] + r3[i] + r4[i]}
data ← data.frame(r1,r2,r3,r4, ns, t1 = T[,1], t2= T[,2]) #%>% arrange(t1)
r1 ← data$r1 ; r2 ← data$r2 ; r3 ← data$r3 ; r4 ← data$r4
r ← matrix(ncol = 4, nrow = num, c(r1,r2,r3,r4)) ; r
ns ← data$ns
data24 <-list()
pos ← r1+r2
neg ← r3+r4
data24 ← list( r = r, n = ns, NS= num , pos=pos, neg=neg, T=data$t1, num_ref=3, nt=2)
NS=15
sum(ns) # N= 10,968y_list ← list()
y1a ← list(length = max(ns))
y1b ← list(length = max(ns))
pa ← list(length = max(ns))max ← max(ns)
for (i in 1:NS) {
y1a[[i]] = c(rep(1, r[i,1]), rep(1, r[i,2]), rep(0, r[i,3]), rep(0, r[i,4]), rep(2, max - ns[i] ))
y1b[[i]] = c(rep(1, r[i,1]), rep(0, r[i,2]), rep(1, r[i,3]), rep(0, r[i,4]), rep(2, max - ns[i] ))
y_list[[i]] = matrix(ncol = 2, c(y1a[[i]] , y1b[[i]] ))
}y = array(data= unlist(y_list), dim = c( max(ns), 2, NS))
meta_model2 ← mod$sample(
data = list(x=4, y1 = 0, y2=0.6, NS=4, ns=c(ns[c(1:4)]), y=y[1:428,c(1:4)], # first 4 studies
nt = 2, r = r[c(1:4),]),
seed = 123,
chains = 4,
parallel_chains = 4,
iter_warmup = 250,
iter_sampling = 350,
refresh = 12,
adapt_delta = 0.80,
max_treedepth = 10)meta_model2r ← rstan::read_stan_csv(meta_model2$output_files())