读完这篇,你能做什么
能根据原有判断(先验)和各假设下证据出现的可能性(似然)计算离散后验,解释低发生率场景,并拒绝不可能证据与非法概率。
学习理由、准备要求与知识点
为什么学它
模型预测和实验结果都有不确定性。把“故障时会报警”误读成“报警就多半故障”,就会得出错误判断。
先读这些内容
知识点清单
- 样本空间与事件
- 概率范围和归一化
- 联合与条件概率
- 条件方向不对称
- 全概率公式
- 先验似然后验
- 独立与条件独立
- 零证据和对数归一化
运行前先确认Java 17;Python 3.14 CPU 教学实验,无外部数据、预训练权重、GPU 或多机训练。源代码基线与局限见源码模块。
01先弄懂它是什么
看到“概率是多少”,先问清楚在做什么试验、可能出现哪些结果。例如掷一次公平六面骰,可能的结果是一到六,这些结果合起来叫样本空间。“掷出偶数”包含其中三个结果,概率为二分之一。概率在零到一之间;把所有互不重叠、又覆盖全部情况的事件列出来,它们的概率相加为一。没有说清抽样方式,一个百分比就很难解释。
条件概率回答的是“已经知道一件事发生,另一件事有多可能”。P(A|B) 表示已知 B 发生时 A 的概率;当 P(B)>0 时,P(A|B)=P(A且B)/P(B)。它通常不等于 P(B|A)。例如故障设备很容易报警,不代表一报警就大多是故障:如果正常设备特别多,其中少量误报也可能占了很多报警。
贝叶斯公式把两种方向连接起来:P(H|E)=P(E|H)*P(H)/P(E)。H 是假设,E 是观察证据;P(H) 为先验,P(E|H) 为似然,更新后的 P(H|E) 为后验。对一组互斥且完备的假设,P(E) 等于各假设的先验乘似然后求和,这个分母既代表证据概率,也负责后验归一化。
文中这几个词,先认一认
- 先验
- 看到这次证据之前,对某个假设有多大可能的判断,用概率表示。
- 似然
- 先假定某个假设成立,再看当前证据在这个假设下有多容易出现;离散情况用概率,连续情况通常用概率密度。
- 后验
- 把当前证据纳入考虑后,对假设概率的更新结果;它仍依赖所用模型和原来的先验。
02看看它怎么工作
用设备告警推导基础发生率影响:故障率为百分之一,故障设备有百分之九十触发告警,正常设备有百分之五误报。设想一万台设备,约一百台故障,其中九十台告警;九千九百台正常,其中约四百九十五台误报。告警总数约五百八十五,故障占九十除以五百八十五,即约百分之十五点四,而非百分之九十。
这个例子中的设备数量是对期望比例的说明,不代表每次观察都严格得到同样计数。先验和似然也来自建模或数据估计,可能随设备类型、环境和时间变化。后验计算即使算术完全正确,也不能保证模型假设与现实吻合;需要保留这些概率的来源和适用范围。
独立意味着 P(A且B)=P(A)*P(B),或在相关概率非零时条件概率不随另一事件改变。条件独立则是在给定某个变量之后的关系,它不等于无条件独立。若两个告警来自同一个传感器的重复处理,把它们当独立证据相乘可能重复计算信息,使后验过度自信。
离散假设更新可以先计算权重 w_i=prior_i*likelihood_i,再除以 sum(w)。但非常小的概率连乘可能在浮点数中下溢。改用 log(w_i)=log(prior_i)+log(likelihood_i),减去最大对数权重后取指数并归一化,可以保持相对大小。零概率用负无穷表示,不应对零直接取普通有限对数。
若所有假设都给当前证据零概率,分母为零,后验在此模型下未定义。不能为了得到数字就自动返回均匀分布,这会掩盖模型不覆盖证据的问题。平滑、增加其他假设或修正观测模型都可以作为设计选择,但应提前声明并验证,不能在失败后偷偷改变公式。
先跑通一个最小例子
Python Fraction 提供精确有理数对照,避免把告警例子里的差异归因于浮点舍入。
from fractions import Fraction as F
def posterior(prior,likelihood):
if len(prior)!=len(likelihood) or not prior or sum(prior)!=1:
raise ValueError("prior")
if any(v<0 or v>1 for v in prior+likelihood):
raise ValueError("probability")
weights=[p*q for p,q in zip(prior,likelihood)]
total=sum(weights)
if total==0:
raise ValueError("impossible evidence") # 模型不覆盖证据,不能伪造后验。
return [w/total for w in weights]
p=posterior([F(1,100),F(99,100)],[F(9,10),F(1,20)])
assert p[0]==F(2,13)
assert sum(p)==1
assert posterior([F(1,4),F(3,4)],[F(1),F(1)])==[F(1,4),F(3,4)]
assert posterior([F(1,2),F(1,2)],[F(0),F(1)])==[F(0),F(1)]
assert F(9,10)!=p[0] # 检出率与告警后的故障概率是不同条件方向。
try:
posterior([F(1,2),F(1,2)],[F(0),F(0)])
raise AssertionError("impossible evidence accepted")
except ValueError:
pass
print("PASS 6; posterior_fault =",float(p[0]))
核对运行结果打印 PASS 6,故障后验约 0.153846;这是给定离散模型的计算,不是对真实设备故障率的测量。
正在加载流程图…
查看流程图源码(Mermaid)
flowchart LR
A["互斥完备的假设与先验"] --> C["先验乘当前证据似然"]
B["明确观测模型"] --> C
C --> D["检查证据总概率"]
D --> E["归一化得到后验"]
E --> F["结合模型假设解释结果"]按顺序看,每一步做了什么
- 定义事件、条件方向和假设集合。
- 核对先验非负且总和为一。
- 计算每个假设下的证据似然。
- 检查证据是否在模型支持范围内。
- 归一化并记录概率来源与限制。
03对照实现代码
PyTorch v2.9.1;torch/distributions/categorical.py · Categorical.__init__
以下为原创精简教学实现,不是原样库源码;只演示本文说明的机制,省略真实实现的优化、调度和完整兼容边界。
import math
def normalized_log_weights(log_weights):
finite=[x for x in log_weights if math.isfinite(x)]
if not finite:
raise ValueError("no positive mass")
shift=max(finite) # 公共平移不改变归一化比例。
mass=[0.0 if x==-math.inf else math.exp(x-shift) for x in log_weights]
total=math.fsum(mass)
return [x/total for x in mass] # 原创离散权重模型,不自动执行贝叶斯建模。
PyTorch v2.9.1 的 Categorical 构造器要求 probs 和 logits 二选一。概率路径沿最后一维求和归一化,对数路径减去 logits 的 logsumexp;最后一维列出可选类别,其前面的维度作为批量形状。对每个批量位置,一次采样得到一个类别编号,而不是整条概率向量。
Categorical 不会自行判断哪项是先验、哪项是似然,也不会替调用者证明假设互斥完备。贝叶斯更新需要先由业务模型构造正确权重,再借用归一化机制。把通用分布类调用成功当作后验具有统计意义,会跳过最重要的建模步骤。
本篇自写函数演示的是:给所有对数权重加上同一个偏移量,与最后归一化有什么关系。它只接受本篇入口生成的有限对数权重或负无穷。真实框架还会处理 Tensor 校验、广播和缓存;Python 代码负责操作 Tensor,真正的底层数值汇总由设备算子执行。因此这个小列表循环是教学示意,不能当作框架内核的实现。
归一化只保证概率和在数值误差范围内接近一,不保证模型经过校准。一个错误模型也能输出合法概率向量。研究中还需要用独立数据检验概率预测与实际频率的对应关系,尤其注意分布变化、重复证据和选择偏差。
代码先调用谁,再调用谁
- 调用方定义假设及证据权重
- Categorical 选择 probs 或 logits 路径
- 沿最后事件维归一化
- 确定批量和事件形状
- 调用方解释与检验分布含义
04动手写一个例子
对数空间的离散贝叶斯更新
先验与离散证据似然均为零到一的有限数,先验总和约为一;返回后验数组,拒绝全零证据,避免微小乘积下溢。
- 输入 1
prior=[.01,.99], likelihood=[.9,.05]- 输出 1
posterior[0]≈2/13
- 输入 2
相同非零似然- 输出 2
后验等于先验
先验证形状、数值范围和先验和。对每个正先验且正似然的假设计算对数权重,零项记录为负无穷;如果没有正权重,立即指出证据不可能。不能先把小概率相乘再取对数,否则乘法下溢已经丢掉信息。
找到最大对数权重 max,计算 exp(logWeight-max)。至少一个缩放权重为一,其余位于零到一,所以分母既不会因所有项太小而变零,也不会因为取巨大指数而溢出。最后归一化得到后验,相同公共因子在比值中抵消。
算法输出的是给定输入概率模型的结果,不包含概率参数的估计不确定性。测试用精确可手算比例、无信息证据、排除某假设、极小似然和非法输入覆盖不同路径。舍入容差用于检查和接近一,而不是允许明显不归一的先验。
为什么这样写是对的每个缩放权重与原始先验乘似然成相同正比例;归一化后保留全部可表示的相对质量。
固定次数扫描假设数组,每项做常数次浮点与初等函数运算;参数估计成本不属于本函数。
保存为 Main.java,运行 javac --release 17 -encoding UTF-8 Main.java,再运行 java Main。程序包含固定输入自测,断言失败时会抛出错误。
public class Main {
static double[] posterior(double[] prior,double[] likelihood){
if(prior==null||likelihood==null||prior.length==0||prior.length!=likelihood.length)throw new IllegalArgumentException("shape");
double total=0,max=Double.NEGATIVE_INFINITY;double[] log=new double[prior.length];
for(int i=0;i<prior.length;i++){
double p=prior[i],q=likelihood[i];
if(!Double.isFinite(p)||!Double.isFinite(q)||p<0||p>1||q<0||q>1)throw new IllegalArgumentException("probability");
total+=p;
log[i]=(p==0||q==0)?Double.NEGATIVE_INFINITY:Math.log(p)+Math.log(q); // 先取对数,不先做微小乘积。
max=Math.max(max,log[i]);
}
if(Math.abs(total-1)>1e-12||max==Double.NEGATIVE_INFINITY)throw new IllegalArgumentException("prior/evidence");
double[] out=new double[prior.length];double sum=0;
for(int i=0;i<out.length;i++){out[i]=Math.exp(log[i]-max);sum+=out[i];} // 至少一项为一。
for(int i=0;i<out.length;i++)out[i]/=sum; // 公共缩放因子在比值中抵消。
return out;
}
static void near(double a,double b){if(!Double.isFinite(a)||Math.abs(a-b)>1e-12)throw new AssertionError(a+" != "+b);}
static void bad(Runnable r){try{r.run();}catch(IllegalArgumentException e){return;}throw new AssertionError();}
public static void main(String[] args){
near(posterior(new double[]{.01,.99},new double[]{.9,.05})[0],2.0/13);
near(posterior(new double[]{.25,.75},new double[]{1,1})[0],.25);
near(posterior(new double[]{.5,.5},new double[]{0,1})[1],1);
near(posterior(new double[]{.5,.5},new double[]{1e-300,1e-300})[0],.5);
bad(()->posterior(new double[]{.5,.5},new double[]{0,0}));
bad(()->posterior(new double[]{.2,.2},new double[]{1,1}));
bad(()->posterior(new double[]{1},new double[]{-1}));
System.out.println("PASS 7");
}
}这些特殊情况也要试一试
- 零似然排除相应假设。
- 全零证据使后验未定义。
- 极小似然不先直接连乘。
- 本篇似然为离散事件概率,连续密度不受小于一限制且需另立接口。
进阶选读 · 连续参数与后验近似
场景假设不是有限类别,而是连续参数。
做法以密度和积分替代离散求和,根据问题使用解析共轭、数值积分或采样;检查收敛与近似偏差。
复杂度成本依维度和方法变化,高维积分通常无法按小列表方式直接枚举。
好处与代价更灵活,但密度值可大于一,先验和收敛诊断都需重新说明。
05项目里怎么用
在应用中记录先验从何而来、似然如何估计、证据是否经过选择。只在告警设备里收集数据,再把其中故障比例当作所有设备的故障率,就改变了抽样条件。概率推断需要明确观察过程,否则再精确的公式也可能回答错问题。
多个信号联合更新时,应检查它们是否共享来源。重复日志、同一模型的多个近似分数或由同一传感器派生的特征,通常不能未经论证地视为独立证据。可以建立联合模型,或在数据上评估相关性与校准;不能用更多相乘项制造表面上的高置信度。
后验概率与决策还隔着成本和约束。即使某假设概率最高,也未必应立即采取代价很高的动作;不同误报和漏报成本会改变阈值。教学计算只说明如何更新分布,生产决策仍需任务目标、风险预算和独立评估,不应把一个小例子的最优阈值推广到所有场景。
容易踩的坑
- 交换
P(A|B)与P(B|A)。 - 忽略基础发生率。
- 把相关证据按独立证据重复相乘。
- 全零分母时偷偷返回均匀分布。
几种做法,怎么选
表格有四列,窄屏可左右滑动查看代价和适用条件。
| 方案 | 优势 | 代价与限制 | 适用条件 |
|---|---|---|---|
| 精确离散枚举 | 每项含义清楚且可核对 | 假设数大时成本增加 | 有限类别更新 |
| 对数权重 | 避免微小乘积下溢 | 需要处理零质量和数值误差 | 长证据链或小概率 |
| 连续后验近似 | 表达复杂参数不确定性 | 计算与诊断要求更高 | 参数研究与推断 |
06检验是否读懂了
先自己想、自己写,再展开答案核对。场景题是假设的练习情境;遇到还没学过的内容,可以做完基础后再回来。
先用自己的话解释
01似然等于后验吗?
展开参考答案与推导
不等于。似然固定假设看证据,后验固定证据看假设,二者由先验和证据总概率联系。只有在特定对称条件下数值才可能偶然相同。
02归一化后概率和为一是否证明模型正确?
展开参考答案与推导
不能。归一化仅满足分布的一个数学约束,错误的假设和似然也能产生合法分布。还需要检验模型与实际观察是否吻合。
03连续似然密度必须不大于一吗?
展开参考答案与推导
不必须。密度通过积分形成概率,数值可能大于一。本篇算法刻意限制离散事件似然,不能直接套用到任意连续密度。
换个情况,还会处理吗
01高检出率告警为何多数仍可能正常?
展开参考答案与推导
正常对象可能远多于异常对象,少量误报率乘上巨大正常基数仍产生很多告警。应结合基础发生率,用全概率公式计算告警中的异常比例。
02重复两次同一告警能再乘一次似然吗?
展开参考答案与推导
不能默认如此。需要判断重复信息是否提供新的条件独立证据,若只是同一事件的复制,重复更新会夸大置信度。
03所有假设都解释不了证据怎么办?
展开参考答案与推导
明确报告模型支持范围不足,检查输入、观测模型和假设集合;若采用平滑或其他类别,应作为事先说明的模型变更重新验证。
写代码试一试
01计算告警后的故障比例。
- 输入 / 条件
故障告警90,正常告警495- 输出 / 预期
90/585=2/13
提示 条件分母是全部告警。
展开参考答案与推导
只在告警人群中计算故障占比,因此分母为五百八十五,不能除以全部故障数一百;后者回答的是检出率。
02无信息证据如何更新?
- 输入 / 条件
prior=[.2,.8],likelihood=[.5,.5]- 输出 / 预期
[.2,.8]
提示 各项乘相同因子。
展开参考答案与推导
两个假设被相同比例缩放,归一化后比例不变。证据没有区分假设,所以后验保持先验。
03如何避免概率乘法下溢?
- 输入 / 条件
两个约1e-300的因子- 输出 / 预期
在对数域保留相对权重
提示 先 log 再相加。
展开参考答案与推导
不要先乘出零再取对数,应分别取对数相加,减去最大值后指数化归一化;零概率另外表示为负无穷。
读完之后,独立完成
课后作业:自己做一遍
本篇共 10 道作业,先完成 8 道基础与综合任务,再按前置知识挑战进阶题。其中包含 1 道思维拓展,试着换个条件,看看原来的办法是否还管用。不附参考答案。
能根据原有判断(先验)和各假设下证据出现的可能性(似然)计算离散后验,解释低发生率场景,并拒绝不可能证据与非法概率。
本篇重点加练
后验更新的可靠性取决于证据依赖假设,需避免把归一化正确当成推断正确。
- 先验似然后验
- 独立与条件独立
重点内容会多练几次。先说清楚怎么做,再试试空数据、出错或条件改变时会发生什么。
先自己做,卡住时记下问题,再回来查。问答题写清“为什么、什么时候适用”;动手题留下输入、输出和运行步骤,方便下次重做。
基础必做
- 作业 01原理问答
掷两枚公平骰子,定义 A 为和大于 8、B 为第一枚为 6。列出样本空间并分别计算联合和两个方向的条件概率。
- 提交内容
- 事件表与计算记录
- 怎样算完成
- 条件分母明确
- 事件没有重复计数
练到的知识点样本空间与事件 · 概率范围和归一化 · 联合与条件概率 · 条件方向不对称
- 作业 02代码推演
三类硬币的先验为 [0.2,0.5,0.3],正面概率为 [0.2,0.5,0.8]。连续观察“正、正、反”,写出每次观测后的信念计算记录。
- 提交内容
- 逐次更新表
- 怎样算完成
- 每步归一化可核对
- 证据和先验角色清楚
练到的知识点全概率公式 · 先验似然后验
- 作业 03原理问答
对同一联合分布,分别先观察 E1 再观察 E2,以及反过来更新。分析最终后验可否一致,列出每步所需概率与条件;不要默认两项证据独立。
- 提交内容
- 两种更新次序与条件表
- 怎样算完成
- 证据来源关系明确
- 未给定概率保持未知
练到的知识点先验似然后验 · 独立与条件独立
- 作业 04代码推演
先验赔率为 1:4,依次收到似然比 3 和 0.5;在声明证据更新所需条件后,用概率形式和赔率形式分别记账并核对。
- 提交内容
- 两种表示的更新记录
- 怎样算完成
- 条件和方向一致
- 中间记录完整
练到的知识点先验似然后验
综合应用
- 作业 05编程实践
编写有限假设贝叶斯更新器,接收对数先验与对数似然,测试极小似然、某类不可能和全部不可能三类输入。
- 提交内容
- 脚本与接口测试
- 怎样算完成
- 有效输出满足概率契约
- 零证据状态有明确表示
练到的知识点先验似然后验 · 零证据和对数归一化
- 作业 06设计评审
研究用两个来自同一传感器的告警作为独立证据。提出一个包含共同原因的概率模型,并列出检验独立性假设所需的数据。
- 提交内容
- 概率图与数据需求
- 怎样算完成
- 条件变量明确
- 假设与观测证据分开
练到的知识点独立与条件独立
- 作业 07排错实验
在一个三假设模型中分别注入负概率、先验和不为一、证据似然全零,检查实现是拒绝还是重解释;为每类异常写可复现案例。
- 提交内容
- 异常实验与契约修订
- 怎样算完成
- 输入校验覆盖完整
- 不会静默改变事件含义
练到的知识点概率范围和归一化 · 全概率公式 · 零证据和对数归一化
- 作业 08编程实践
用 Python 标准库枚举二元原因 H 与二元证据 E1、E2,自己构造含相关证据的合法联合分布,比较精确后验与独立性近似后验。
- 提交内容
- 联合概率表、代码与误差比较
- 怎样算完成
- 所有概率可核验归一化
- 近似假设由实验单独标识
练到的知识点先验似然后验 · 独立与条件独立
进阶挑战 · 掌握前置后选做
- 作业 09面试场景
分类器在均衡样本上表现良好,部署人群中的目标事件比例改变。制定只更新先验与重新训练两种方案的对照协议,说明各方案依赖的假设。
- 提交内容
- 受控实验方案
- 怎样算完成
- 分布变化因素具体
- 评价集与拟合数据隔离
练到的知识点条件方向不对称 · 先验似然后验 · 独立与条件独立
思维拓展
先写出你的猜想,再用例子或实验验证。答案可以不同,但要说清依据、适用情况,以及还有什么没弄懂。
- 作业 10思维拓展 · 反例构造
“观测数量越多,后验一定越接近真实状态”是否无条件成立?构造有限假设空间中的反例,指出错误来自模型失配、依赖假设或证据质量中的哪一项。
- 提交内容
- 反例概率模型与论证
- 怎样算完成
- 反例分布合法
- 失效条件明确且不混淆
练到的知识点先验似然后验 · 独立与条件独立
完成后,再检验一次
给每题标记“独立完成 / 查阅后完成 / 尚未完成”。查过资料或没做出的题,记下卡在哪里。隔一天换一组输入再试,能解释结果和出错原因,再把这个知识点标为掌握。
继续阅读
先看能帮你完成当前练习的部分。例子跑通后,再读更深入的解释。
- 必读参考文档英文
PyTorch v2.9.1:Categorical 参数归一化 (新标签页)↗
核对 probs 与 logits 两条归一化路径,明确分布构造不自动完成贝叶斯建模。
- 深入参考文档英文
MIT 18.05:概率与统计 (新标签页)↗
阅读条件概率、全概率和贝叶斯推断课程。
- 深入参考文档英文
Brown Seeing Theory:贝叶斯推断 (新标签页)↗
通过可视化观察先验、似然和后验之间的关系。
- 深入参考文档英文
PyTorch 2.9 distributions (新标签页)↗
核对 Categorical 参数和事件维语义。