2015-03-02 289 views
1

我正在做贝叶斯分析,我试图估计两个参数。为了近似后验分布,我构建了一个精细网格并计算网格中每个元素的后验概率。我规范化它,使网格总和为1.r - 从概率网格抽样(贝叶斯后验近似)

现在我对分布采样感兴趣。这是我到目前为止有:

sampleGrid <- function(post.grid, mu.grid, sig2.grid) { 
    value <- sample(post.grid, 1, prob=post.grid) 
    index <- which(post.grid == value) 
    col <- as.integer(index/nrow(post.grid))+1 
    row <- index-(col-1)*nrow(post.grid) 
    return(c(mu.grid[row], sig2.grid[col])) 
} 

不过,我运行与运行时的问题时,我想品尝了很多,因为我使用了一个for循环:

for(i in 1:nrow(sample.grid)) { 
    sample.grid[i, ] <- sampleFromGrid(post.grid, mu.grid, sig2.grid) 
} 

我在想,如果有一种矢量化的方法。我的尝试是:

vectorizedSampleFromGrid <- function(post.grid, mu.grid, sig2.grid, n){ 
    values <- sample(post.grid, n, replace=T, prob=post.grid) 
    index <- which(post.grid %in% values) 
    if(length(values)!=length(index)) { 
     temp.df <- count(values) 
     index <- which(post.grid %in% temp.df[,1]) 
     temp.df <- cbind(temp.df, index) 
     temp.df <- temp.df[temp.df[, 2] > 1, ] 
     for(i in 1:nrow(temp.df)) { 
      index <- c(index, rep(temp.df[i, 3], temp.df[i,2]-1)) 
     } 
    } 
    col <- as.integer(index/nrow(post.grid))+1 
    row <- index-(col-1)*nrow(post.grid) 
    return(cbind(mu.grid[row], sig2.grid[col])) 
} 

我知道一些元素将被采样一次以上。我试图做的是将这些索引多次添加到原始索引列表中,取决于它们被采样了多少次。但是,当我这样做时,结果是不正确的。

如果有人能提供任何建议,我将不胜感激。

回答

2

这是我会做的。创建一个矢量化函数来评估后验(或至少与其成正比的东西):

f = function(mu, sigma, log=TRUE) { 
    logf = dnorm(mu, 0, sigma, log=TRUE) + dgamma(sigma, 1, 1, log=TRUE) 
    if (log) return(logf) 
    return(exp(f)) 
} 

现在在网格上评估这个函数。

library(dplyr) 
grid = mutate(expand.grid(mu=seq(-3,3,1), sigma=seq(1,7,1)), 
       logp = f(mu,sigma), 
       logp = logp-max(logp), # for numerical stability 
       p = exp(logp), 
       p = p/sum(p))  # Normalize 

现在从该网格获取样本:

samples = sample_n(grid, size=100, replace=TRUE, weight=grid$p)