将Stan

时间:2017-12-11 15:50:31

标签: r missing-data jags imputation stan

我有一些缺失的序数数据,我试图在斯坦模拟。由于Stan不能直接处理离散参数,我试图将那些缺失的情况的响应变量的不同可能值边缘化。

直觉上,我认为我需要缺失值的概率是某些序数结果,乘以那些序数结果的概率,然后缺失值不是某些序数结果的概率乘以1 - 概率那些序数结果。

然而,在实践中,我不确定我是否正在斯坦本身正确编码模型,或者我的确切数学直觉是否适合边缘化丢失的数据。虽然Stan手册有处理离散参数的例子,但我仍然有点迷失。我还想在Stan y块中做出预测或获得generated quantities值的估算向量,但我可以做一些入门指针。问题是没有让代码运行,更健全地检查我已正确完成它。

实施例

例如,请考虑R包wine中的ordinal数据。下面的R代码采用rating变量,将其转换为3类别比例以便于解释,在变量new_rating_w_miss中导致15%的缺失,然后创建一个向量missing如果值丢失则为1,否则为0。由于Stan不会采用NA值,因此我将缺失值设为-1

library(ordinal)
library(rstan)
library(runjags)
library(rjags)
data(wine)

wine$new_rating <- ifelse( wine$rating > 3, 3, wine$rating)
wine$new_rating_w_miss <- ifelse( wine$rating > 3, 3, wine$rating)
wine$temp_num <- ifelse(wine$temp == "cold", 1, 0)

set.seed(2017)
n_missing <- sample(0:nrow(wine), nrow(wine)*0.15, replace=FALSE)

wine$new_rating_w_miss[ n_missing ] <- -1
wine$is_missing <- ifelse(wine$new_rating_w_miss == -1, 1, 0 )

斯坦模型

我的Stan型号代码如下:

data {
  int K;
  int<lower=0> N;
  int<lower=1> D;
  int y[N];
  int<lower=0> missing[N];
  int<lower=0> N_miss;
  row_vector[D] x[N];
}

parameters {
  vector[D] beta;
  real<lower=0,upper=1> p;
  ordered[K-1] c;
}

model {
  vector[K] theta;
  vector[N_miss] lp;
  beta ~ normal(0, 5);
  p ~ beta(2,2);
  for (n in 1:N) {
    real eta;
    eta = x[n] * beta;
    theta[1] = Phi( (c[1] - eta) );
    for (k in 2:(K-1))
      theta[k] = Phi( (c[k] - eta)) - Phi( (c[k-1] - eta));
    theta[K] = 1 - Phi( (c[K-1] - eta) );

    if(missing[n] == 0){
      y[n] ~ categorical(theta);
      missing[n] ~ bernoulli(p);
  }

if(missing[n] == 1){
target += log_mix( theta[1] ,
                    categorical_lpmf( 1 | theta ),
                    categorical_lpmf( (2 || 3) | theta )
                  )

            +

            log_mix( theta[2] ,
                                categorical_lpmf( 2 | theta ),
                                categorical_lpmf( (1 || 3) | theta )
                              )

            +

            log_mix( theta[3] ,
                                categorical_lpmf( 3 | theta ),
                                categorical_lpmf( (1 || 2) | theta )
                              );
  missing[n] ~ bernoulli(p);
    }
 }
}

可以看出,我试图通过使用Stan中的log_mix()函数来边缘化离散的未知值。具体而言,在给定从观察数据估计的那些值的(log)概率的情况下,将缺失值的(log)概率相加为123,以及然后是反(log)概率。

一个问题是:我应该从观察到的和未观察到的数据中估算出单独的theta概率向量吗?

结果:

Inference for Stan model: Stan_missing_model.
4 chains, each with iter=500; warmup=250; thin=1; 
post-warmup draws per chain=250, total post-warmup draws=1000.

           mean se_mean   sd    2.5%     25%     50%     75%   97.5% n_eff Rhat
