第19期 ⭐⭐⭐ 进阶

贝叶斯统计建模

使用PyMC进行概率编程,从模型定义到后验分析的完整流程

⏱️ 学习时间:约30分钟 🎲 核心技能:PyMC + statsmodels
⚠️
免责声明: 本内容仅供医学学习参考,不作为临床诊断依据。 实际临床决策请结合患者具体情况和多学科意见。
🎯

技能简介

贝叶斯统计提供了一种直观的参数不确定性量化方法,相比传统频率学派方法, 它能够直接给出参数的概率分布解释,并允许将先验知识纳入模型。

本教程将介绍如何使用 PyMC 进行概率编程, 以及 statsmodels 进行传统统计建模, 并对比两种方法的结果差异。

📊 贝叶斯 vs 频率学派对比

方面 贝叶斯 频率学派
参数解释 概率分布 点估计
不确定性 可信区间 置信区间
先验信息 ✓ 可以纳入 ✗ 不考虑
小样本 表现更好 可能不稳定
计算方式 MCMC采样 解析解/优化

🧠 开始贝叶斯建模前先定义这 4 件事

临床问题与决策目标

先明确你是要做风险预测、治疗效应评估还是亚组比较,以及最终决策阈值是什么,否则后验概率很难转成可解释结论。

结局类型与似然函数

二分类、计数、生存时间和连续型结局对应的 likelihood 完全不同,模型定义前就要把 outcome 尺度讲清楚。

先验来源与敏感性分析

要提前决定先验来自文献、专家经验还是弱信息设定,并计划至少一轮敏感性分析,避免结论被单一先验绑架。

采样预算与收敛标准

链数、draws、warmup、可接受的 R-hat/ESS 和 divergence 处理策略要先想好,不然容易跑了很久却拿到不可用结果。

📦 一套可汇报的贝叶斯分析至少应交付这 4 样

模型公式与先验清单

别人需要知道你用了什么 likelihood、哪些协变量、先验如何设置,以及它们为什么合理。

收敛与采样诊断结果

至少报告 R-hat、ESS、trace plot 和 divergence 情况,否则后验均值再漂亮也没有解释价值。

后验总结与不确定性可视化

建议整理后验均值、中位数、95% 可信区间以及关键参数的密度图/森林图,方便直接进汇报或论文。

预测与决策解释

最好说明后验概率如何影响临床判断,并给出与频率学派模型的对照,帮助团队理解贝叶斯带来的增量价值。

💡 使用场景

🏥

小样本临床研究

当样本量较小时,贝叶斯方法可以通过先验信息提高估计稳定性

📊

不确定性量化

需要给出预测的完整概率分布,而非单一置信区间

🔬

临床试验设计

适应性试验设计需要实时更新后验概率

🧬

复杂层次模型

多中心研究、纵向数据等需要层次结构的数据

🛠️ Step 1: 模型定义

首先使用PyMC定义一个贝叶斯逻辑回归模型,用于预测心衰患者的30天死亡率。 我们使用弱信息先验(weakly informative priors)避免对结果产生过大影响。

import pymc as pm
import numpy as np
import pandas as pd

# 准备数据
# X: 特征矩阵 (n_samples, n_features)
# y: 二分类结局 (0/1)

with pm.Model() as bayesian_model:
  # 1. 定义先验分布
  # 使用正态分布作为系数的弱信息先验
  intercept = pm.Normal('intercept', mu=0, sigma=10)
  beta = pm.Normal('beta', mu=0, sigma=10, shape=X.shape[1])

  # 2. 定义线性预测器
  logit_p = intercept + pm.math.dot(X, beta)

  # 3. 定义似然函数
  # 使用Bernoulli分布(二分类)
  y_obs = pm.Bernoulli('y_obs',
             logit_p=logit_p,
             observed=y)

  # 4. 查看模型结构
  pm.model_to_graphviz(bayesian_model)

💡 先验选择建议

  • 弱信息先验:N(0, 10) 或 N(0, 5),影响小但正则化
  • 无信息先验:N(0, 100) 或更大,让数据说话
  • 正则化先验:如Laplace(0, 1),类似LASSO
  • • 避免使用过于强的先验,除非有充分的先验知识

🛠️ Step 2: MCMC采样

使用马尔可夫链蒙特卡洛(MCMC)方法从后验分布中采样。 PyMC默认使用NUTS(No-U-Turn Sampler)算法,这是HMC的高效变体。

with bayesian_model:
  # 1. MCMC采样
  trace = pm.sample(
    draws=2000,     # 每条链的采样次数
    tune=1000,      # 调谐步数(burn-in)
    chains=4,      # 链的数量
    cores=4,      # 并行计算
    return_inferencedata=True
  )

  # 2. 检查收敛性
  # R-hat < 1.05 表示收敛良好
  print(pm.summary(trace, round_to=2))

  # 3. 可视化采样轨迹
  pm.plot_trace(trace)
  pm.plot_posterior(trace)

