Unable to constrain a transformed parameter to range(0,1)

The error that i’m receiving is Initialization failed. Rejecting initial value: Error evaluating the log probability at the initial value. Exception: model_jb5igvs5_namespace::log_prob: preTreat_rate is 1.00337, but must be less than or equal to 1.000000

This is related to the rate parameters, which I define in the transformed parameters block. The idea is a difference in differences model. Of interest, I want to compute the lift attributable to treatment exposure, However, Stan is running into initialization errors where the numerator exceeds the denominator.

How should I combat this?

bayesian_model = """
data {
  int<lower=0> N1;        // num pre-treat observations
  int<lower=0> N2;        // num post-treat observations
  int<lower=0> N3;        // num pre-ctrl observations
  int<lower=0> N4;        // num post-ctrl observations  
  
  int<lower=0> preTreat_N[N1];  // num pre-treat trials
  int<lower=0> preTreat_K[N1];  // num pre-treat successes
  
  int<lower=0> postTreat_N[N2];  // num post-treat trials
  int<lower=0> postTreat_K[N2];  // num post-treat successes  
  
  int<lower=0> preCtrl_N[N3];  // num pre-ctrl trials
  int<lower=0> preCtrl_K[N3];  // num pre-ctrl successes
  
  int<lower=0> postCtrl_N[N4];  // num post-ctrl trials
  int<lower=0> postCtrl_K[N4];  // num post-ctrl successes    
}

parameters {
  // model parameters
  real mu_preTreat_N;
  real mu_preTreat_K;  
  
  real mu_postTreat_N;
  real mu_postTreat_K;  
  
  real mu_preCtrl_N;
  real mu_preCtrl_K;
  
  real mu_postCtrl_N;
  real mu_postCtrl_K;  
  
  real<lower=0> std_preTreat_N;
  real<lower=0> std_preTreat_K;
  
  real<lower=0> std_postTreat_N;  
  real<lower=0> std_postTreat_K;    
  
  real<lower=0> std_preCtrl_N;
  real<lower=0> std_preCtrl_K;
  
  real<lower=0> std_postCtrl_N;  
  real<lower=0> std_postCtrl_K;  
  
}

transformed parameters {
  real<lower=0,upper=1> preTreat_rate = mu_preTreat_K / mu_preTreat_N;
  real<lower=0,upper=1> postTreat_rate = mu_postTreat_K / mu_postTreat_N;
  real<lower=0,upper=1> preCtrl_rate = mu_preCtrl_K / mu_preCtrl_N;
  real<lower=0,upper=1> postCtrl_rate = mu_postCtrl_K / mu_postCtrl_N;  

}

model {
  // prior distributions
  mu_preTreat_N ~ normal(1000, 500);
  mu_preTreat_K ~ normal(700, 400);  
  
  mu_postTreat_N ~ normal(1000, 500);
  mu_postTreat_K ~ normal(700, 400);    
  
  mu_preCtrl_N ~ normal(1000, 500);
  mu_preCtrl_K ~ normal(700, 400);  
  
  mu_postCtrl_N ~ normal(1000, 500);
  mu_postCtrl_K ~ normal(700, 400);      
  
  std_preTreat_N ~ exponential(0.1);
  std_preTreat_K ~ exponential(0.1);  
  
  std_postTreat_N ~ exponential(0.1);
  std_postTreat_K ~ exponential(0.1);    
  
  std_preCtrl_N ~ exponential(0.1);
  std_preCtrl_K ~ exponential(0.1);  
  
  std_postCtrl_N ~ exponential(0.1);
  std_postCtrl_K ~ exponential(0.1);      

  // likelihood function
  for (i in 1:N1){
    preTreat_N[i] ~ normal(mu_preTreat_N, std_preTreat_N);
    preTreat_K[i] ~ normal(mu_preTreat_K, std_preTreat_K);    
  }
  
  for (i in 1:N2){
    postTreat_N[i] ~ normal(mu_postTreat_N, std_postTreat_N);
    postTreat_K[i] ~ normal(mu_postTreat_K, std_postTreat_K);    
  }  
  
  for (i in 1:N3){
    preCtrl_N[i] ~ normal(mu_preCtrl_N, std_preCtrl_N);
    preCtrl_K[i] ~ normal(mu_preCtrl_K, std_preCtrl_K);    
  }  
  
  for (i in 1:N4){
    postCtrl_N[i] ~ normal(mu_postCtrl_N, std_postCtrl_N);
    postCtrl_K[i] ~ normal(mu_postCtrl_K, std_postCtrl_K);    
  }    
  
}

generated quantities {
  real lift;
  lift = (postTreat_rate - postCtrl_rate) - (preTreat_rate - preCtrl_rate);
}
"""    

Range constraints are only forced in the parameters block. The other blocks (including transformed parameters) check to see whether the constraints are met and throw an error if not.

Neither of the parameters in the parameters block have constraints put on them. So there is nothing forcing the parameter in the transformed parameter block to be within that range.

One option would be to put your constrained parameters in the parameters block and your unconstrained parameters in the transformed parameters block.

parameters{
 real<lower=0, upper=1> preTreat_rate;
 real<lower=0> mu_preTreat_N;
} 
transformed parameters{
 real mu_preTreat_K = preTreat_rate * mu_preTreat_N;
} 
1 Like