You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在R与Stan中提取Logistic回归模型generated quantities块预测值并与真实观测对比的方法验证及简便实现咨询

Question: Extract and Compare Generated Quantities Predictions with Observations in Stan

I want to extract the predictions from the generated quantities block in my Stan fit and compare them to the true observed values, but I haven't found a straightforward solution. Here's my implementation for a simple logistic regression model:

library(rstan)
library(tidyverse)
library(boot)
rstan_options(auto_write = TRUE)
options(mc.cores = parallel::detectCores())
T <- 40
set.seed(123)
x <- sort(runif(T, 0, 10))
alpha <- 1
beta <- 0.2
logit_p <- alpha + beta * x
p <- inv.logit(logit_p)
y <- rbinom(T, 1, p)
model_code <- "
data {
  int<lower=0> N;
  vector[N] x;
  int<lower=0,upper=1> y[N];
}
parameters {
  real alpha;
  real beta;
}
model {
  y ~ bernoulli_logit(alpha + beta * x);
}
generated quantities {
  vector[N] z;
  for (n in 1:N) z[n] = bernoulli_logit_rng(alpha + beta * x[n]);
}"
model_data <- list(
  N = T,
  x = x,
  y = y
)
stan_run <- stan(
  data = model_data,
  model_code = model_code
)
posterior <- rstan::extract(stan_run)
df <- as.data.frame(posterior$z)
df <-df %>% summarise(across(everything(.), ~ ifelse(length(.[which(. == 1)]) > length(.[which(. == 0)]), 1, 0)))

I'm not sure if the above implementation is correct, and I'm wondering if there's a more direct and simpler way to do this.


Answer

Great question! Your current approach is technically correct, but there are cleaner, more idiomatic ways to extract and summarize these posterior predictions for comparison with your observed values. Let's break down the improvements:

1. Simplify Your Majority-Vote Calculation

Your existing code for getting majority-vote predictions works, but it can be streamlined using vectorized operations (faster and more readable for this task):

# Extract posterior draws of your generated z values
posterior_z <- posterior$z

# Calculate the proportion of draws where z == 1 for each observation
pred_probs <- colMeans(posterior_z)

# Get majority-vote predictions (matches your original logic)
pred_majority <- ifelse(pred_probs > 0.5, 1, 0)

This achieves the exact same result as your dplyr pipeline but cuts out unnecessary steps, which is especially helpful for larger datasets.

2. Use Stan's Built-in posterior_predict() (No Custom Generated Quantities Needed)

If you don't need the custom z variable in your Stan code, you can skip defining it in the generated quantities block entirely. Stan's posterior_predict() function automatically generates posterior predictive draws for your outcome variable based on the model's likelihood:

# Generate posterior predictive draws directly from the fit
posterior_pred <- posterior_predict(stan_run)

# Calculate prediction probabilities and majority votes
pred_probs <- colMeans(posterior_pred)
pred_majority <- ifelse(pred_probs > 0.5, 1, 0)

This is a more straightforward workflow because you don't have to manually code the predictive draw logic in your Stan model—posterior_predict() handles that for you.

3. Compare Predictions to True Observations

Once you have your predictions, combining them with the true values for analysis is easy. Here's how to create a comparison dataframe and calculate basic metrics:

comparison_df <- tibble(
  x = x,
  true_y = y,
  pred_success_prob = pred_probs,
  pred_majority = pred_majority
)

# Check the first few rows of the comparison
head(comparison_df)

# Calculate overall prediction accuracy
accuracy <- mean(comparison_df$pred_majority == comparison_df$true_y)
cat(paste0("Prediction Accuracy: ", round(accuracy * 100, 2), "%\n"))

4. Visualize the Comparison

A plot helps you intuit how well the model's predictions align with reality. This plot shows true values, majority-vote predictions, and the model's predicted probability of success:

ggplot(comparison_df, aes(x = x)) +
  geom_point(aes(y = true_y), color = "navy", alpha = 0.7, size = 2) +
  geom_point(aes(y = pred_majority), color = "firebrick", alpha = 0.7, shape = 1, size = 2) +
  geom_line(aes(y = pred_success_prob), color = "forestgreen", linewidth = 1) +
  labs(
    x = "Predictor Variable x",
    y = "Outcome (1 = Success)",
    title = "True Values vs. Posterior Predictions",
    subtitle = "Navy = True Observation, Red = Majority Vote, Green = Predicted Success Probability"
  ) +
  theme_minimal()

Quick Validation of Your Original Code

For what it's worth, your original method does produce correct majority-vote predictions—the simplified version above just makes the code more efficient and readable. Using posterior probabilities (instead of just majority votes) also gives you more insight into the model's uncertainty for each prediction, which is often more useful than a binary yes/no.

内容的提问来源于stack exchange,提问作者Amin Shn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 12:52:33