上周一个做运营的朋友拿着体检报告找我,说某项指标筛查结果是阳性,报告上写“灵敏度99%”。他问我:“都99%了,是不是基本可以确诊了?”我说你先别慌,把另外两个数字给我——你所在人群这种指标的阳性率大概是多少,以及这项检测对健康人的假阳性率是多少。他愣了一下:报告上没写。
问题就出在这。
这就是先验概率、似然概率(更准确地说,似然函数)与后验概率这三个概念最典型的应用场景。凡是做过机器学习、数据分析、产品决策的人,几乎每天都在和这三者的“变体”打交道:模型参数估计、A/B测试、推荐系统CTR平滑、风控模型校准……本质上都是同一套贝叶斯思维。这篇博客我想把这几个概念彻底拆开讲清楚,顺便把我这些年踩过的坑也一并交代了。
1. 先从一个被低估的体检案例说起:99%的准确率为什么仍然可能错
1.1 用一张四格表算明白真正的阳性概率
假设某种罕见病的真实患病率是0.1%,也就是1000个人里大约有1个患者。检测试剂盒的灵敏度(真阳性率)是99%,也就是说确实患病的人去做检测,99%会显示阳性。假阳性率是1%,也就是没病的人去做检测,也有1%的概率被误报为阳性。
现在你随机拉一个人做检测,结果呈阳性。请问这个人真正患病的概率是多少?
直觉会告诉你:灵敏度都99%了,假阳性才1%,阳性了基本跑不掉吧?我们拿数字说话。假设有10万人参与筛查:
- 按0.1%患病率,这10万人里应有100个患者。检测灵敏度99%,意味着其中99人会正确报阳性;
- 剩下的99,900人是健康的。假阳性率1%,意味着有999个健康人会被误报为阳性;
- 所有检测阳性人数 = 99 + 999 = 1098人。
1098个阳性里,真正患病的只有99人。99除以1098,约等于9.0%。
换句话说,一个灵敏度99%、假阳性率1%的检测,在0.1%患病率的人群里,阳性结果对应的真实患病概率只有9%。这个结论第一次看确实反直觉,但它不是检测报告写错了,而是我们把两个完全不同的条件概率搞混了。
1.2 贝叶斯公式登场:把条件反过来看
上述混乱的本质是:我们想知道的是 P(患病 | 检测阳性),检测报告给的却是 P(检测阳性 | 患病)。前者叫后验概率,后者是似然。二者之间的关系由贝叶斯定理串起来:
P(患病 | 阳性) = P(阳性 | 患病) × P(患病) / P(阳性)
代入数字:
- 先验 P(患病) = 0.001
- 似然 P(阳性 | 患病) = 0.99
- 分母 P(阳性) = 0.001×0.99 + 0.999×0.01 = 0.01098
所以 P(患病 | 阳性) = 0.00099 / 0.01098 ≈ 0.090,约9%。
这个结果和用四格表算出来的一模一样。贝叶斯公式在这里做的事情,本质上是把“从因到果”的已知概率(患病→阳性),结合基底比率(先验),反推出“从果到因”的概率(阳性→患病)。
1.3 先验对结论的影响大到什么程度
同样的检测试剂盒,如果放在不同场景里,结论会非常不一样。我用同一套公式算了几种组合:
| 场景 | 患病率(先验) | 灵敏度 | 假阳性率 | 阳性后真实患病概率 |
|---|---|---|---|---|
| 罕见病全民筛查 | 0.1% | 99% | 1% | 约9.0% |
| 已出现症状的高危人群 | 10% | 99% | 1% | 约91.7% |
| 同期二次筛查(先验变高) | 1% | 99% | 1% | 50.0% |
| 假阳性率优化后 | 0.1% | 99% | 0.1% | 约49.8% |
先验从0.1%变成10%,同样的检测结果,后验概率从9%跳到91.7%。所以你看,抛开先验谈“准确率”,在决策层面几乎没有意义。这也解释了为什么医生在开检测之前总要问一堆病史和接触史——那些信息全部是在调整先验。
行为经济学里有个著名的“基础比率谬误”(base rate fallacy),指的就是人在判断时过度依赖眼前证据(检测阳性),忽略总体基底比率(患病率)。在做数据分析时,这种谬误也极其常见:看到一个模型准确率95%就觉得稳了,却不问正负样本分布是否均衡。本质上,都是颠倒了先验、似然、后验之间的关系。
2. 分清三兄弟:先验、似然、后验各自的职责边界
2.1 先验概率:数据进来之前,你相信什么
先验概率是在观测到当前数据之前,你对某个未知量 θ 的信念,记作 P(θ)。注意它是“信念”,不是“真理”。在贝叶斯框架里,一切皆不确定,θ 本身也是一个随机变量,有分布。
根据信念的强弱,先验大致分三类:
- 无信息先验(或不完全先验):表示“我对θ几乎一无所知”。经典例子是均匀分布 Beta(1,1),它给 θ 的每个取值同等权重。
- 弱信息先验:你有一点点方向性知识,但不想过度约束。比如历史转化率在2%左右,你可以用 Beta(2, 98) 这样均值接近0.02、方差很大的分布。它只是把推断往合理区域轻轻推一把,数据量稍大就会被冲掉。
- 强信息先验:你掌握了可靠的领域知识或历史数据,比如一个成熟渠道的点击率分布,这时可以把先验设置得比较集中(方差小)。
很多业务场景里,先验就是“行业基准”或“历史平均”。以一个 App 的新版本上线为例,新版本没有自身历史数据,但老版本平均点击率是4%,行业同类功能普遍在3%~5%之间,那你在评估新版本短期数据时,用 Beta(40, 960) 这类先验(均值4%,相当于把老版本40次成功、960次失败的观测当作“虚拟样本”)就是合理且稳健的做法。
但先验不是让你拍脑袋的。“拍脑袋”的问题是它不含不确定性信息——你只知道“我觉得转化率应该不错”,却不知道“不错”到底是多少、有多宽。先验分布的方差才是你“不确定程度”的体现。方差越小,代表你越自信,后续观测数据要达到的量级也必须越强才能撼动它。
2.2 似然函数:数据固定不动,让参数自己动
似然函数是贝叶斯公式里的第二个组成部分,记作 L(θ | Data) = P(Data | θ)。它回答的问题是:在 θ 取某个值的条件下,我手上这组数据出现的可能性有多大。
这里有一个几乎所有初学者都会卡住的点:P(Data | θ) 和 P(θ | Data) 长得像,含义完全不同。前者把 θ 当成固定值,看数据的概率;后者把 Data 当成已知事实,看 θ 的分布。似然函数本质上是一个“关于 θ 的函数”,只是从概率 P(Data | θ) 转了个视角来看——把数据的观测结果固定住,让 θ 在参数空间里滑动,看看每个 θ 值对这组数据的解释力有多强。
也正是因为视角不同,似然函数严格来说不能叫做“概率”。它对 θ 积分(或求和)不保证等于1。比如连续参数空间下,似然函数取值可能是密度值,完全可以大于1。你在代码里算出一个“似然值”是7.3,不用怀疑自己算错了,它只是相对大小有意义,绝对值没有概率含义。所以统计学教材里更偏爱“似然函数”或“似然度”这个叫法,而不是“似然概率”。标题里保留了大众习惯的说法,但正式写代码、写文档时,建议用“likelihood function”,避免和概率混淆。
实践中几乎总是使用对数似然,原因有三个:第一,累乘的似然会迅速变成极小的数,浮点直接下溢;第二,对数把乘法变成加法,数学推导和程序实现都简单;第三,很多分布的似然里带着指数项,取对数后直接变成二次型,和梯度计算天然契合。
2.3 后验概率:信念更新之后的“最终答案”
后验概率 P(θ | Data) 是观测数据之后你对 θ 的新信念。贝叶斯公式告诉我们:
P(θ | Data) = P(Data | θ) × P(θ) / P(Data)
其中分母 P(Data) 是一个归一化因子,用来保证 P(θ | Data) 对 θ 积分为1。实际计算中,如果只是要比较不同 θ 的相对优劣,分母完全可以忽略,因为它是常数,不改变 θ 之间的排序。我们把“正比于”记成:
P(θ | Data) ∝ P(Data | θ) × P(θ)
这个式子就是整个贝叶斯推断的核心:后验正比于似然乘以先验。
打个比方:先验是你手里的嫌疑人名单,每个人根据过往案底有一个初始怀疑度;似然是眼前的证据(指纹、脚印)和每个嫌疑人匹配的程度;后验是所有证据汇总后重新生成的怀疑度排序。名单没有变,证据也没有变,但排序完全可能重来。
后验不是一个点,而是一整个分布。你可以从分布里提取不同的量来使用:均值(后验期望)、众数(MAP估计)、分位数(可信区间)。它保留了“不确定性”信息,这是后验相比单纯点估计最大的优势——这一点后面讲机器学习训练时还会展开。
3. 用一个硬币实验把贝叶斯更新完整跑一遍
3.1 为什么选硬币问题
概念再清楚,不动手算一遍总觉得隔层纱。硬币问题是最小、最完整的贝叶斯更新生态:参数只有一个 θ(硬币正面朝上的概率),先验可以可视化,似然是简单的幂函数,后验有解析解,而且所有中间过程都能画出来。把它弄透之后,再去理解更复杂的模型参数估计,逻辑是一样的。
设 θ ∈ [0,1] 表示硬币正面的概率。对一个正常硬币,θ 大概率在0.5附近,但我们的确不确定。用一个 Beta(2,2) 作为先验——它的密度曲线像一座中心在0.5、两端平滑下降的小山,表达的是“认为均匀硬币最合理,但不排除偏差”。
Beta 分布在概率类参数的建模里是神器,因为它取值范围是 [0,1],形状灵活,并且和“二项分布/伯努利分布”天生共轭。所谓共轭,是指“先验选 Beta 分布 + 似然是二项分布”之后,后验仍然是一个 Beta 分布,只是参数变了。这种解析性质能让我们精确求解,无需任何近似采样。
3.2 网格近似:不依赖公式也能算后验
先上最简单、最好理解的数值方法:网格法。把 θ 在 [0,1] 上离散成很多点,在每个点上计算 先验 × 似然,然后归一化。这是“暴力美学”,也是理解贝叶斯公式的直接落点。
import numpy as np from scipy import stats import matplotlib.pyplot as plt theta_grid = np.linspace(0, 1, 1001) # 先验:Beta(2, 2) prior = stats.beta.pdf(theta_grid, 2, 2) # 观测:抛10次,6次正面,4次反面 n, k = 10, 6 likelihood = theta_grid**k * (1 - theta_grid)**(n - k) # 后验未归一化 = 先验 * 似然 posterior_unnormalized = prior * likelihood # 数值积分归一化(梯形法则) posterior_grid = posterior_unnormalized / np.trapz(posterior_unnormalized, theta_grid) # 共轭解析解:Beta(2+6, 2+4) = Beta(8, 6) posterior_analytic = stats.beta.pdf(theta_grid, 8, 6) print(f"网格法后验均值: {np.trapz(theta_grid * posterior_grid, theta_grid):.4f}") print(f"解析后验均值: {8 / (8 + 6):.4f}")把三个分布画在同一张图上,你会看到一条清晰的链路:先验的密度在0.5附近最高,似然函数在 θ=0.6 处最高(因为实验里正面比例是0.6),两者相乘之后,后验的峰值落在0.5和0.6之间偏向0.6一侧,大约是0.57。这就是“先验与数据谈判的结果”:先验说“我觉得大概是0.5”,数据说“我观察到0.6”,后验说“那我信0.57吧”。
3.3 连续更新:观测一条数据,后验就动一次
贝叶斯更新的魅力在于它是循序渐进的过程。同样一枚硬币,你每一次抛掷都能刷新一次后验。但要注意,最终的后验只取决于数据整体,与数据产生的顺序无关。先验 Beta(2,2),观测到“6正4反”之后是 Beta(8,6);你也可以先观测到“1正”,后验变成 Beta(3,2),再观测到“5正4反”,最后仍然变成 Beta(8,6)。这和贝叶斯公式天然自洽:一份一份地看数据,和攒齐了一次性看,结果完全相同。这个性质在工程上很实用——流式数据的在线学习本质上就是不断用新数据更新先前的后验。
我们还可以直观地看“数据量怎么影响先验”:
- 数据很少(比如只有1次正面),先验 Beta(2,2) 变成 Beta(3,2),曲线只是轻微右移,峰值仍然在0.5附近;
- 数据达到10次(6正4反),后验 Beta(8,6) 的均值约0.571,峰值明显右移;
- 数据达到1000次(如果真实 θ=0.4,观测约400正600反),后验变成 Beta(402,602),均值约0.400,此时曲线非常窄,几乎完全由数据主导,初始先验的影响已经微乎其微。
但如果你用的是“强先验”,比如 Beta(200,200),形状本身就非常尖,相当于你预设“几乎百分百信这是个正常硬币”。要把它扳到平均0.4,需要的数据量远比弱先验多。这正是先验强度的含义:它不是把结论拖向某个值,而是给某些区间更高的“初始权重”,数据要积累到足够强才能覆盖它。
3.4 一个需要随手记住的实操经验
网格法虽然直观,但只适用于参数维度很低的场景。参数一旦到二维以上,网格数量就指数爆炸。真实项目里,绝大多数模型没有共轭先验,也没有办法写出解析后验。这时候要么用 MCMC(马尔可夫链蒙特卡洛)采样,要么用变分推断做近似。早期我犯过一个错:不管什么模型都拿网格法硬算,结果一个三维参数就卡到怀疑人生。后来习惯了先用共轭模型验证代码逻辑,再上采样方法,出错的概率低了很多。
4. 机器学习训练视角:MLE、MAP 与全贝叶斯估计
4.1 MLE:唯数据论的极限
最大似然估计(MLE)思路极其直接:找一个参数 θ,让观测数据出现的“概率”最大。写成优化问题就是:
θ_MLE = argmax_θ P(Data | θ)
或者等价地最大化对数似然。
一个经典到不能再经典的例子:假设某用户在未来7天会否购买商品,每次行为独立,转化率 θ 未知。如果现有100次曝光、8次转化,似然函数是 θ⁸(1-θ)⁹²,最大化得到 θ_MLE = 8/100 = 0.08。这看起来很合理。
但 MLE 在“小样本+极端观测”下会露出丑陋的獠牙:一个硬币连抛10次,10次全是正面,MLE 给出的估计是 θ=1,也就是“这枚硬币永远正面”。你心里清楚这只是运气,但最大似然不会表达这种怀疑,它把所有概率押在了让数据出现的那个点上。没有先验给它“兜底”,小样本过拟合几乎是必然的。
4.2 MAP:把先验写进优化目标,它就成了正则项
最大后验估计(MAP)不再单独最大化似然,而是最大化后验:
θ_MAP = argmax_θ [ log P(Data | θ) + log P(θ) ]
因为在优化视角下归一化分母是常数,不需要管它。看到这个式子的第一反应应该是:MAP 就是 MLE 加了一项“参数的先验对数概率”。这一项在深度学习里有个更耳熟的名字:正则项。
推导逻辑很简单。假设模型参数服从高斯先验 θ ~ N(0, λ),那么 log P(θ) 正比于 -θ²/(2λ²)。把它加进目标函数,等价于在损失函数里加了一个 L2 惩罚(weight decay / 岭回归)。如果先验是拉普拉斯分布,则 log P(θ) 正比于 -|θ|,对应 L1 正则(Lasso)。所以“先验信息”和“正则化”本质上是一回事——先验说你更相信参数在0附近,正则项就惩罚那些偏离0太远的解;先验对某些方向更有偏好,体现在优化目标里就是那些方向的收缩。
这一点对工程实践非常友好。模型不加正则,就是纯 MLE;加了 L2/L1,就等于隐式设定了高斯/拉普拉斯形式的先验。区别只在于:很多人写代码时把它当超参调,但在贝叶斯视角下,它是有明确概率图景的。
4.3 全贝叶斯:把整个后验都用起来,而不是选一个点
MLE 和 MAP 给出的都只是一个点估计。点估计的问题在于,它把参数的不确定性抹掉了。如果模型对参数估计很自信,但你手上只有200条样本,并且这些样本还采得比较偏,点估计会让你盲目乐观。
全贝叶斯估计保留完整的后验分布,并在预测时做边际化:
P(y_new | x_new, Data) = ∫ P(y_new | x_new, θ) × P(θ | Data) dθ
也就是把“所有可能 θ 下的预测”按后验权重加权平均。这会天然地反映不确定性:后验方差大的地方,预测的不确定度就大。对比一下:
- 点估计管线:先训一个 θ_MAP,然后预测时只代入这个 θ;
- 贝叶斯管线:在 θ 的后验分布上做聚合,输出的是一个预测分布。
实际工程里,全贝叶斯不是免费的:MCMC 采样慢、存储大,实时推理还要折成近似。但凡是小样本决定要不要做实验、贝叶斯优化里选下一个采样点、或者需要给业务方解释“这个预测到底有多不确定”的场景,全贝叶斯的收益往往远超成本。近些年很多团队在生产环境里用 SWA、Laplace 近似甚至蒸馏方案逼近全贝叶斯,都是这个思路的工程妥协。
另外,贝叶斯视角下模型选择的工具也不同。频率派常用各种信息准则和交叉验证,贝叶斯派则比较“边际似然”:
P(Data | Model_i) = ∫ P(Data | θ, Model_i) × P(θ | Model_i) dθ
两个模型的边际似然之比叫贝叶斯因子(Bayes Factor)。它表达的是数据支持 H1 相对于 H2 的强度。和 p 值不同,贝叶斯因子可以对称地支持“原假设”而不仅是拒绝它,而且不依赖渐近近似。不过边际似然对先验很敏感,实际使用时我会把它当成一个参考指标,而不是自动决策开关。
4.4 三种估计方法的对比表格
| 方法 | 数学目标 | 抗过拟合能力 | 不确定性表达 | 计算成本 |
|---|---|---|---|---|
| MLE | max log P(Data | θ) | 弱,小样本易极端 | 无(只有点) |
| MAP | max [log P(Data | θ)+log P(θ)] | 中等,等价于L1/L2正则 | 有限(可通过曲率近似) |
| 全贝叶斯 | 计算整个 P(θ | Data) | 强 | 完整后验分布/预测分布 |
5. 落地时的先验选择、结果解释与翻车预防
5.1 先验设置的三个实用准则
第一,能利用历史数据就别空想。评估新老功能对比时,老版本的数据就是天然先验。如果你已经在跑一个功能100天,日均转化率1.8%,标准差0.3%,那 Beta 先验参数可以直接按“等价样本量”折算:样本量等于方差的倒数量级的,直接代入就行。
第二,没有可靠信息时,用弱信息先验,而不是假装“无信息”。我见过不少人用 Beta(1,1) 均匀分布当“无信息先验”,然后声称自己是客观的。但“无信息”本身就是一种信息假设:它认为所有取值概率相同。参数做变换后(比如从概率 p 换成 log-odds),均匀先验就不再均匀。实际操作中,除非样本量极低,否则 Beta(1,1) 和弱信息先验的差异很快会被数据抹平;真正危险的是强先验,强先验在小样本下会全面接管结论。
第三,无论选了什么先验,必须做敏感性分析。固定同一组数据,分别用“无信息先验”“弱信息先验”“略有偏差的强先验”跑一遍。如果后验结论在两个先验之间发生了质变(比如从“显著为正”变成“不确定”),那只能说明当前数据量不足以支撑稳健结论。这个结论本身就有价值:它告诉你还需要继续收集数据,而不是强行拍板。
5.2 给非技术人解释贝叶斯结果时的沟通模板
做算法不止要算得对,还要讲得清。我总结了一套话术,业务方普遍能接受:
“我们现在掌握的数据是X,但样本量不大,单看数据容易高估。我们给它加了一个先验假设,来自历史大盘/行业经验,相当于给估计值一个合理的‘起点’。计算出来的不是一个孤独的数字,而是一个分布。比如版本B的相对提升,后验期望是1.2%,90%的可信区间是 [0.3%, 2.1%],也就是说在90%的概率下,提升落在0.3到2.1个百分点之间。”
这里重点区分两个词:“可信区间”和“置信区间”。贝叶斯的可信区间(credible interval)是说“参数有 90% 概率落在这个区间内”,频率派的置信区间(confidence interval)则必须解释成“重复抽样会有90%区间覆盖真值”。两句话在业务语境下听起来差不多,但语义差异很大。项目文档里我会刻意标注清楚,避免审计和复查时产生歧义。
5.3 几个我真实踩过的坑
先验数据泄漏。早期做转化率预估时,我把老版本“上线后所有数据”都揉进先验,然后用新版本前两周数据做对比。结果老版本先验里混入的“实验期间波动”让后验收缩过头,导致新版本看起来提升幅度被低估。后来规定:构造先验只能用观测窗口之前或外部渠道的数据,绝不能用同期任何信息。
把似然当概率,导致以为代码写错了。连续分布下某些点的密度值可以大于1,我第一次算出来一个似然值等于3.2时确认了三遍代码。确定性地说:离散概率永远在 [0,1],连续密度函数的值与量纲有关,不必大惊小怪。调试时建议把“对数似然”打出来,看到负数才是正常的。
MAP 点估计被当成全贝叶斯用。有些场景(比如小样本冷启动)点估计方差大是致命问题。MAP 只是众数,后验尾巴有多厚、对称性如何,它完全不管。需要给业务解释“不确定性”时,必须回退到完整后验或至少用拉普拉斯近似得出方差。
过度相信默认先验。PyMC 和 Stan 里默认先验都很宽,看似“不干预”,实际上在极度稀疏的数据下会让后验变成一大堆不合理的厚尾。曾在一个稀疏事件率模型里用默认指数先验,得出的事件率区间下界都为正、上界大得惊人,业务方差点拿去当预算依据。后来换成了基于同类产品均值的弱信息先验,才得到合理范围。
5.4 工具选型
先上结论:
- 只有一两个参数、能写出共轭先验的场景(Beta-Bernoulli、Gamma-Poisson、Normal-Normal),直接用 scipy.stats 或 numpy 手算/网格/画图,不引入额外重依赖。
- 参数稍微多点、要正经做推断,优先 PyMC(Python 生态友好)或 Stan(rstan/cmdstanpy)。MCMC 采样慢,但能处理复杂后验。
- 生产环境对延迟敏感,需要实时给出后验/预测分布,不要上采样方法。可以考虑变分推断、拉普拉斯近似,或者把问题裁剪成共轭模型再上线。
常见共轭组合可以存一份备忘:
| 似然模型 | 共轭先验 | 后验参数更新 |
|---|---|---|
| 伯努利/二项 | Beta(α, β) | Beta(α+成功数, β+失败数) |
| 泊松 | Gamma(α, β) | Gamma(α+事件数, β+暴露量) |
| 正态(方差已知) | Normal(μ₀, σ₀²) | 均值按精度加权平均 |
| 正态(均值已知) | Inv-Gamma | 方差按精度更新 |
如果你不想背表,记住 Beta↔二项、Gamma↔泊松这两组就够了,业务里绝大多数计数类、转化率类问题都落在这两个框里。
最后再分享一个个人习惯,可能比任何公式都管用:每当我看到一个“准确率95%”“p<0.05”“显著提升”的结论,我会强迫自己写下三个数字——先验是什么、似然的分子是什么、分母是什么。因为这正是贝叶斯公式逼你想清楚的东西。先验是你原本相信的,似然是数据告诉你的,后验是你最终应该相信的。把这三者理清楚,即使不做贝叶斯建模,你的业务判断也会稳很多。