我有一些缺失的序数数据,我试图在斯坦模拟。由于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)概率相加为1
,2
或3
,以及然后是反(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
数据在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中的一个类似模型,它自动估算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
答案 0 :(得分:3)
你需要编写等于log posterior加上常量的东西。这通常是模型的对数关节。
缺少连续数据通常使用参数建模---请参阅有关缺失数据的手册章节。
||
操作是合乎逻辑的,因此categorical_lpmf((2 || 3) | theta)
将等于categorical_lpmf(1 | theta)
因为(2 || 3)
评估为1
(任何非零值)被视为逻辑真,1
对真值进行编码。
如果您遗漏的离散数据x
在1:K
时可以使用具有日志密度/质量lp[k]
的值x == k
,那么编码它的方式就像target += log_sum_exp(lp);
您需要确保在lp[k]
中包含规范化字词。
你可能想要处理所有事情并查看缺失的数据是否对后验产生任何影响 - 它通常只是因素。
您没有观察到观察到的和未观察到的数据的不同参数。