Monte Carlo Dropout( MC Dropout)用于不确定性估计的数学基础,它背后的理论来自一篇非常有影响力的论文:
"Dropout as a Bayesian Approximation: Representing Model Uncertainty in Deep Learning " — Yarin Gal & Zoubin Ghahramani, ICML 2016
在贝叶斯学习中,预测的目标是所谓的后验预测分布(posterior predictive distribution) :
- 也就是:在所有可能的参数下,对应的预测加权平均。但这个积分太复杂 → 所以我们用 Dropout + 多次 forward 来采样近似这个积分。因此,是可计算的,即预测不确定性是可直接计算的。
🎯 多次 forward(每次用不同 Dropout mask):
- 得到多个模型参数不同的 softmax 结果 → 可以计算平均(期望预测)、方差(不确定性)、熵 → 评价不确定程度。
- 实际上就是:
总结:利用Dropout 模拟多个可能模型对当前输入的预测,进而估计整体的预测分布。
🧠 不确定性分解公式回顾:
总预测不确定性(预测熵):
这个公式可以直译为:
总的不确定性 = 模型之间预测差异有多大+模型内部每次预测平均有多不确定
注意 总预测不确定性(预测熵)是可以直接计算的:
🎯 一、什么是 Aleatoric(期望熵)?
这部分的直觉是:
- 假设我们对一个输入 xx,从多个模型(Dropout 实例)中做出 T 次预测;
- 每个模型都给出自己的预测概率 ,其中有些预测“摇摆”,有些预测“坚定”;
- 然后我们看每次预测中自己有多不确定(预测分布的 熵 ) ,再对这些熵取平均。
🔍 关键理解:
即便模型本身很稳定(不同模型预测结果都差不多),但预测分布本身也可能非常模糊(比如分布为
[0.5, 0.5]) ⇒ 说明是 数据本身就模糊、含糊、不可预测 ⇒ 属于 Aleatoric 不确定性。
🧪 类比:
多个医生(模型)独立看了同一张模糊的 X 光片(难以判断),他们一致地觉得不确定 ⇒ 病人问题来自于“图像本身太模糊”。
🧠 二、什么是 Epistemic(互信息)?
即:总预测熵 减去平均单个模型预测熵。
这部分衡量的是:
-
不同模型预测的结果之间差异有多大;
-
如果模型之间意见不合(有的预测 A,有的预测 B,有的预测 C),那说明:
- 模型对这个输入还没“学明白”;
- 是模型缺乏知识(见得少)导致的 ⇒ 属于 Epistemic 不确定性。
🧪 类比:
多个医生独立看了一张 X 光图,有的说“有病”,有的说“没病” ⇒ 模型之间不一致,说明医生之间缺乏共同知识 ⇒ 是模型的问题,不是图像的问题。
🔬 三、一个图示直觉(分类任务)
假设你输入图像 x,多次 MC Dropout 得到这些分布(横轴为类别):
情况一:模型稳定但每次都不确定(高 Aleatoric)
| 模型1 | 模型2 | 模型3 |
|---|---|---|
| [0.5, 0.5] | [0.5, 0.5] | [0.5, 0.5] |
- 每次模型都“自己不确定” → 高 Aleatoric
- 但每次模型都一样 → 低 Epistemic
- 总不确定性 ≈ 每次都模糊
情况二:模型都很自信但互相预测不同(高 Epistemic)
| 模型1 | 模型2 | 模型3 |
|---|---|---|
| [0.9, 0.1] | [0.2, 0.8] | [0.1, 0.9] |
- 每次模型都很确定 → Aleatoric 很低
- 但预测结果差异大 → 模型之间不一致 → Epistemic 高
- 总不确定性 ≈ 来自模型意见不合
总结口语解释
| 不确定性类型 | 来自哪里? |
|---|---|
| Aleatoric | 每次模型预测“自己都不太确定” |
| Epistemic | 模型之间意见不合,不一致 |
✅ 四、代码示例:用 MC Dropout 分离 Aleatoric 和 Epistemic 不确定性(分类任务)
要明确区分 Epistemic(模型)和 Aleatoric(数据)不确定性,你需要使用 贝叶斯建模技术(例如 MC Dropout 或 Deep Ensembles),并对每个输入进行多次预测,从而统计模型行为的分布特性。
以下是一个在 分类任务中使用 MC Dropout 的完整示例(PyTorch 实现):
🔧 假设条件:
- 你有一个分类模型,最后一层是
nn.Softmax。 - 模型中包含 Dropout 层,且推理阶段需保持 Dropout 开启(MC Dropout)。
- 模型每次预测都输出
[batch_size, num_classes]的概率分布。
🧩 步骤 1:多次预测(T 次)
def enable_dropout(model):
"""启用 Dropout 的 inference 阶段行为"""
for m in model.modules():
if isinstance(m, nn.Dropout):
m.train()
def mc_predictions(model, x, T=20):
"""返回 T 次 MC Dropout 预测的 softmax 概率 [T, B, C]"""
model.eval()
enable_dropout(model)
preds = []
for _ in range(T):
logits = model(x) # 输出 logits
probs = torch.softmax(logits, dim=-1)
preds.append(probs)
return torch.stack(preds) # shape: [T, B, C]
🧮 步骤 2:分解不确定性
def compute_uncertainty(mc_probs):
"""
mc_probs: [T, B, C] — T 次 softmax 概率
返回:
- predictive_entropy: [B]
- expected_entropy: [B]
- epistemic: [B]
- aleatoric: [B]
"""
mean_probs = mc_probs.mean(dim=0) # [B, C]
log_mean_probs = torch.log(mean_probs + 1e-8)
# 总预测不确定性(熵)
predictive_entropy = - (mean_probs * log_mean_probs).sum(dim=-1) # [B]
# 每次预测的熵
log_mc_probs = torch.log(mc_probs + 1e-8)
entropies_per_sample = - (mc_probs * log_mc_probs).sum(dim=-1) # [T, B]
expected_entropy = entropies_per_sample.mean(dim=0) # [B]
# 模型不确定性(Epistemic) = predictive_entropy - expected_entropy
epistemic = predictive_entropy - expected_entropy
aleatoric = expected_entropy
return {
'predictive_entropy': predictive_entropy,
'epistemic': epistemic,
'aleatoric': aleatoric
}
✅ 输出解释举例:
# 你输入一个样本 x 得到的结果
{
'predictive_entropy': tensor([0.98]),
'epistemic': tensor([0.65]),
'aleatoric': tensor([0.33])
}
说明这个样本有:
- 总不确定性 0.98;
- 其中 65% 来源于模型缺乏知识(模型不确定性);
- 33% 是数据本身模糊(数据不确定性)。