Thank you for your answer @jsocolar.
Here is a reproducible example that I am running myself at the moment.
# ==========================================================================
# Simulate data with 4 predator_ids and standardized covariates
# ==========================================================================
options(mc.cores = parallel::detectCores())
library(data.table)
library(brms)
library(parallel)
set.seed(42)
# Simulation parameters
n_predators <- 4
n_per_pred <- 250
total_obs <- n_predators * n_per_pred
# Generate predictor variables
sim_data <- rbindlist(lapply(1:n_predators, function(i) {
predator <- paste0("sim_pred_", i)
cumul_xp_pred <- rnorm(n_per_pred, mean = 10, sd = 5)
game_duration <- rnorm(n_per_pred, mean = 500, sd = 100)
prey_avg_speed <- rnorm(n_per_pred, mean = 2, sd = 0.3)
prey_avg_rank <- rnorm(n_per_pred, mean = 12, sd = 3)
# Generate hunting_success based on cumul_xp_pred
mu <- 1 / (1 + exp(-0.5 * (cumul_xp_pred - 10) / 5)) # logistic on standardized xp
hunting_success <- rbinom(n_per_pred, size = 4, prob = pmin(pmax(mu, 0.05), 0.95))
data.table(
predator_id = predator,
hunting_success = hunting_success,
game_duration = game_duration,
prey_avg_speed = prey_avg_speed,
cumul_xp_pred = cumul_xp_pred,
prey_avg_rank = prey_avg_rank
)
}))
# Standardize predictors
sim_data[, Zgame_duration := scale(game_duration)]
sim_data[, Zprey_avg_speed := scale(prey_avg_speed)]
sim_data[, Zcumul_xp := scale(cumul_xp_pred)]
sim_data[, Zprey_avg_rank := scale(prey_avg_rank)]
sim_data[, predator_id := as.factor(predator_id)]
# ==========================================================================
# Set up model formula and priors
# ==========================================================================
model_formula_builtin <- brmsformula(
hunting_success | trials(4) ~
Zcumul_xp +
(1 | predator_id)
)
model_formula_custom <- brmsformula(
hunting_success | vint(4) ~
Zcumul_xp +
(1 | predator_id)
)
# Priors for complex gamm model
#priors <- c(
# set_prior("normal(1, 0.5)", class = "b", coef = "Zgame_duration"),
# set_prior("normal(0, 1)", class = "b", coef = "Zprey_avg_rank"),
# set_prior("normal(0, 2)", class = "b", coef = "sZcumul_xp_1"),
# set_prior("normal(0, 0.5)", class = "Intercept"),
# set_prior("normal(0, 0.5)", class = "sds"),
# set_prior("normal(log(2), 0.5)", class = "phi")
#)
# Priors for simpler gamm model
#priors <- c(
# set_prior("normal(0, 2)", class = "b", coef = "sZcumul_xp_1"),
# # prior on the intercept
# set_prior("normal(0, 0.5)", class = "Intercept"),
# # prior on sds parameters
# set_prior("normal(0, 0.5)", class = "sds"),
# # priors on phi
# set_prior("normal(log(2), 0.5)", class = "phi")
#)
# Priors for linear model
priors <- c(
set_prior("normal(0, 1)", class = "b", coef = "Zcumul_xp"),
set_prior("normal(0, 0.5)", class = "Intercept"),
set_prior("normal(0, 0.5)", class = "sd"),
set_prior("normal(log(2), 0.5)", class = "phi")
)
# ==========================================================================
# Fit model using built-in beta_binomial
# ==========================================================================
fit_builtin <- brm(
formula = model_formula_builtin,
family = beta_binomial(),
data = sim_data,
warmup = 200,
iter = 1200,
thin = 1,
chains = 4,
threads = threading(3),
backend = "cmdstanr",
seed = 123,
prior = priors,
control = list(adapt_delta = 0.99)
)
# ==========================================================================
# Fit model using custom beta_binomial2
# ==========================================================================
beta_binomial2 <- custom_family(
"beta_binomial2", dpars = c("mu", "phi"),
links = c("logit", "log"), lb = c(NA, 0),
type = "int", vars = "vint1[n]"
)
stan_funs <- "
real beta_binomial2_lpmf(int y, real mu, real phi, int T) {
return beta_binomial_lpmf(y | T, mu * phi, (1 - mu) * phi);
}
int beta_binomial2_rng(real mu, real phi, int T) {
return beta_binomial_rng(T, mu * phi, (1 - mu) * phi);
}
"
stanvars <- stanvar(scode = stan_funs, block = "functions")
fit_custom <- brms(
formula = model_formula_custom,
family = beta_binomial2,
stanvars = stanvars,
data = sim_data,
warmup = 200,
iter = 1200,
chains = 4,
thin = 1,
threads = threading(3),
backend = "cmdstanr",
seed = 123,
prior = priors,
control = list(adapt_delta = 0.99)
)
I am running the test on Pop!OS 22.04 LTS with brms 2.22.0 and R version 4.1.3
Best,
Maxime