我想在Stan运行一个强大的逻辑回归(robit)。该模型建议在Gelman& Co.希尔的“使用回归和多级方法的数据分析”(2006年,第124页),但我不确定如何实现它。我检查了Stan's Github repository和the reference manual,但不幸的是我仍然感到困惑。这是我用来模拟常规逻辑回归的一些代码。我应该添加什么,以便错误跟随,比如7个自由度的分布?如果我运行多级分析,那么它是否会是相同的程序?
library(rstan)
set.seed(1)
x1 <- rnorm(100)
x2 <- rnorm(100)
z <- 1 + 2*x1 + 3*x2
pr <- 1/(1+exp(-z))
y <- rbinom(100,1,pr)
df <- list(N=100, y=y,x1=x1,x2=x2)
# Stan code
model1 <- '
data {
int<lower=0> N;
int<lower=0,upper=1> y[N];
vector[N] x1;
vector[N] x2;
}
parameters {
real beta_0;
real beta_1;
real beta_2;
}
model {
y ~ bernoulli_logit(beta_0 + beta_1 * x1 + beta_2 * x2);
}
'
# Run the model
fit <- stan(model_code = model1, data = df, iter = 1000, chains = 4)
print(fit)
谢谢!
答案 0 :(得分:5)
我必须遗漏一些东西,但我无法适应danilofreire从Luc发布的解决方案。所以我刚刚从JAGS翻译了一个模型。
我认为这是正确的,尽管与Luc的解决方案略有不同。
library(rstan)
N <- 100
x1 <- rnorm(N)
x2 <- rnorm(N)
beta0 <- 1
beta1 <- 2
beta2 <- 3
eta <- beta0 + beta1*x1 + beta2*x2 # linear predictor
p <- 1/(1 + exp(-eta)) # inv-logit
y <- rbinom(N, 1, p)
dlist <- list(y = y, x1 = x1, x2 = x2, N = N, nu = 3) # adjust nu as desired df
mod_string <- "
data{
int<lower=0> N;
vector[N] x1;
vector[N] x2;
int<lower=0, upper=1> y[N];
real nu;
}
parameters{
real beta0;
real beta1;
real beta2;
}
model{
vector[N] pi;
for(i in 1:N){
pi[i] <- student_t_cdf(beta0 + beta1*x1[i] + beta2*x2[i], nu, 0, 1);
y[i] ~ bernoulli(pi[i]);
}
}
"
fit1 <- stan(model_code = mod_string, data = dlist, chains = 3, iter = 1000)
print(fit1)
答案 1 :(得分:4)
Luc Coffeng在Stan mailing list上给我发了这个答案,我想我应该在这里添加。他说:
“采用GLM作为您的robit回归的基础:只需用e ~ student_t(7, 0, sigma_e)
替换标准错误术语,其中sigma_e ~ cauchy(0, 2)
或您认为可以的任何比例(我不会超过5)因为(-5,5)的逆logit覆盖了[0,1]区间的大部分。除了t-误差的比例之外,你还可以指定t-error的df作为参数。见下文建议的代码。
我希望您的数据包含的信息比您提供的玩具示例更多,即每个人的多次观察(如下所示)。每个单元/单元只需观察一次,实际上无法识别该模型。“
然后他提供了以下示例:
library(rstan)
set.seed(1)
x1 <- rnorm(100)
x2 <- rnorm(100)
z <- 1 + 2*x1 + 3*x2 + 0.1 * rt(100, 7)
pr <- 1/(1+exp(-z))
y <- rbinom(100,10,pr)
df <- list(N=100, y=y, x1=x1, x2=x2, nu = 7)
# Stan code
model1 <- '
data {
int<lower=0> N;
int<lower=0,upper=10> y[N];
vector[N] x1;
vector[N] x2;
real nu;
}
parameters {
real beta_0;
real beta_1;
real beta_2;
real<lower=0> sigma_e;
vector[N] e;
}
model {
e ~ student_t(nu, 0, sigma_e);
sigma_e ~ cauchy(0, 1);
y ~ binomial_logit(10, beta_0 + beta_1 * x1 + beta_2 * x2 + e);
}
'
# Run the model
fit <- stan(model_code = model1, data = df, iter = 4000, chains = 2)
print(fit)
鲍勃卡彭特还简要评论了这个问题:
“[...]是的,你可以在分级设置中做同样的事情,但是你必须要小心,因为当你接近常态时,随着比例运行到无穷大,建模自由度可能会很棘手。 “
回答Bernd的问题,Luc解释了为什么他在模型代码中写了y ~ bernoulli_logit(10...
:
“在我提供的示例代码中,10是样本大小。您可能已经注意到玩具数据包含每个/单位的多个观察值(即每个单位10个观测值)。
Stan手册还提供了有关函数和抽样语句参数的广泛信息。“
答案 2 :(得分:1)
更新:我将johnmyleswhite示例翻译成Stan Synthax并不起作用。我不太了解Stan Synthax翻译代码。也许有人可以帮忙?以下是原始答案。
如果你查看jbaums提到的johnmyleswhite example,你会发现重要的代码是:
y[i] ~ dbern(p[i])
p[i] <- pt(z[i], 0, 1, 1)
z[i] <- a * x[i] + b
正如您所看到的,使用invlogit计算概率,他使用t分布(实际上,累积t)。在stan中,只需使用:
student_t_cdf
我不太了解Stan synthax,但我认为你可以使用类似下面的内容:
model {
y ~ bernoulli(theta);
theta <- student_t_cdf(df, mu, sigma)
mu <- beta_0 + beta_1 * x1 + beta_2 * x2;
}
请注意,您必须在df和sigma上放置先验。 Something like:
df_inv ~ uniform(0, 0.5);
df <- 1 / df_inv;
sigma_z <- sqrt((df-2)/df);
我会试着看看它是否有效。让我知道如果稍微调整一下我的答案就可以使它发挥作用。
答案 3 :(得分:1)
Stan 2.4参考手册第26页:
y ~ bernoulli(Phi( beta_0 + beta_1 * x1 + beta_2 * x2 ))
一般解决方案是y ~ bernoulli(link_function(eta))
,其中link_function
是,例如Phi
。恰好是一个特殊的函数bernoulli_logit
,它包含了这个功能,在数值上更稳定。
如果没有明确的原因,我建议阅读广义线性模型。维基百科页面不是一个糟糕的评论。