How to specify a non-linear model that evaluates to zero below a threshold and an exponential function otherwise?

Please also provide the following information in addition to your question:

  • Operating System: linux
  • brms Version: 2.8.0

I have a function:

fun_douillard <- function(t, tg, Gm, k){
y <- (t > tg) * Gm * (1-exp(-k * (t-tg)))
}

That evaluates to zero when t <= tg and the exponential function otherwise.

I would like to estimate the parameters tg, Gm, and k from experimental data using non linear regression.

How can I specify such a model using the brms model formula syntax?

Thank you for your help

/Jannik

More or less literally as written down by you

library(brms)
bform <- bf(
	y ~ (t > tg) * Gm * (1-exp(-k * (t-tg))),
	tg ~ 1,
	Gm ~ 1,
	k ~ 1, 
	nl = TRUE
)
bprior <- prior(normal(0, 10), nlpar = tg, lb = 0) +
	prior(normal(0, 10), nlpar = Gm, lb = 0) +
	prior(normal(0, 1), nlpar = k, lb = 0)

dat <- data.frame(
	y = rnorm(100),
	t = seq(0, 1, length.out = 100)
)

fit <- brm(bform, dat, prior = bprior)
summary(fit)

The priors on the parameters are just placeholders but note that I put a lower boundary of 0 on all of the 3 parameters because I think this is what you have in mind anyway. If this is not how the parameters are bounded, plase change/remove these bounds.

1 Like

Thank you Paul.

That was more simple than I had imagined!

/Jannik

Dear paul,

Thank you for showing me how to formulate the non-linear model and set the bounded priors.

Nevertheless, I have a follow up question, and I was not sure if I needed to make a new post?

In fact, my parameters are assumed to depend on varios physical and chemical parameters.
How do I set priors on both the Intercept and the predictors? For example,

bform <- bf(firmness ~ (minutes > tg) * Gm * (1 - exp(-k * (minutes - tg))),
tg ~ pH + dose,
Gm ~ pH + protein,
k ~ pH + temperature,
nl = TRUE)

Would it then be correct to set priors as follows:

bprior <- prior(normal(11, 1), nlpar = tg, coef = Intercept)+
prior(normal(0, 10), nlpar = tg, coef = pH)+
prior(normal(0, 10), nlpar = tg, coef = dose)+
prior(normal(260, 1), nlpar = Gm, coef = Intercept)+
prior(normal(0, 10), nlpar = Gm, coef = pH)+
prior(normal(0, 10), nlpar = Gm, coef = protein)+
prior(normal(0.23, 0.05), nlpar = k, coef = Intercept)+
prior(normal(0, 1), nlpar = k, coef = pH)
prior(normal(0, 1), nlpar = k, coef = Temperature)

Or is there a better way?

/Jannik

This looks syntactically correct. Whether the prior make sense for your model and data I don’t know.

Alternatively, you can use

prior(normal(11, 1), nlpar = tg, coef = Intercept)+

prior(normal(0, 10), nlpar = tg)

in which case it will use a normal(11, 1) prior for the intercept and a prior(normal(0, 10), nlpar = tg) prior for all other coefficients.

This may save some lines of code if you have a lot of predictors.

Thanks Paul,

I will try this.

Have a wonderful day :-)