beta[1]   -1.28    0.01 0.30   -1.83   -1.48   -1.28   -1.09   -0.67   808 1.00
p          0.16    0.00 0.04    0.09    0.13    0.15    0.18    0.24   812 1.00
c[1]      -1.26    0.01 0.23   -1.70   -1.43   -1.26   -1.11   -0.81   699 1.00
c[2]      -0.72    0.01 0.21   -1.15   -0.86   -0.70   -0.57   -0.27   746 1.00
lp__    -119.80    0.08 1.47 -123.45 -120.57 -119.34 -118.71 -118.02   378 1.02

在R

中运行模型

使用上面的R数据在wine中运行模型:

stan_data <- list( K = 3, N = nrow(wine), D = 1, 
                   y = wine$new_rating_w_miss, 
                   missing = wine$is_missing, 
                   N_miss = sum(wine$is_missing),
                   x = as.matrix(wine$temp_num) 
                  )

fit_stan <- stan(file = "Stan_missing_model.stan", data = stan_data, 
                  cores = 4, chains = 4, warmup = 250, iter = 500)
print(fit_stan)

估算JAGS中的类似模型

JAGS中的一个类似模型,它自动估算NA值,似乎得出的参数估计值不太相似:

model{
   for( i in 1:N ){
       y[i] ~ dcat( theta[i, 1:3] )
       theta[i,1] <- phi( c[1] - mu[i] )
       theta[i,2] <- phi( c[2] - mu[i] ) - phi( c[1] - mu[i] )
       theta[i,3] <- 1 - phi( c[2] - mu[i] )

       mu[i] <- beta * temp[i]
       miss[i] ~ dbern( p )
    }

  beta ~ dnorm(0 , 5)
  p ~ dbeta( 2, 2)
  for(i in 1:2){
    c_raw[i] ~ dnorm(0,1.0E-3)
   }
  c <- sort(c_raw)

}

jags_data <- list( N = nrow(wine), 
                   y = ifelse(wine$new_rating_w_miss == -1, 
                              NA, wine$new_rating_w_miss), 
                   temp = wine$temp_num, 
                   miss = wine$is_missing
                  )

jags_monitor <- c("beta","p","c")

fit_jags <- run.jags(model = "JAGS_so_model.txt", 
                    data = jags_data, monitor = jags_monitor,
                    inits = list("c_raw" = c(-0.5,0.5)),
                    n.chains = 4, burnin = 500, sample = 500)
summary(fit_jags)

         Lower95     Median    Upper95       Mean        SD Mode       MCerr MC%ofSD SSeff       AC.10      psrf
beta -1.40131934 -0.8531391 -0.3148070 -0.8516923 0.2783449   NA 0.022165423     8.0   158  0.05891468 1.0284938
p     0.07983462  0.1547419  0.2356164  0.1576307 0.0410555   NA 0.001264152     3.1  1055 -0.00592979 0.9989195
c[1] -2.64389817 -2.0139135 -1.4006353 -2.0246384 0.3322312   NA 0.024410375     7.3   185  0.08432516 1.0213586
c[2] -1.35215148 -0.9021336 -0.4709347 -0.9031153 0.2319716   NA 0.019547231     8.4   141  0.07087327 1.0153249

1 个答案:

答案 0 :(得分:3)

你需要编写等于log posterior加上常量的东西。这通常是模型的对数关节。

缺少连续数据通常使用参数建模---请参阅有关缺失数据的手册章节。

||操作是合乎逻辑的,因此categorical_lpmf((2 || 3) | theta)将等于categorical_lpmf(1 | theta)因为(2 || 3)评估为1(任何非零值)被视为逻辑真,1对真值进行编码。

如果您遗漏的离散数据x1:K时可以使用具有日志密度/质量lp[k]的值x == k,那么编码它的方式就像target += log_sum_exp(lp);

您需要确保在lp[k]中包含规范化字词。

你可能想要处理所有事情并查看缺失的数据是否对后验产生任何影响 - 它通常只是因素。

您没有观察到观察到的和未观察到的数据的不同参数。