I am trying to convert a latent variable model from BUGS code to Stan. The model runs in BUGS however I am sampling directly from a latent discrete variable D1[i]. I know that to do this in Stan you need to marginalise out the discrete latent variable and cannot sample this directly as the code below attempts to do.
I was wondering if anybody had any idea of how to code this up? I have seen some examples on marginalising but still cannot figure it out.
The data is:
res1 <- c(rep(1, 262), rep(2, 24), rep(3, 26))
res2 <- c(rep(1, 183), rep(2, 61), rep(3, 18), rep(1, 13), rep(2, 5),
rep(3, 6), rep(1, 3), rep(2, 4), rep(3, 19))
res3 <- c(rep(1, 181), rep(2, 1), rep(3, 1), rep(1, 56), rep(2, 5),
rep(1,16), rep(2, 1), rep(3, 1), rep(1, 10), rep(3, 3),
rep(1, 5), rep(1, 2), rep(2, 2), rep(3, 2),
rep(1,1), rep(2, 2), rep(3, 4), rep(2, 1), rep(3, 18))
data = list(res1=res1, res2=res2, res3=res3, N = 312, nt=3)
Code: (need to marginalise out the D1[i])
data {
int<lower=0> nt; // # of diagnostic tests
int<lower=0> N; // # of subjects
int res1[N]; // results of test 1
int res2[N]; // results of test 2
int res3[N]; // results of test 3
}
parameters {
vector<lower = 0>[nt] a11;
vector<lower = 0>[nt] a10;
vector<lower = 0>[nt] c11;
vector<lower = 0>[nt] c10;
vector[nt] b0;
vector[nt] b1;
vector[N] t;
int<lower=0,upper=1> D1[N];
real<lower=0,upper=1> p;
}
transformed parameters {
vector[nt] b11;
vector[nt] b10;
vector<lower=0,upper=1>[nt] Se;
vector<lower=0,upper=1>[nt] Sp;
vector<lower=0,upper=1>[nt] int_d;
vector<lower=0,upper=1>[nt] int_nd;
real<lower=1,upper=2> D[N];
real<lower=0,upper=1> p1[nt,N,2,3];
real<lower=0,upper=1> probs[nt,N,3];
for (j in 1:nt) {
b11[j] = 0;
b10[j] = 0;
Se[j] = 1-Phi( c11[j] - a11[j] );
int_d[j] = Phi( c11[j] - a11[j] ) - Phi( b11[j] - a11[j] );
int_nd[j] = Phi( c10[j] - a10[j] ) - Phi( b10[j] - a10[j] );
Sp[j] = Phi( b10[j] - a10[j] );
for (i in 1:N) {
// diseased
p1[j,i,2,1] = Phi(b11[j] - a11[j]) ;
p1[j,i,2,2] = Phi(c11[j] - a11[j] ) - Phi(b11[j] - a11[j]) ;
p1[j,i,2,3] = 1-Phi(c11[j] - a11[j] ) ;
// non-diseased
p1[j,i,1,1] = Phi(b10[j] - a10[j]) ;
p1[j,i,1,2] = Phi(c10[j] - a10[j]) - Phi(b10[j] - a10[j]) ;
p1[j,i,1,3] = 1-Phi(c10[j] - a10[j] ) ;
probs[j,i,1] = p1[j,i,D[i],1];
probs[j,i,2] = p1[j,i,D[i],2];
probs[j,i,3] = p1[j,i,D[i],3];
D[i]<-D1[i]+1;
}
}
}
model {
p~uniform(0,1) ;
for (j in 1:nt) {
a11[j] ~normal(0,1);
a10[j] ~normal(0,1);
c11[j] ~normal(0,1);
c10[j] ~normal(0,1);
for (i in 1:N) {
D1[i] ~ bernoulli(p)
res1[i]~categorical(probs[1,i,1:3]) ;
res2[i]~categorical(probs[2,i,1:3]) ;
res3[i]~categorical(probs[3,i,1:3]) ;
}
}
Background: The model and data are the probit latent class model (assuming conditional dependence between tests) described in Xu et al (doi: 10.1002/sim.5695). I wrote the model in BUGS first, by extending some code I had for a simpler version, where each test has dichotomous results rather than three categories as is the case here (this model: https://pubmed.ncbi.nlm.nih.gov/8805757/).