Hello,
even though I know the spline-function of the mgcv-package can be used for brms, I am trying to customize my fitting function, which is why I am defining my own function. The code-example should only exemplify my current problem.
Using the brms-interface, would it be possible to define the a parameters as an k x 1 - array where I could either define the spline-parameters as random-effects (with a normal population prior with a common mu- and sigma-parameter) or giving every individual array-element its own prior?
The code for reproducibility purposes:
f_test_stan = 
" 
  // B-Spline basis function
  real f_B(int i,           // index
           int d,           // degree
           real x) {        // variable
    real a;
    real b;
    real out;
    
    // initialize values   
    row_vector[15] knots =  [ -4, -2,  0,  2,  4,  6,  8, 10, 12, 14, 16, 18, 20, 22, 24 ];
    // knots(n = 10, d = 2, min = 0, max = 20)
    
    if (d == 0) {
      if (x >= knots[i] && x < knots[i + 1]) {
        out = 1;
      } else {
        out = 0;
      }
    } else {
      a = (x - knots[i]) / (knots[i + d] - knots[i]);
      b = (knots[i + d + 1] - x) / (knots[i + d + 1] - knots[i + 1]);
      out = a * f_B(i, d - 1, x) + b * f_B(i + 1, d - 1, x);
    }
    return out;
  }
  
  // Spline function
  real f_spline(real x,   // variable
                real a1,  // parameters
                real a2,
                real a3,
                real a4,
                real a5,
                real a6,
                real a7,
                real a8,
                real a9,
                real a10,
                real a11,
                real a12) {
    
    real out;
    int d;
    
    // initialize values
    d = 2;
    
    // There are n + d many B-splines
    out = a1 * f_B(1, d, x);
    out = out + a2 * f_B(2, d, x);
    out = out + a3 * f_B(3, d, x);
    out = out + a4 * f_B(4, d, x);
    out = out + a5 * f_B(5, d, x);
    out = out + a6 * f_B(6, d, x);
    out = out + a7 * f_B(7, d, x);
    out = out + a8 * f_B(8, d, x);
    out = out + a9 * f_B(9, d, x);
    out = out + a10 * f_B(10, d, x);
    out = out + a11 * f_B(11, d, x);
    out = out + a12 * f_B(12, d, x);
    return out;
  }
"
test_data = data.table(x = seq(0, 20, 0.01))
test_data[,y := sin(x) + rnorm(1, 0, 0.1), by = 'x']
prior_test = c(set_prior("normal(0, 1)", nlpar = "a1"),
               set_prior("normal(0, 1)", nlpar = "a2"),
               set_prior("normal(0, 1)", nlpar = "a3"),
               set_prior("normal(0, 1)", nlpar = "a4"),
               set_prior("normal(0, 1)", nlpar = "a5"),
               set_prior("normal(0, 1)", nlpar = "a6"),
               set_prior("normal(0, 1)", nlpar = "a7"),
               set_prior("normal(0, 1)", nlpar = "a8"),
               set_prior("normal(0, 1)", nlpar = "a9"),
               set_prior("normal(0, 1)", nlpar = "a10"),
               set_prior("normal(0, 1)", nlpar = "a11"),
               set_prior("normal(0, 1)", nlpar = "a12"))
eq_test= bf(y ~ f_spline(x, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12),
            a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 ~ 1,
            nl = TRUE)
stan_vars_test = stanvar(scode = f_test_stan, block = "functions")
mod_test = brm(eq_test,
               family = gaussian(), 
               data = test_data,
               prior = prior_test,
               stanvars = stan_vars_test, 
               cores = 4,
               iter = 1000,
               control = list(adapt_delta = 0.5, 
                              max_treedepth = 15))
- Operating System: aarch64-apple-darwin20 (darwin20)
- brms Version: 2.15.9, R-Version (4.1.0)
Plot of data:
