Skip to main content

prior-elicitation

Load when the user is choosing priors, running prior predictive checks, calling find_constrained_prior, using PreliZ, or otherwise eliciting domain knowledge into a Bayesian model. Covers weakly informative priors, constrained priors, sensitivity analysis, and elicitation workflows. Triggers include: prior selection, elicitation, find_constrained_prior, PreliZ, prior predictive, expert/informative priors, weakly informative priors, constrained priors.

الانتقال إلى التثبيت

معلومات المصدر

المستودع
pymc-labs/pymc-modeling
آخر نشاط في المصدر
٧ يونيو ٢٠٢٦ في ١٠:١٨
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٧
التفرعات
١

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

مستكشف الملفات
4 ملفات

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
prior-elicitation
description
Load when the user is choosing priors, running prior predictive checks, calling find_constrained_prior, using PreliZ, or otherwise eliciting domain knowledge into a Bayesian model. Covers weakly informative priors, constrained priors, sensitivity analysis, and elicitation workflows. Triggers include: prior selection, elicitation, find_constrained_prior, PreliZ, prior predictive, expert/informative priors, weakly informative priors, constrained priors.
# Prior Elicitation for PyMC Models ## Decision Flowchart: Choosing a Prior Strategy ``` Do you have domain expertise or expert access? ├── YES: Can the expert quantify beliefs precisely? │ ├── YES → Expert elicitation (SHELF protocol, PreliZ roulette/quartile) │ └── NO → Constrained priors (find_constrained_prior, PreliZ maxent) └── NO: Do you know the plausible scale of the parameter? ├── YES → Weakly informative priors (Normal, HalfNormal, Student-t) └── NO → Use prior predictive checks to calibrate └── Generate predictions → Do they cover plausible outcomes? ├── YES → Prior is acceptable └── NO → Tighten or widen prior, repeat ``` ### When to Use Each Strategy | Strategy | Use When | Example | |---|---|---| | Weakly informative | You know rough scale but not shape | `pm.Normal("beta", 0, 10)` for standardized predictors | | Constrained | "95% sure the value is between A and B" | `pm.find_constrained_prior(pm.Normal, ...)` | | MaxEnt | You have bounds and want least-informative prior | `preliz.maxent(preliz.Normal(), -1, 1, 0.94)` | | Expert-elicited | Domain expert provides quantiles or probabilities | SHELF protocol with PreliZ | | Hierarchical | Group-level parameters with partial pooling | `pm.Normal("mu_group", mu=mu_hyper, sigma=sigma_hyper)` | ## pm.find_constrained_prior Finds distribution parameters such that a specified mass falls within given bounds. ```python import pymc as pm # "I'm 95% sure the effect is between -2 and 2" params = pm.find_constrained_prior( pm.Normal, lower=-2, upper=2, mass=0.95, init_guess={"mu": 0, "sigma": 1}, ) # Returns: {"mu": 0.0, "sigma": 1.02} # Use directly in model with pm.Model() as model: beta = pm.Normal("beta", **params) ``` ### Common Patterns ```python # Positive parameter, 90% between 0.1 and 10 params = pm.find_constrained_prior( pm.LogNormal, lower=0.1, upper=10, mass=0.90, init_guess={"mu": 0, "sigma": 1}, ) # Rate parameter, 80% between 0.01 and 0.5 params = pm.find_constrained_prior( pm.Gamma, lower=0.01, upper=0.5, mass=0.80, init_guess={"alpha": 2, "mu": 0.1}, ) # Bounded parameter (probability), 95% between 0.2 and 0.8 params = pm.find_constrained_prior( pm.Beta, lower=0.2, upper=0.8, mass=0.95, init_guess={"alpha": 5, "beta": 5}, ) ``` See `references/find_constrained_prior.md` for full API details. ## PreliZ Integration PreliZ is a library for prior elicitation. It provides tools to translate domain knowledge into probability distributions. ### Maximum Entropy (maxent) Find the least-informative distribution consistent with constraints: ```python import preliz as pz # Least-informative Normal with 94% mass in [-1, 1] dist = pz.maxent(pz.Normal(), -1, 1, 0.94) # Least-informative HalfNormal with 94% mass below 5 dist = pz.maxent(pz.HalfNormal(), 0, 5, 0.94) # Use result in PyMC with pm.Model(): sigma = pm.HalfNormal("sigma", sigma=dist.sigma) ``` ### Roulette (chip-and-bin elicitation) Interactive method where an expert allocates "chips" to bins: ```python # Define bins and expert-allocated chip counts pz.roulette(x_min=0, x_max=100, nrows=10) # Opens interactive widget — expert distributes chips across bins # Returns fitted distribution ``` ### Predictive Finder (predictive_elicitation) Elicit priors by reasoning about observable predictions: ```python def my_model(x, beta0, beta1, sigma): mu = beta0 + beta1 * x return pz.Normal(mu=mu, sigma=sigma) # Expert specifies: "when x=5, y is typically between 10 and 30" pz.predictive_finder(my_model, target=pz.Normal()) ``` ### Quartile Method Specify distribution via expert-provided quartiles: ```python # Expert says: "median is 50, Q1 is 30, Q3 is 70" dist = pz.quartile(pz.Normal(), q1=30, q2=50, q3=70) ``` See `references/preliz.md` for comprehensive PreliZ reference. ## Prior Predictive Interpretation Checklist Always run prior predictive checks before sampling: ```python with model: prior_pred = pm.sample_prior_predictive(draws=500, random_seed=42) # prior_pred is a DataTree (ArviZ 1.0) prior_samples = prior_pred["prior"].ds prior_predictive = prior_pred["prior_predictive"].ds ``` ### What to Check 1. **Range of predictions**: Do simulated outcomes cover the plausible data range? - Plot: `az.plot_ppc_dist(prior_pred, group="prior_predictive", kind="ecdf")` 2. **Impossible values**: Are any simulated outcomes physically impossible? - Negative counts, probabilities outside [0,1], negative durations 3. **Scale**: Is the prior predictive spread reasonable relative to the data? - Too wide = vague, slow convergence. Too narrow = overly informative 4. **Shape**: Do simulated datasets look qualitatively like real data? - Bimodal when data is unimodal? Heavy tails when data is bounded? ### Red Flags - Prior predictive covers 10+ orders of magnitude — priors too vague - >10% of samples produce impossible values — wrong distribution family or scale - Prior predictive is concentrated on a narrow range far from data — prior is miscalibrated - All prior predictive samples look identical — prior is too tight (dogmatic) ## Expert Elicitation Workflow ### SHELF-like Protocol 1. **Define the parameter**: What does it represent? What are its units? 2. **Establish plausible range**: "What is the lowest/highest value you would expect?" 3. **Elicit quantiles**: "What value are you 25%/50%/75% sure the parameter is below?" 4. **Elicit tail behavior**: "Is there any chance of extreme values? How extreme?" 5. **Fit distribution**: Use `preliz.quartile()` or `pm.find_constrained_prior()` 6. **Validate**: Show the fitted distribution back to the expert for confirmation 7. **Prior predictive check**: Generate predictions and ask "do these look realistic?" For prior predictive checking workflows in PyMC, see the [pymc-modeling skill](../pymc-modeling/SKILL.md). ### Translating Domain Knowledge | Expert says | Translation | |---|---| | "Roughly between A and B" | `find_constrained_prior(..., lower=A, upper=B, mass=0.90)` | | "Usually around X, rarely above Y" | LogNormal or Gamma with median near X, 95th percentile near Y | | "Positive, with diminishing probability for large values" | HalfNormal, Exponential, or HalfCauchy | | "Could go either way, maybe 50-50" | `pm.Beta("p", alpha=1, beta=1)` or `pm.Normal("effect", 0, ...)` | | "No more than X in absolute value" | `pm.TruncatedNormal` or `pm.Uniform(-X, X)` | See `references/elicitation_workflows.md` for detailed protocols. ## Sensitivity Analysis ### Checking Prior Sensitivity Conclusions are robust if they hold under different reasonable priors. ```python # Fit model with original priors with pm.Model() as model_original: beta = pm.Normal("beta", 0, 1) ... idata_orig = pm.sample() # Fit with wider priors with pm.Model() as model_wide: beta = pm.Normal("beta", 0, 10) ... idata_wide = pm.sample() # Fit with different family with pm.Model() as model_robust: beta = pm.StudentT("beta", nu=3, mu=0, sigma=1) ... idata_robust = pm.sample() # Compare posteriors visually import arviz as az az.plot_forest( [idata_orig, idata_wide, idata_robust], model_names=["Original", "Wide", "Robust"], var_names=["beta"], ) ``` ### What to Report - If posteriors are similar across priors: conclusions are data-driven (robust) - If posteriors differ substantially: conclusions are prior-sensitive — report sensitivity - Always compare the posterior-to-prior contraction: strong contraction = data is informative ### Power-scaling Sensitivity For systematic sensitivity analysis, scale the prior log-density by a factor alpha: ```python # alpha > 1: stronger prior influence # alpha < 1: weaker prior influence # Compare posteriors across alpha in [0.5, 0.75, 1.0, 1.25, 1.5] ``` When posteriors are stable across alpha values, the inference is robust to prior choice.
عرض على GitHub