qinghuan
← 数学语言与概率基础 / 全部笔记

单元 05 / 数学语言与概率基础

P0 · 必会主线L0 · 零基础

概率、条件概率与贝叶斯推断

从“已知一件事发生,另一件事有多可能”理解条件概率和贝叶斯公式,再用离散假设更新实验检查直觉。

本篇目录 · 按需要跳转

读完这篇,你能做什么

能根据原有判断(先验)和各假设下证据出现的可能性(似然)计算离散后验,解释低发生率场景,并拒绝不可能证据与非法概率。

学习理由、准备要求与知识点

为什么学它

模型预测和实验结果都有不确定性。把“故障时会报警”误读成“报警就多半故障”,就会得出错误判断。

先读这些内容

知识点清单

  • 样本空间与事件
  • 概率范围和归一化
  • 联合与条件概率
  • 条件方向不对称
  • 全概率公式
  • 先验似然后验
  • 独立与条件独立
  • 零证据和对数归一化

运行前先确认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 提供精确有理数对照,避免把告警例子里的差异归因于浮点舍入。

experiment.py · python
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["结合模型假设解释结果"]

按顺序看,每一步做了什么

  1. 定义事件、条件方向和假设集合。
  2. 核对先验非负且总和为一。
  3. 计算每个假设下的证据似然。
  4. 检查证据是否在模型支持范围内。
  5. 归一化并记录概率来源与限制。

03对照实现代码

PyTorch v2.9.1:Categorical 参数归一化 (新标签页)↗

PyTorch v2.9.1;torch/distributions/categorical.py · Categorical.__init__

以下为原创精简教学实现,不是原样库源码;只演示本文说明的机制,省略真实实现的优化、调度和完整兼容边界。

核心机制代码 · python
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,真正的底层数值汇总由设备算子执行。因此这个小列表循环是教学示意,不能当作框架内核的实现。

归一化只保证概率和在数值误差范围内接近一,不保证模型经过校准。一个错误模型也能输出合法概率向量。研究中还需要用独立数据检验概率预测与实际频率的对应关系,尤其注意分布变化、重复证据和选择偏差。

代码先调用谁,再调用谁

  1. 调用方定义假设及证据权重
  2. Categorical 选择 probs 或 logits 路径
  3. 沿最后事件维归一化
  4. 确定批量和事件形状
  5. 调用方解释与检验分布含义

04动手写一个例子

对数空间的离散贝叶斯更新

先验与离散证据似然均为零到一的有限数,先验总和约为一;返回后验数组,拒绝全零证据,避免微小乘积下溢。

输入 1
prior=[.01,.99], likelihood=[.9,.05]
输出 1
posterior[0]≈2/13
输入 2
相同非零似然
输出 2
后验等于先验

先验证形状、数值范围和先验和。对每个正先验且正似然的假设计算对数权重,零项记录为负无穷;如果没有正权重,立即指出证据不可能。不能先把小概率相乘再取对数,否则乘法下溢已经丢掉信息。

找到最大对数权重 max,计算 exp(logWeight-max)。至少一个缩放权重为一,其余位于零到一,所以分母既不会因所有项太小而变零,也不会因为取巨大指数而溢出。最后归一化得到后验,相同公共因子在比值中抵消。

算法输出的是给定输入概率模型的结果,不包含概率参数的估计不确定性。测试用精确可手算比例、无信息证据、排除某假设、极小似然和非法输入覆盖不同路径。舍入容差用于检查和接近一,而不是允许明显不归一的先验。

为什么这样写是对的每个缩放权重与原始先验乘似然成相同正比例;归一化后保留全部可表示的相对质量。

时间 O(k),k 为假设数。额外空间 O(k) 的对数权重和后验结果。

固定次数扫描假设数组,每项做常数次浮点与初等函数运算;参数估计成本不属于本函数。

保存为 Main.java,运行 javac --release 17 -encoding UTF-8 Main.java,再运行 java Main。程序包含固定输入自测,断言失败时会抛出错误。

Main.java · 完整可运行程序 · Java
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 道思维拓展,试着换个条件,看看原来的办法是否还管用。不附参考答案。

这次练什么

能根据原有判断(先验)和各假设下证据出现的可能性(似然)计算离散后验,解释低发生率场景,并拒绝不可能证据与非法概率。

本篇重点加练

后验更新的可靠性取决于证据依赖假设,需避免把归一化正确当成推断正确。

  • 先验似然后验
  • 独立与条件独立

重点内容会多练几次。先说清楚怎么做,再试试空数据、出错或条件改变时会发生什么。

