0Pricing
R Academy · درس

كتابة نماذج Stan في R

حدّد كتل البيانات والمعاملات وكتلة النموذج باستخدام صياغة Stan

كتابة نماذج Stan في R درس مجاني في R Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في R Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة R Academy 4 دروس في المجموع.

ما هو Stan؟

Stan هي لغة برمجة احتمالية للنمذجة الإحصائية البايزية. ويمثّل RStan واجهة R إلى Stan. تكتب النموذج بلغة Stan (شبيهة بـ C++)، ثم يترجمه Stan إلى شيفرة C++ فعّالة تنفّذ أخذ عينات مونتِ كارلو الهاملتوني (HMC) لتقريب التوزيع اللاحق.

# Stan installation check
library(rstan)

# Check version
cat('RStan version:', as.character(packageVersion('rstan')), '\n')

# Enable parallel chains
options(mc.cores = parallel::detectCores())

# Reuse compiled models across sessions
rstan_options(auto_write = TRUE)

cat('Stan ready. Cores:', parallel::detectCores(), '\n')

بنية نموذج Stan

يمكن أن يحتوي نموذج Stan على ست كتل مسمّاة كحد أقصى: data وtransformed data وparameters وtransformed parameters وmodel وgenerated quantities. والكتل الأساسية الثلاث هي data وparameters وmodel.

library(rstan)

# Stan model as a character string in R
stan_code <- '
data {
  int<lower=0> N;       // number of observations
  vector[N] x;          // predictor
  vector[N] y;          // response
}
parameters {
  real alpha;           // intercept
  real beta;            // slope
  real<lower=0> sigma;  // noise (must be positive)
}
model {
  // Priors
  alpha ~ normal(0, 10);
  beta  ~ normal(0, 10);
  sigma ~ exponential(1);

  // Likelihood
  y ~ normal(alpha + beta * x, sigma);
}
'

cat('Stan model defined as a string in R\n')
cat('Blocks: data, parameters, model\n')

data{}: تعريف بيانات الإدخال

تعرّف كتلة data جميع البيانات الخارجية التي يتلقاها النموذج من R. وتشمل الأنواع int وreal وvector[N] وmatrix[M,N] وarray. وتُفحَص القيود مثل <lower=0> أثناء التشغيل.

library(rstan)

# Comprehensive data block examples
data_block_examples <- '
data {
  // Scalars
  int<lower=1> N;               // at least 1 observation
  int<lower=2> K;               // at least 2 groups

  // Constrained scalars
  real<lower=0, upper=1> rate;  // probability

  // Vectors
  vector[N] y;                  // continuous response
  array[N] int<lower=0, upper=1> z;  // binary outcomes

  // Matrix
  matrix[N, K] X;               // design matrix

  // Integer array
  array[N] int group;           // group membership 1..K
}
'

cat(data_block_examples)

parameters{}: أنواع المعلمات

تُصرّح كتلة parameters بالقيم المجهولة التي سيُجري Stan أخذ عينات منها. وتحدد القيود في هذه الكتلة فضاء المعلمات: <lower=0> للكميات الموجبة، و<lower=0, upper=1> للاحتمالات. ويطبّق Stan تلقائيًا تصحيحات ياكوبيان لاحتمال اللوغاريتم للمعلمات المقيّدة.

library(rstan)

# Common parameter declarations
param_examples <- '
parameters {
  // Unconstrained
  real mu;                        // mean
  vector[K] beta;                 // regression coefficients

  // Positive (sigma, lambda, variance)
  real<lower=0> sigma;
  real<lower=0> lambda;

  // Probability
  real<lower=0, upper=1> theta;

  // Simplex (sums to 1, for mixture weights)
  simplex[K] pi;

  // Correlation matrix
  corr_matrix[K] Omega;

  // Cholesky factor of covariance
  cholesky_factor_cov[K] L_Sigma;
}
'
cat(param_examples)

model{}: التوزيعات السابقة ودالة الإمكان

تراكم كتلة model الاحتمال اللوغاريتمي اللاحق باستخدام صياغة ~ (التلدة). وتُعدّ y ~ normal(mu, sigma) اختصارًا لإضافة لوغاريتم دالة كثافة الاحتمال للتوزيع الطبيعي إلى target. ويمكنكم كتابة زيادات الاحتمال اللوغاريتمي صراحةً باستخدام target += normal_lpdf(y | mu, sigma).

library(rstan)

model_block_example <- '
model {
  // --- Priors ---
  mu    ~ normal(0, 10);          // weakly informative
  sigma ~ cauchy(0, 2.5);         // half-Cauchy for scale
  beta  ~ normal(0, 1);           // standardised coefficients

  // --- Likelihood ---
  // Tilde notation (most common)
  y ~ normal(mu + X * beta, sigma);

  // Equivalent explicit notation:
  // target += normal_lpdf(y | mu + X * beta, sigma);

  // For loop (less common but valid)
  // for (i in 1:N)
  //   target += normal_lpdf(y[i] | mu, sigma);
}
'
cat(model_block_example)

