Hi Perry
Below is a simple example in which I would like to fit a bayesian adaptive regression spline using nimble: (Note the nimble code below is meant to illustrate ideally what I would like to achieve but I'm not sure how to specify it correctly using nimbleFunctions:
<R code
## LOAD PACKAGES ---------
library(data.table)
library(splines2)
library(nimble)
## SIMULATE DATA ---------
set.seed(123)
dt <- data.table(x = seq(0.1, 10, 0.1))
betas <- c(20, 30, 50)
dt[, y := nsp(x, knots = 5, intercept = T)%*%betas + rnorm(100, 0, 0.5)
]
## ATTEMPT TO PREPARE BARS IN NIMBLE
## Specify nsp code in R
Build_nsp <- function(x, K) {
nsp(x, knots = K, intercept = T)
}
## Convert R function to a function that can be called in nimble
Rnsp <- nimbleRcall(function(x = double(1), K = double(1)) {},
Rfun = 'Build_nsp',
returnType = double(2))
nim_spCode <- nimbleCode({
## Determine number of coefficients based
## on number of knots
p <- KNum + 2
## Prep spline design matrix
B[1:N,1:p] <- Rnsp(x[1:N], K = K)
for (i in 1:N) {
fit[i] <- inprod(B[i, 1:p], betas[1:p])
}
## Simulate the number of knots
## such that it is very dependent on
## the data
Alpha[1:Kmax] <- nimRep(0.01, Kmax)
Theta[1:Kmax] ~ ddirch(Alpha[1:Kmax])
KNum ~ dcat(Theta[1:Kmax])
## Attempt to make the knot position random
for (i in 1:KNum){
K[i] ~ dunif(0.1, 9.9)
}
for (i in 1:p) {
betas[i] ~ dnorm(0, sd = 1)
}
for (i in 1:N) {
y[i] ~ dnorm(fit[i], sd = 1)
}
}
)
y_m <- mean(dt$y)
y_sd <- sd(dt$y)
sp_Const <- list(N = dim(dt)[1], Kmax = 3)
sp_Data <- list(y = (dt$y - y_m) / y_sd,
x = dt$x)
sp_Inits <- list(betas = rep(0, 3), KNum = 2 )
sp_mod <- nimbleModel(code = nim_spCode ,
name = "sp_mod" ,
constants = sp_Const ,
data = sp_Data ,
inits = sp_Inits )
>
The error received when running the nimbleModel is as follows: "Defining model
Error in getSymbolicParentNodesRecurse(x, constNames, indexNames, nimbleFunctionNames, :
Dynamic indexing found in a vector of indices, 1:p. Only scalar indices, such as 'idx' in 'x[idx]', can be dynamic. One can instead use dynamic indexing in a vector of indices inside a nimbleFunction."
I have been able to bring in a natural cubic spline (provided by the splines2 package) into the nimble code using the nimbleRcall. So it is possible to make a given number of knots random. However, I'm not sure how to enable the number of knots (KNum in the R code above) to vary as well.
Thank you for your assistance Perry.
Best regards
Kavir