Thanks @Bob_Carpenter
I’m fitting a hierarchical piecewise spline model with subject-specific (random) change points. The outcome is a pain score measured repeatedly over time for each individual. The time variable is denoted C_1, and the change points are the parameters b_t1,...,b_t6,, which are constrained to lie within certain bounds.
Below are my current parameters and transformed parameters blocks. The model code was generated using brms, which manually adds truncated-normal log densities to lprior for the bounded change-point parameters b_t1,...,b_t6. Do I need to add any additional Jacobian adjustments for these bounded btb_tbt parameters? Key points about my setup:
-
The b_t1,...,b_t6 parameters are declared directly as bounded parameters (with data- and parameter-dependent bounds), not as nonlinear transforms of other parameters.
-
brms is already assigning truncated-normal priors to them via explicit log-density terms in lprior.
-
I do not apply any further nonlinear transformation to b_t1,...,b_t6 before using them in the likelihood.
Given this, is the current truncated-normal implementation sufficient, or is an extra Jacobian adjustment still required? I’d appreciate guidance on that as well.
Thanks
parameters {
vector[K_cons] b_cons; // regression coefficients
vector[K_s1] b_s1; // regression coefficients
vector[K_s2] b_s2; // regression coefficients
vector[K_s3] b_s3; // regression coefficients
vector[K_s4] b_s4; // regression coefficients
vector[K_s5] b_s5; // regression coefficients
vector[K_s6] b_s6; // regression coefficients
vector[K_s7] b_s7; // regression coefficients
vector<lower=min(C_1),upper=max(C_1)>[K_t1] b_t1; // regression coefficients
vector<lower=min(C_1) + b_t1,upper=max(C_1)>[K_t2] b_t2; // regression coefficients
vector<lower=min(C_1) + b_t2,upper=max(C_1)>[K_t3] b_t3; // regression coefficients
vector<lower=min(C_1) + b_t3,upper=max(C_1)>[K_t4] b_t4; // regression coefficients
vector<lower=min(C_1) + b_t4,upper=max(C_1)>[K_t5] b_t5; // regression coefficients
vector<lower=min(C_1) + b_t5,upper=max(C_1)>[K_t6] b_t6; // regression coefficients
real<lower=0> sigma; // dispersion parameter
vector<lower=0>[M_1] sd_1; // group-level standard deviations
matrix[M_1, N_1] z_1; // standardized group-level effects
cholesky_factor_corr[M_1] L_1; // cholesky factor of correlation matrix
}
transformed parameters {
matrix[N_1, M_1] r_1; // actual group-level effects
// using vectors speeds up indexing in loops
vector[N_1] r_1_cons_1;
vector[N_1] r_1_s1_2;
vector[N_1] r_1_s2_3;
vector[N_1] r_1_s3_4;
vector[N_1] r_1_s4_5;
vector[N_1] r_1_s5_6;
vector[N_1] r_1_s6_7;
vector[N_1] r_1_s7_8;
vector[N_1] r_1_t1_9;
vector[N_1] r_1_t2_10;
vector[N_1] r_1_t3_11;
vector[N_1] r_1_t4_12;
vector[N_1] r_1_t5_13;
vector[N_1] r_1_t6_14;
// prior contributions to the log posterior
real lprior = 0;
// compute actual group-level effects
r_1 = scale_r_cor(z_1, sd_1, L_1);
r_1_cons_1 = r_1[, 1];
r_1_s1_2 = r_1[, 2];
r_1_s2_3 = r_1[, 3];
r_1_s3_4 = r_1[, 4];
r_1_s4_5 = r_1[, 5];
r_1_s5_6 = r_1[, 6];
r_1_s6_7 = r_1[, 7];
r_1_s7_8 = r_1[, 8];
r_1_t1_9 = r_1[, 9];
r_1_t2_10 = r_1[, 10];
r_1_t3_11 = r_1[, 11];
r_1_t4_12 = r_1[, 12];
r_1_t5_13 = r_1[, 13];
r_1_t6_14 = r_1[, 14];
lprior += normal_lpdf(b_cons | 0, 1);
lprior += normal_lpdf(b_s1 | 0, 5);
lprior += normal_lpdf(b_s2 | 0, 5);
lprior += normal_lpdf(b_s3 | 0, 5);
lprior += normal_lpdf(b_s4 | 0, 5);
lprior += normal_lpdf(b_s5 | 0, 5);
lprior += normal_lpdf(b_s6 | 0, 5);
lprior += normal_lpdf(b_s7 | 0, 5);
lprior += normal_lpdf(b_t1 | 0, 5)
- 1 * log_diff_exp(normal_lcdf(max(C_1) | 0, 5), normal_lcdf(min(C_1) | 0, 5));
lprior += normal_lpdf(b_t2 | 0, 5)
- 1 * log_diff_exp(normal_lcdf(max(C_1) | 0, 5), normal_lcdf(min(C_1) + b_t1 | 0, 5));
lprior += normal_lpdf(b_t3 | 0, 5)
- 1 * log_diff_exp(normal_lcdf(max(C_1) | 0, 5), normal_lcdf(min(C_1) + b_t2 | 0, 5));
lprior += normal_lpdf(b_t4 | 0, 5)
- 1 * log_diff_exp(normal_lcdf(max(C_1) | 0, 5), normal_lcdf(min(C_1) + b_t3 | 0, 5));
lprior += normal_lpdf(b_t5 | 0, 5)
- 1 * log_diff_exp(normal_lcdf(max(C_1) | 0, 5), normal_lcdf(min(C_1) + b_t4 | 0, 5));
lprior += normal_lpdf(b_t6 | 0, 5)
- 1 * log_diff_exp(normal_lcdf(max(C_1) | 0, 5), normal_lcdf(min(C_1) + b_t5 | 0, 5));
lprior += student_t_lpdf(sigma | 3, 0, 11.9)
- 1 * student_t_lccdf(0 | 3, 0, 11.9);
lprior += normal_lpdf(sd_1[1] | 0, 1)
- 1 * normal_lccdf(0 | 0, 1);
lprior += normal_lpdf(sd_1[2] | 0, 2)
- 1 * normal_lccdf(0 | 0, 2);
lprior += normal_lpdf(sd_1[3] | 0, 2)
- 1 * normal_lccdf(0 | 0, 2);
lprior += normal_lpdf(sd_1[4] | 0, 2)
- 1 * normal_lccdf(0 | 0, 2);
lprior += normal_lpdf(sd_1[5] | 0, 2)
- 1 * normal_lccdf(0 | 0, 2);
lprior += normal_lpdf(sd_1[6] | 0, 2)
- 1 * normal_lccdf(0 | 0, 2);
lprior += normal_lpdf(sd_1[7] | 0, 2)
- 1 * normal_lccdf(0 | 0, 2);
lprior += normal_lpdf(sd_1[8] | 0, 2)
- 1 * normal_lccdf(0 | 0, 2);
lprior += normal_lpdf(sd_1[9] | 0, 5)
- 1 * normal_lccdf(0 | 0, 5);
lprior += normal_lpdf(sd_1[10] | 0, 5)
- 1 * normal_lccdf(0 | 0, 5);
lprior += normal_lpdf(sd_1[11] | 0, 5)
- 1 * normal_lccdf(0 | 0, 5);
lprior += normal_lpdf(sd_1[12] | 0, 5)
- 1 * normal_lccdf(0 | 0, 5);
lprior += normal_lpdf(sd_1[13] | 0, 5)
- 1 * normal_lccdf(0 | 0, 5);
lprior += normal_lpdf(sd_1[14] | 0, 5)
- 1 * normal_lccdf(0 | 0, 5);
lprior += lkj_corr_cholesky_lpdf(L_1 | 1);
}