先自己做,卡住时记下问题,再回来查。问答题写清“为什么、什么时候适用”;动手题留下输入、输出和运行步骤,方便下次重做。

基础必做

  1. 作业 01原理问答

    掷两枚公平骰子,定义 A 为和大于 8、B 为第一枚为 6。列出样本空间并分别计算联合和两个方向的条件概率。

    提交内容
    事件表与计算记录
    怎样算完成
    • 条件分母明确
    • 事件没有重复计数

    练到的知识点样本空间与事件 · 概率范围和归一化 · 联合与条件概率 · 条件方向不对称

  2. 作业 02代码推演

    三类硬币的先验为 [0.2,0.5,0.3],正面概率为 [0.2,0.5,0.8]。连续观察“正、正、反”,写出每次观测后的信念计算记录。

    提交内容
    逐次更新表
    怎样算完成
    • 每步归一化可核对
    • 证据和先验角色清楚

    练到的知识点全概率公式 · 先验似然后验

  3. 作业 03原理问答

    对同一联合分布,分别先观察 E1 再观察 E2,以及反过来更新。分析最终后验可否一致,列出每步所需概率与条件;不要默认两项证据独立。

    提交内容
    两种更新次序与条件表
    怎样算完成
    • 证据来源关系明确
    • 未给定概率保持未知

    练到的知识点先验似然后验 · 独立与条件独立

  4. 作业 04代码推演

    先验赔率为 1:4,依次收到似然比 3 和 0.5;在声明证据更新所需条件后,用概率形式和赔率形式分别记账并核对。

    提交内容
    两种表示的更新记录
    怎样算完成
    • 条件和方向一致
    • 中间记录完整

    练到的知识点先验似然后验

综合应用

  1. 作业 05编程实践

    编写有限假设贝叶斯更新器,接收对数先验与对数似然,测试极小似然、某类不可能和全部不可能三类输入。

    提交内容
    脚本与接口测试
    怎样算完成
    • 有效输出满足概率契约
    • 零证据状态有明确表示

    练到的知识点先验似然后验 · 零证据和对数归一化

  2. 作业 06设计评审

    研究用两个来自同一传感器的告警作为独立证据。提出一个包含共同原因的概率模型,并列出检验独立性假设所需的数据。

    提交内容
    概率图与数据需求
    怎样算完成
    • 条件变量明确
    • 假设与观测证据分开

    练到的知识点独立与条件独立

  3. 作业 07排错实验

    在一个三假设模型中分别注入负概率、先验和不为一、证据似然全零,检查实现是拒绝还是重解释;为每类异常写可复现案例。

    提交内容
    异常实验与契约修订
    怎样算完成
    • 输入校验覆盖完整
    • 不会静默改变事件含义

    练到的知识点概率范围和归一化 · 全概率公式 · 零证据和对数归一化

  4. 作业 08编程实践

    用 Python 标准库枚举二元原因 H 与二元证据 E1、E2,自己构造含相关证据的合法联合分布,比较精确后验与独立性近似后验。

    提交内容
    联合概率表、代码与误差比较
    怎样算完成
    • 所有概率可核验归一化
    • 近似假设由实验单独标识

    练到的知识点先验似然后验 · 独立与条件独立

进阶挑战 · 掌握前置后选做

  1. 作业 09面试场景

    分类器在均衡样本上表现良好,部署人群中的目标事件比例改变。制定只更新先验与重新训练两种方案的对照协议,说明各方案依赖的假设。

    提交内容
    受控实验方案
    怎样算完成
    • 分布变化因素具体
    • 评价集与拟合数据隔离

    练到的知识点条件方向不对称 · 先验似然后验 · 独立与条件独立

思维拓展

先写出你的猜想,再用例子或实验验证。答案可以不同,但要说清依据、适用情况,以及还有什么没弄懂。

  1. 作业 10思维拓展 · 反例构造

    “观测数量越多,后验一定越接近真实状态”是否无条件成立?构造有限假设空间中的反例,指出错误来自模型失配、依赖假设或证据质量中的哪一项。

    提交内容
    反例概率模型与论证
    怎样算完成
    • 反例分布合法
    • 失效条件明确且不混淆

    练到的知识点先验似然后验 · 独立与条件独立

完成后,再检验一次

给每题标记“独立完成 / 查阅后完成 / 尚未完成”。查过资料或没做出的题,记下卡在哪里。隔一天换一组输入再试,能解释结果和出错原因,再把这个知识点标为掌握。

继续阅读

先看能帮你完成当前练习的部分。例子跑通后,再读更深入的解释。

打开资料库,找下一份学习材料 ↗