Prior for constrained parameters that have to sum to 1?

Suppose beta is a vector of K parameters and I want them to sum to one. My understanding is that one way of achieving this is declaring beta to be a simplex, that is simplex[K] beta;. Is that the only way? If so, is there a way of adding informative priors? For example, suppose that K=3 and I have some good idea that the true values for betas are [0.2, 0.5, 0.3].

Thanks for the help!

There might be a way to do this using simplices, but an alternative is to do something like sum(beta) ~ normal(1,.01) for a soft sum-to-one constraint. For example:

    data{
      int<lower=0> n;
    }
    parameters{
      real<lower=0, upper=1> beta[n];
    }
    model{
      beta ~ normal(.5, 1); // the prior
      sum(beta) ~ normal(1,.01);  // the soft sum-to-one constraint
    }
    generated quantities{
      real sum_beta = sum(beta);
    }

That’s one way you can do it, and would force a “hard constraint” - the vector would sum always to one. For more details, see the manual section about Parameterizing Centered Vectors.

You can use a Dirichlet prior. It is parameterised by a vector which can be used to incorporate this prior information. Here’s an example you can play with:

library(cmdstanr)
library(posterior)
library(dplyr)
m <- "
data {
  real scale;
}
generated quantities {
  simplex[3] y;
  y = dirichlet_rng([2, 5, 3]'*scale);
}
"
mod <- cmdstan_model(write_stan_file(m))
fit <- mod$sample(data=list(scale=1), iter_sampling = 100, fixed_param = T)
fit$draws() %>% as_draws_df() %>% select(c(1,2,3)) %>% summarise_all(list(mean = mean, sd = sd))

Here, y will have the mean values [0.2, 0.5, 0.3], and you can play with scale to adjust the variance.

Hope that helps!

2 Likes