如何将先验均值与标准差变量传入brms模型?
在brms中使用变量传递先验参数的解决方法
你遇到的问题是因为brms生成Stan代码时,不会自动解析prior()函数里的R变量,而是直接将变量名写入Stan代码,导致Stan编译器无法识别这些仅存在于R环境中的变量。下面是两种可行的解决方法:
方法1:使用准引用强制求值
利用R的准引用语法(!!操作符),让R先将变量替换为具体数值,再传递给brms。修改后的代码如下:
library(tidyverse) library(brms) df_demo = tibble( A = rbinom(1e3, 1, .5), B = rbinom(1e3, 1, .51), ) |> pivot_longer( everything(), names_to = "recipe", values_to = "convert" ) MU_INTERCEPT = 0 SD_INTERCEPT = 0.1003353 MU_TRT = 0 SD_TRT = 0.02000267 brm( formula = "convert ~ recipe", prior = prior(normal(!!MU_INTERCEPT, !!SD_INTERCEPT), class = Intercept) + prior(normal(!!MU_TRT, !!SD_TRT), class = b, coef=recipeB), data = df_demo, family = bernoulli )
!!会强制R对后续变量求值,把变量的实际数值代入先验定义,生成的Stan代码里就会是具体数字而非变量名,Stan就能正常编译。
方法2:构造字符串形式的先验
如果不习惯准引用,也可以直接通过字符串拼接生成先验规则,再传给prior参数:
library(tidyverse) library(brms) df_demo = tibble( A = rbinom(1e3, 1, .5), B = rbinom(1e3, 1, .51), ) |> pivot_longer( everything(), names_to = "recipe", values_to = "convert" ) MU_INTERCEPT = 0 SD_INTERCEPT = 0.1003353 MU_TRT = 0 SD_TRT = 0.02000267 # 拼接先验字符串 prior_str = paste0( "normal(", MU_INTERCEPT, ", ", SD_INTERCEPT, ") class=Intercept; ", "normal(", MU_TRT, ", ", SD_TRT, ") class=b coef=recipeB" ) brm( formula = "convert ~ recipe", prior = prior_str, data = df_demo, family = bernoulli )
这种方式通过字符串拼接直接将变量值写入先验规则,同样能避免Stan识别R变量的问题。
错误原因说明
你之前的代码中,prior(normal(MU_INTERCEPT, SD_INTERCEPT), class = Intercept)会被brms直接转换成Stan代码里的normal_lpdf(Intercept | MU_INTERCEPT, SD_INTERCEPT),但Stan环境中没有定义MU_INTERCEPT这类变量,因此抛出“标识符不在作用域内”的错误。上述两种方法的核心都是让R先把变量替换为具体数值,再生成合法的Stan代码。
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