ملاءمة نموذج طبيعي بسيط

فيما يلي سير عمل كامل ومختصر باستخدام Stan: تعريف سلسلة النموذج، وتجهيز قائمة البيانات، واستدعاء stan()، ثم فحص النتائج باستخدام print(). يترجم Stan النموذج في المرة الأولى، ثم يخزّن النسخة المترجمة مؤقتًا للاستخدام في عمليات التشغيل اللاحقة.

library(rstan)

# Stan model: estimate mean and SD of a normal distribution
normal_model <- '
data {
  int<lower=0> N;
  vector[N] y;
}
parameters {
  real mu;
  real<lower=0> sigma;
}
model {
  mu    ~ normal(0, 10);
  sigma ~ exponential(0.1);
  y     ~ normal(mu, sigma);
}
'

# Simulate data
set.seed(42)
y_data <- rnorm(50, mean = 5, sd = 2)

# Fit the model
fit <- stan(
  model_code = normal_model,
  data       = list(N = length(y_data), y = y_data),
  chains     = 2,
  iter       = 1000,
  warmup     = 500,
  refresh    = 0  # suppress iteration output
)

print(fit, pars = c('mu', 'sigma'))

الانحدار الخطي في Stan

يجعل Stan الانحدار الخطي البايزي مباشرًا: حدّدوا توزيعات سابقة طبيعية للمعاملات، وتوزيعًا أُسّيًا أو توزيعًا نصف-كوشي للمعلمة sigma. ويوفّر التوزيع اللاحق توزيعًا كاملًا لعدم اليقين لكل معامل، وليس مجرد تقديرات نقطية.

library(rstan)

lin_reg_model <- '
data {
  int<lower=0> N;
  vector[N] x;
  vector[N] y;
}
parameters {
  real alpha;
  real beta;
  real<lower=0> sigma;
}
model {
  alpha ~ normal(0, 10);
  beta  ~ normal(0, 10);
  sigma ~ exponential(1);
  y ~ normal(alpha + beta * x, sigma);
}
generated quantities {
  vector[N] y_rep;  // posterior predictive
  for (i in 1:N)
    y_rep[i] = normal_rng(alpha + beta * x[i], sigma);
}
'

set.seed(7)
n <- 80
x <- rnorm(n); y <- 2 + 3 * x + rnorm(n, 0, 1)

fit <- stan(model_code = lin_reg_model,
            data = list(N = n, x = x, y = y),
            chains = 2, iter = 1000, refresh = 0)
print(fit, pars = c('alpha', 'beta', 'sigma'))

كتلة transformed parameters{}

تحسب كتلة transformed parameters الكميات المشتقة من المعلمات التي أُخذت عيناتها. وتفيد هذه الكميات في تمثيل النماذج بطريقة مستقرة عدديًا، مثل تحليل تشولسكي والتحويلات اللوغاريتمية، مع الحفاظ على قابلية تفسير المعلمات الأساسية.

library(rstan)

# Model with transformed parameters
trans_param_example <- '
data {
  int<lower=0> N;
  array[N] int<lower=0> y;  // counts
}
parameters {
  real log_lambda;           // work in log space for stability
}
transformed parameters {
  real<lower=0> lambda;
  lambda = exp(log_lambda);  // transform back to original scale
}
model {
  log_lambda ~ normal(1, 2);  // prior on log scale
  y ~ poisson(lambda);
}
'

set.seed(42)
y_counts <- rpois(30, lambda = 5)

fit_poisson <- stan(
  model_code = trans_param_example,
  data       = list(N = length(y_counts), y = y_counts),
  chains     = 2, iter = 1000, refresh = 0
)
print(fit_poisson, pars = c('log_lambda', 'lambda'))

كتلة generated quantities{}

تُنفَّذ كتلة generated quantities بعد أخذ العينات لحساب كميات إضافية، مثل عينات التنبؤ اللاحق (y_rep)، والاحتمال اللوغاريتمي للتحقق المتقاطع LOO-CV، أو المعلمات المحوّلة اللازمة للتلخيصات. وتُؤخذ القيم هنا من توزيع التنبؤ اللاحق.

library(rstan)

# Use generated quantities for posterior predictive checks
model_with_gq <- '
data {
  int<lower=0> N;
  vector[N] y;
}
parameters {
  real mu;
  real<lower=0> sigma;
}
model {
  mu    ~ normal(0, 10);
  sigma ~ exponential(0.5);
  y     ~ normal(mu, sigma);
}
generated quantities {
  vector[N] y_rep;           // replicated datasets
  real mean_y_rep;           // mean of replicated data
  for (i in 1:N)
    y_rep[i] = normal_rng(mu, sigma);
  mean_y_rep = mean(y_rep);
}
'

