【问题标题】:How to use a distinct data set per chain in Stan?如何在 Stan 中为每个链使用不同的数据集?
【发布时间】:2015-01-22 17:28:16
【问题描述】:

我有一个包含许多缺失观测值的数据集,我使用 Amelia 包创建了估算数据集。我想知道是否可以在每个链中使用不同的数据集并行运行相同的模型,并将结果合并到单个 Stan 对象中。

# Load packages
library(Amelia)
library(rstan)

# Load built-in data
data(freetrade)

# Create 2 imputed data sets (polity is an ordinal variable)
df.imp <- amelia(freetrade, m = 2, ords = "polity")

# Check the first data set
head(df.imp$imputations[[1]])

# Run the model in Stan
code <- '
    data {
int<lower=0> N;          
vector[N] tariff;     
vector[N] polity;      
}
    parameters {
real b0;                  
real b1;           
real<lower=0> sigma;       
}
    model {
b0 ~ normal(0,100);  
b1 ~ normal(0,100); 
tariff ~ normal(b0 + b1 * polity, sigma);    
}
'

# Create a list from the first and second data sets
df1 <- list(N = nrow(df.imp$imputations[[1]]),
            tariff = df.imp$imputations[[1]]$tariff,
            polity = df.imp$imputations[[1]]$polity)

df2 <- list(N = nrow(df.imp$imputations[[2]]),
            tariff = df.imp$imputations[[2]]$tariff,
            polity = df.imp$imputations[[2]]$polity)

# Run the model
m1 <- stan(model_code = code, data = df1, chains = 1, iter = 1000) 

我的问题是如何同时在两个数据集上运行最后一行代码,运行 2 个链并将输出与相同的 stan() 函数结合起来。有什么建议吗?

【问题讨论】:

    标签: r stan


    【解决方案1】:

    您可以单独运行模型,然后使用 sflist2stanfit() 组合它们。

    例如

    seed <- 12345
    s1 <- stan_model(model_code = code) # compile the model
    
    m1 <- sampling(object = s1, data = df1, chains = 1,
                   seed = seed, chain_id = 1, iter = 1000) 
    m2 <- sampling(object = s1, data = df2, chains = 1,
                   seed = seed, chain_id = 2, iter = 1000)
    
    f12 <- sflist2stanfit(list(m1, m2))
    

    【讨论】:

    • 非常感谢您的回答。它在这里工作得很好,而且非常直观。我不知道sflist2stanfit(),它做得很好。它只是效率不高,因为它将代码转换为 C++ 两次并且不能并行运行,但我会记住这一点。再次感谢。
    • 只需编译一次模型,然后可以将不同的数据集传递给它,无论是并行还是串行。例如,m &lt;- stan_model(model_code = code),然后将m 传递给stan()fit 参数。
    • 感谢您的澄清,本。我也可以将它传递给sampling(object = m, ...),对吗?它似乎在这里工作。
    【解决方案2】:

    您必须使用其中一个包来在 R 中进行并行计算。 根据这篇文章,它应该可以工作: Will RStan run on a supercomputer?

    这是一个可能有效的示例(我将此代码用于 JAGS,稍后将使用 Stan 对其进行测试):

    library( doParallel )
    cl <- makeCluster( 2 ) # for 2 processes
    registerDoParallel( cl )
    
    library(rstan)
    
    # make a function to combine the results
    stan.combine <- function(...) { return( sflist2stanfit( list(...) )  ) }
    
    mydatalist <- list(df1 , df2)    
    myseeds <- c(123, 456)
    
    # now start the chains
    nchains <- 2
    m_both <- foreach(i=1:nchains , 
                  .packages = c( 'rstan' ), 
                  .combine = "stan.combine") %dopar% {
                 result <- stan(model_code = code, 
                       data = mydatalist[[i]], # use the right dataset
                       seed=myseeds[i],        # use different seeds
                       chains = 1, iter = 1000) 
                 return(result) }
    

    让我知道它是否适用于 Stan。正如我所说,我还没有测试过。

    【讨论】:

    • 感谢您的回答,dwcoder。但是,代码在这里不起作用。我复制并粘贴了它,它给出了一些错误:Error: unexpected 'in' in "m_both &lt;- foreach(i in",然后是Error: unexpected ',' in " .packages = c( 'rstan' ),",最后是Error: unexpected ')' in " )"
    • 让我看看,我已经设置好了。
    • 我修好了。出现问题:foreach( 1 in 1:nchains ) 应该是 foreach( 1=1:nchains)
    • 我需要指出@user2980360 的代码不会并行运行,它会一个接一个地运行两条链。如果你想使用两个核心,你需要使用像doParallel这样的包。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-04
    • 2016-11-29
    • 2016-03-26
    • 1970-01-01
    • 1970-01-01
    • 2015-01-20
    • 1970-01-01
    相关资源
    最近更新 更多