📌 收敛性诊断指标

  • R-hat:< 1.05 表示收敛,< 1.01 更佳
  • ESS:有效样本量,越大越好(>400通常可接受)
  • 轨迹图:应像"毛毛虫",无规律波动
  • 自相关图:快速下降到0表示采样效率高

🛠️ Step 3: 后验分析

后验分布包含了参数的所有信息。我们可以计算各种统计量,并进行后验预测检验。

import arviz as az

# 1. 提取后验摘要
summary = pm.summary(trace)
print(summary)

# 输出示例:
#      mean  sd hdi_3% hdi_97% ...
# intercept -2.1 0.5  -3.0  -1.2
# beta[0]   0.8 0.3  0.3   1.3

# 2. 计算95%可信区间 (HDI)
# HDI: Highest Density Interval
hdi = pm.hdi(trace, hdi_prob=0.95)

# 3. 后验预测检验
with bayesian_model:
  # 生成后验预测样本
  ppc = pm.sample_posterior_predictive(trace)

  # 比较观测数据和预测数据
  az.plot_ppc(az.from_pymc3(posterior_predictive=ppc, model=bayesian_model))

⚠️ 可信区间 vs 置信区间

  • 可信区间 (Credible Interval):参数有95%概率落在该区间内(贝叶斯)
  • 置信区间 (Confidence Interval):重复抽样95%的区间会包含真值(频率学派)
  • • 贝叶斯的解释更直观,符合大多数研究者的直觉

🛠️ Step 4: 与频率学派模型比较

使用statsmodels拟合传统的逻辑回归模型,并与贝叶斯结果进行比较。

import statsmodels.api as sm
import statsmodels.formula.api as smf

# 1. 使用statsmodels拟合逻辑回归
X_sm = sm.add_constant(X) # 添加截距项
model_freq = sm.Logit(y, X_sm)
result_freq = model_freq.fit()

# 2. 查看结果
print(result_freq.summary())

# 3. 比较系数估计
comparison = pd.DataFrame({
  '贝叶斯后验均值': summary['mean'],
  '频率学派估计': result_freq.params,
  '差异': summary['mean'] - result_freq.params
})
print(comparison)

💡 结果解读

  • • 当样本量较大时,两种方法的点估计通常很接近
  • • 贝叶斯方法提供完整的后验分布,而非单一估计值
  • • 小样本时,先验信息会使贝叶斯估计更稳定
  • • 贝叶斯方法可以自然处理复杂模型结构

🛠️ Step 5: 预测与决策支持

使用拟合好的贝叶斯模型进行新样本预测,并量化预测的不确定性。

with bayesian_model:
  # 1. 对新数据进行预测
  X_new = ... # 新样本特征

  # 生成后验预测分布
  ppc_new = pm.sample_posterior_predictive(
    trace,
    predictions=True
  )

  # 2. 计算预测概率
  pred_prob = ppc_new['y_obs'].mean(axis=0)

  # 3. 预测不确定性
  pred_std = ppc_new['y_obs'].std(axis=0)

  # 4. 风险分层示例
  risk_categories = []
  for prob, uncertainty in zip(pred_prob, pred_std):
    if prob > 0.7:
      risk_categories.append('高风险')
    elif prob > 0.3:
      risk_categories.append('中风险')
    else:
      risk_categories.append('低风险')

🧯 贝叶斯分析最危险的 4 个误区

把可信区间写成“结果已经被证明”

95% 可信区间描述的是在当前模型与先验下参数分布的不确定性,并不等于结论绝对正确或具有因果性。

先验设定很强,却不做敏感性分析

如果不同先验下结论会明显变化,就必须诚实报告这种不稳定性,而不是只展示最符合预期的那一版。

忽略收敛诊断和 divergence

MCMC 没收敛时,后验分布和概率陈述都不可信;R-hat、ESS 和采样轨迹不是可选项,而是结果有效性的底线。

默认“贝叶斯一定比频率学派更高级”

贝叶斯并不是自动更好,真正关键的是问题匹配度、模型检查和解释清晰度,而不是方法标签本身。

⚠️ 注意事项

1.

先验选择很重要

过强的先验可能主导结果,过弱的先验可能导致收敛问题。建议使用弱信息先验作为起点。

2.

检查模型收敛

不要忽略R-hat和ESS等诊断指标。未收敛的模型结果不可信。

3.

计算成本较高

贝叶斯分析通常比频率学派方法需要更多计算资源,特别是复杂模型。

4.

模型验证必不可少

使用后验预测检验、交叉验证等方法验证模型预测能力。

🔗 相关技能

📦

下载完整代码包

包含:示例代码、数据文件、结果图表 · 22个文件 · 1.1MB

立即下载

💡 代码包内含 README.md 文档,包含环境配置和运行说明。解压后即可使用。