set.seed(1)
y_obs <- rnorm(40, 3, 1.5)
fit <- stan(model_code = model_with_gq,
            data = list(N = length(y_obs), y = y_obs),
            chains = 2, iter = 1000, refresh = 0)
print(fit, pars = c('mu', 'sigma', 'mean_y_rep'))

تمرير البيانات من R إلى Stan

الوسيط data في stan() هو قائمة R مُسمّاة. ويجب أن تطابق الأسماء تمامًا أسماء المتغيرات المعلنة في كتلة data{} في Stan. وتتحول المتجهات إلى vector[N] في Stan، والأعداد الصحيحة إلى int، ومصفوفات R إلى matrix[M,N] في Stan.

library(rstan)

# Data preparation: names must match Stan data block exactly
set.seed(42)
n <- 60
x1 <- rnorm(n)
x2 <- rnorm(n)
y  <- 1.5 + 2 * x1 - 0.8 * x2 + rnorm(n, 0, 0.5)

# Build the design matrix
X <- cbind(x1, x2)  # 60 x 2 matrix

# Named list passed to stan(data = ...)
stan_data <- list(
  N = n,          # int
  K = ncol(X),    # int
  X = X,          # matrix[N, K]
  y = y           # vector[N]
)

cat('Stan data list elements:\n')
for (nm in names(stan_data)) {
  cat(' ', nm, ': class =', class(stan_data[[nm]]),
      'dim =', paste(dim(stan_data[[nm]]), collapse = 'x'),
      '\n')
}

عرض النموذج المترجم

بعد الملاءمة، استخدموا print(fit) لعرض التلخيصات اللاحقة (المتوسط، وse_mean، والانحراف المعياري، والكميات، وRhat، وn_eff) لجميع المعلمات. واستخدموا stan_plot(fit) لعرض مخطط فواصل بصري، وtraceplot(fit) لتقييم امتزاج السلاسل.

library(rstan)

# Reuse the simple normal model from scene 6
normal_model <- '
data { int<lower=0> N; vector[N] y; }
parameters { real mu; real<lower=0> sigma; }
model {
  mu ~ normal(0, 10);
  sigma ~ exponential(0.1);
  y ~ normal(mu, sigma);
}
'

set.seed(5)
fit <- stan(model_code = normal_model,
            data = list(N = 50, y = rnorm(50, 7, 3)),
            chains = 2, iter = 1000, refresh = 0)

# Detailed summary table
print(fit)

# Extract as data frame
posterior_df <- as.data.frame(fit)
cat('\nPosterior samples shape:', nrow(posterior_df),
    'rows x', ncol(posterior_df), 'cols\n')

تحقق سريع

في نموذج Stan، تريدون تقييد معلمة لتكون موجبة تمامًا، مثل الانحراف المعياري. أي تصريح مما يلي صحيح؟

مراجعة: كتابة نماذج Stan

أهم النقاط:

  • يتكون نموذج Stan من ثلاث كتل أساسية: data{} وparameters{} وmodel{}
  • القيود: <lower=0> و<upper=1> و<lower=0, upper=1> للاحتمالات
  • الأنواع: int وreal وvector[N] وmatrix[M,N] وsimplex[K]
  • كتلة النموذج: استخدموا صياغة التلدة y ~ normal(mu, sigma) للتوزيعات السابقة ودالة الإمكان
  • تُستخدم transformed parameters{} للكميات المشتقة، وgenerated quantities{} لما بعد أخذ العينات
  • مرّروا البيانات بوصفها قائمة R مُسمّاة، مع مطابقة أسماء كتل Stan تمامًا
  • تخزّن rstan_options(auto_write = TRUE) النماذج المترجمة مؤقتًا
library(rstan)

# Stan model skeleton
model_skeleton <- '
data    { int N; vector[N] y; }
parameters { real mu; real<lower=0> sigma; }
model   { mu ~ normal(0,10); sigma ~ exponential(1); y ~ normal(mu, sigma); }
'
cat(model_skeleton)
cat('\nFit with: stan(model_code = model_skeleton, data = list(N=..., y=...), chains=4)\n')

الأسئلة الشائعة

هل درس «كتابة نماذج Stan في R» مجاني؟

نعم — نص درس «كتابة نماذج Stan في R» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة R Academy، انتقل إلى CoddyKit PRO. تتضمن دورة R Academy 4 دروس في المجموع.

ماذا ستتعلم في «كتابة نماذج Stan في R»؟

حدّد كتل البيانات والمعاملات وكتلة النموذج باستخدام صياغة Stan تتمرن على R Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ R Academy؟

لا تُشترط خبرة سابقة. R Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.

كم من الوقت يستغرق درس «كتابة نماذج Stan في R»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس R Academy هذا؟

نعم. كل درس في R Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. مقدمة إلى التفكير البايزي
  2. كتابة نماذج Stan في R
  3. أخذ عينات MCMC وتشخيصها
  4. فحوصات التنبؤ البعدي
← العودة إلى R Academy