I have a pretty basic question regarding how to specify priors in a model with a logit link function. I stumbled upon this trying to fit the unimodal Sharpe-Schoolfield equation to food consumption rate of fishes as a function of temperature using brms
:
b(T) = \frac{b_0(T_c)e^{E(\frac{1}{kT_c} - \frac{1}{kT})}} {1+e^{E_h(\frac{1}{kT_h} - \frac{1}{kT})}}
where b(T) is the rate at temperature, T, in Kelvin (K), b_0(T_c) is the rate at a common temperature, E (eV) describes the thermal sensitivity of the biological rate, k is Boltzmannās constant (8.62 Ć 10ā5 eV Kā1), Eh (eV) characterises the decline in the rate past the optimum temperature and Th (K) is the temperature at which half the rate is reduced due to high temperatures. This is the parameterization in Padfield et al., (2020).
The data I have compiled consist of many species, and their feeding rate is expressed in as fraction of max. Hence I want to model this with species-varying parameter b_0. I further rescaled the feeding rates to not have 1ās in order to fit a Beta model (can also consider using a zero_one_inflated_beta
once I figure out my little issue). Temperature has also been centred so that 0 is the peak temperature within species. The data can be found here:
d <- readr::read_csv("https://raw.githubusercontent.com/maxlindmark/stan_data/main/dat.csv")
Given how the data have been centred, I think these priors make sense (Iām using uniform priors here to make sure they donāt wander off⦠sometimes I get biomodal posteriors in non-linear models unless at least one parameter has a uniform prior):
prior <-
prior("uniform(0, 1)", nlpar = "b0", lb = 0, ub = 1) + # consumption at the reference temperature, 0 (note all y are bounded in [0,1])
prior("uniform(0, 3)", nlpar = "E", lb = 0, ub = 3) + # activation energy
prior("uniform(0, 4)", nlpar = "Eh", lb = 0, ub = 4) + # de-activation energy
prior("uniform(0, 10)", nlpar = "Th", lb = 0, ub = 10) # temperature at half rate after decline - hence it should be above 0 which is the peak temperature in the data
With that, we can fit the model using an identity link first:
library(readr)
library(brms)
library(dplyr)
library(ggplot2)
library(modelr)
library(tidybayes)
# Fit a Beta model with an identity link
beta_identity <-
brm(bf(con_percent_scaled ~ (b0 * exp(E*((1/(k*(T_c + 273.15))) - 1/(k*(temp_ct + 273.15))))) / (1 + exp(Eh*((1/(k*(Th + 273.15))) - (1/(k*(temp_ct + 273.15)))))),
b0 ~ 1 + (1|species_ab), E ~ 1, Eh ~ 1, Th ~ 1, nl = TRUE),
data = d, family = Beta(link = "identity"), prior = prior, iter = 4000, cores = 3, chains = 3)
d %>%
data_grid(temp_ct = seq_range(temp_ct, n = 50)) %>%
mutate(k = 8.62*10^-5,
T_c = 0) %>%
add_predicted_draws(beta_identity, re_formula = NA, scale = "response") %>%
ggplot(aes(x = temp_ct, y = con_percent_scaled)) +
stat_lineribbon(aes(y = .prediction), .width = c(.95), alpha = 0.4, fill = "grey") +
geom_point(data = d, aes(temp_ct, con_percent_scaled, color = species_ab), alpha = 1)
This looks OK. Next I wanted to try using a logit link function, to make the mean of the Beta-distribution bounded [0,1]:
beta_logit <-
brm(bf(con_percent_scaled ~ (b0 * exp(E*((1/(k*(T_c + 273.15))) - 1/(k*(temp_ct + 273.15))))) / (1 + exp(Eh*((1/(k*(Th + 273.15))) - (1/(k*(temp_ct + 273.15)))))),
b0 ~ 1 + (1|species_ab), E ~ 1, Eh ~ 1, Th ~ 1, nl = TRUE),
data = d, family = Beta(link = "logit", link_phi = "log"), prior = prior, iter = 4000, cores = 3, chains = 3)
d %>%
data_grid(temp_ct = seq_range(temp_ct, n = 50)) %>%
mutate(k = 8.62*10^-5,
T_c = 0) %>%
add_predicted_draws(beta_logit, re_formula = NA, scale = "response") %>%
ggplot(aes(x = temp_ct, y = con_percent_scaled)) +
stat_lineribbon(aes(y = .prediction), .width = c(.95), alpha = 0.4, fill = "grey") +
geom_point(data = d, aes(temp_ct, con_percent_scaled, color = species_ab), alpha = 1)
Ok, hereās where I get stuck: should the priors in the model with an logit link function be on the logit scale? Because when I extract the stancode, mu[n]
is the inv_logit
of the predictors: ... mu[n] = inv_logit((nlp_b0[n] ...
. And if thatās the case, my second problem is I donāt really have a feeling for how to āconvertā the priors that make sense on the scale of the reponse to the logit scale.
Thanks in advance!
- Operating System: MacOS Catalina
- brms Version: brms_2.13.5
edited: response is a fraction, not %