
如果你手头正在读《人工智能数学基础》这本书大概率已经在前面十七章的微积分、线性代数和概率统计里熬得有点上头了。到了第十八章很多人会以为又是一堆枯燥推导但恰恰相反这一章我个人认为是全书里“数学”与“AI实战”之间最接近的一道桥。第十八章讲的是概率图模型它把前面那些零散的分布、条件概率、矩阵运算和优化方法真正拧成了一股能解决实际问题的力量。这一章能解决什么问题举个直白的例子智能推荐系统要同时判断“用户会不会点”“点了之后会不会买”语音识别要在一串声学信号里推断最可能的文字序列医疗辅助诊断要把症状、检查结果和疾病之间的因果关系建模出来。这些场景里变量多、关系复杂不是单靠一个概率公式能搞定的而是需要一种既能表达变量之间依赖关系、又能在数学上方便计算的工具这就是概率图模型。读完这一章你会掌握贝叶斯网络、马尔可夫随机场、隐马尔可夫模型、推断与参数学习这些核心内容也就能看懂后续很多深度学习模型比如生成对抗网络、图神经网络背后的数学逻辑。这套内容适合谁如果你是正在补数学底子的AI工程师或者刚学完概率统计的本科生又或者是从应用开发转到算法方向的程序员这一章都是绕不开的必修课。下面我把这一章的核心思路、关键推导和实操中踩过的坑一条条拆开讲清楚。1. 第十八章的定位为什么偏偏是概率图模型1.1 从“单点概率”到“结构化概率”的思维升级前面章节里处理的大多是单个或少数几个随机变量一个正态分布、两个变量的协方差、一组样本的极大似然估计。这些工具在面对“只有一个随机事件”的问题时足够用但真实AI问题几乎没有这么简单的。举个例子你要判断一封邮件是不是垃圾邮件。光看“邮件里有没有‘中奖’这个词”是不够的还要看“发件人是不是陌生人”“邮件里有没有链接”“正文是不是全大写”等等。这些特征之间不是各自独立的垃圾邮件里“中奖”和“链接”往往同时出现普通邮件里这两个词很难碰到一起。你需要一个框架把这些变量之间的依赖关系明确地表达出来同时又能算出“给定这些词这封邮件是垃圾的概率”。概率图模型干的就是这件事。它用图来编码概率分布节点代表随机变量边代表变量之间的依赖关系。这样一来原本需要指数级参数才能描述的联合分布被拆解成一组局部条件的乘积计算量大幅下降。这正是第十八章放在整本书偏后位置的原因——它需要你同时具备概率、矩阵、图论和优化的基础是前面所有数学工具的综合演练场。1.2 学完这一章你能上手哪些实际任务从工程角度看学了这一章之后你能做的事情非常明确。第一是建模看到一个业务问题能判断变量之间是有向的因果依赖还是无向的关联约束并画出对应的图结构。第二是推断在已知部分观测数据时能算出其他变量在某个条件下的概率分布比如根据用户的历史点击记录推断他当前最可能感兴趣的商品类别。第三是学习在有数据的情况下能估计出模型里的参数比如隐马尔可夫模型里的状态转移矩阵和发射矩阵。这三个能力几乎覆盖了AI入门阶段所有核心场景。推荐系统、语音识别、自然语言处理里的序列标注、计算机视觉里的图像分割底层都在用概率图模型的思路。第十八章之所以重要不是因为它的公式特别难而是因为它第一次把“从数据里学一个可解释的概率模型”这件事完整地走了一遍。2. 核心知识点拆解从有向图到无向图2.1 贝叶斯网络用有向图表达因果依赖贝叶斯网络是第十八章最先引入的模型也是最容易理解的一类概率图模型。它用有向无环图DAG表示变量之间的依赖从原因节点指向结果节点。每个节点都带一个条件概率表描述它在父节点取值给定的情况下的概率分布。假设我们有一个简单的学生成绩模型课程难度D、学生智力I、最终成绩G、推荐信质量L。D和I共同影响GG影响L。这个模型的联合分布可以写成P(D, I, G, L) P(D) × P(I) × P(G|D, I) × P(L|G)这就是贝叶斯网络的因子分解。你可能会问为什么要拆成这么一串直接用一个联合概率表 P(D, I, G, L) 不是更简单吗问题在于参数量。如果每个变量有 k 个取值完整联合表需要 k^4 个参数而拆成局部条件后每个条件表只依赖少数父节点总参数量大幅减少。变量越多这个优势越明显这正是图结构让复杂分布变得可处理的核心原因。贝叶斯网络里还有个非常重要的概念叫 D-分离用来判断两个节点在给定某些观测节点后是否条件独立。初学者最容易在这里摔跟头的是对撞结构。比如上面例子中成绩G同时是难度D和智力I的孩子那么当G未知时D和I是相互独立的先验独立但当你知道G很高之后D和I就不再独立了——一个学生成绩好要么因为课程简单、要么因为智力高如果课程明显很难那你就会更倾向于相信这个学生智力也高。这种现象在AI里叫“explain away”中文常译作“解释消除”是条件独立中非常微妙也特别有用的一条性质。2.2 马尔可夫随机场无向图表达对称关联与贝叶斯网络不同马尔可夫随机场用的是无向图。它更适合表达变量之间的“软约束”或“关联”而不是显式的因果方向。典型的场景是图像去噪每个像素是观测每个像素的真实值是一个隐变量相邻像素之间应该有相近的颜色这种关系是对称的没有谁“导致”谁所以用无向图更自然。马尔可夫随机场的联合分布由定义在团clique全连接的节点子集上的势函数相乘得到P(X) (1/Z) ∏_C φ_C(X_C)这里的 φ_C 是团C上的非负势函数Z是配分函数用来保证所有概率之和为1。这个 Z 在推断和参数学习里都是核心难点因为它是所有可能取值的求和或者积分在高维空间里几乎不可能暴力计算。这也是无向图模型和有向图模型在实际使用中最重要的区别之一贝叶斯网络的局部条件是天然归一化的而无向图必须额外处理那个全局归一化常数。2.3 两类模型怎么选很多新手读完两种模型后会纠结遇到实际问题到底该用哪个我的经验是如果你能明确说出变量之间的因果关系比如“天气导致海藻湿度变化”那就用贝叶斯网络如果你面对的是一种结构化的空间或时序关联比如“相邻像素应该相似”“相邻词性应该搭配”用马尔可夫随机场更自然。还有一个务实的选择标准如果你需要生成样本比如根据模型生成一段文本通常选有向图模型因为采样时直接从根节点按拓扑序生成即可如果你更关心在给定观测后推断隐变量的条件分布并且数据里很多变量天然具有对称关联那么无向图模型往往更贴合。实际工程里还有一种折中方案叫条件随机场它把无向图模型用在条件分布 P(Y|X) 上绕开了对 X 建模的问题在自然语言处理里非常流行。3. 推断问题看懂前向算法就懂了隐马尔可夫模型3.1 变量消去法与信念传播的直观理解图模型建好之后最核心的问题是推断给定部分观测求某个变量的边缘概率或最可能取值。最朴素的做法是直接摊开整个联合分布再求和但高维空间里这样做的计算量是灾难级的。变量消去法的思想很直接按顺序消去变量时把涉及它的因子乘在一起求和再把结果作为新因子传给后续变量。这就像解线性方程组时的高斯消元区别只在处理的是概率因子。信念传播是变量消去法在树结构图上的系统化实现。在有向树或无向树上每个节点向邻居传递“消息”消息代表该节点对邻居在某种状态下的“信念”。经过两轮传递后每个节点都能拿到周围所有信息从而算出自己的边缘分布。你可以把它想象成一群人在一条链上传纸条每个人只跟左右邻居碰头但最终所有人都能汇总整个链条的信息。树结构上信念传播收敛且精确一旦图里出现环路就必须用循环信念传播这类近似算法这也是十八掌后面会提到的内容。3.2 用2状态3观测的例子手推一遍前向算法隐马尔可夫模型HMM是贝叶斯网络在时序数据上的特例也是第十八章里最接地气的部分。它有三个关键要素初始状态分布π、状态转移矩阵A、观测发射矩阵B。这三个要素对应的三个经典问题分别是评估观测序列概率前向算法、解码最可能状态序列维特比算法、从数据学习参数鲍姆-韦尔奇算法本质上就是EM。我当年学HMM时把书上的推导来回看了三遍都没真正理解后来手推了一个极小例子才通。这里也带你推一遍。假设两种状态晴天(S1)和雨天(S2)两种观测海藻干(D)和海藻湿(W)。初始分布 π[0.8, 0.2]转移矩阵 A 中S1到S1是0.7S1到S2是0.3S2到S1是0.4S2到S2是0.6发射矩阵 B 中晴天时观测到干海藻概率0.8、湿海藻概率0.2雨天时观测到干海藻概率0.3、湿海藻概率0.7。现在观测序列是 [D, W, W]求这个序列出现的概率。前向算法定义一个前向变量 α_t(i)表示“到t时刻为止的观测序列且当前状态为Si”的概率。t1时直接乘初始分布和发射概率α1(S1) 0.8 × 0.8 0.64 α1(S2) 0.2 × 0.3 0.06t2时利用上一时刻的结果递推。α2(S1) (α1(S1)×0.7 α1(S2)×0.4) × 发射概率(当前观测为W时S1的发射概率0.2) (0.448 0.024) × 0.2 0.0944。同理α2(S2) (0.64×0.3 0.06×0.6) × 0.7 (0.192 0.036) × 0.7 0.1596。t3时继续递推α3(S1) (0.0944×0.7 0.1596×0.4) × 0.2 (0.06608 0.06384) × 0.2 0.025984 α3(S2) (0.0944×0.3 0.1596×0.6) × 0.7 (0.02832 0.09576) × 0.7 0.086856最后把两个状态的前向变量相加P(观测序列) 0.025984 0.086856 0.11284。这一步推完你才能真正感受到前向算法的高明之处它把指数级的路径数量压缩成了每一步只做 n^2 次乘法。如果直接枚举所有状态路径2个状态3步就有 2^38 条路径状态一多就是灾难而前向算法的复杂度只跟“状态数平方 × 时间步数”成正比这才是它能实际落地的原因。3.3 近似推断MCMC与变分推断是怎么回事精确推断在树结构上可行但一旦图变复杂、节点变多精确推断的计算复杂度会爆炸。这时就需要近似推断。第十八章通常会介绍两大类方法马尔可夫链蒙特卡洛方法MCMC和变分推断。MCMC的思路是用采样的方式逼近目标分布。它的核心是构造一条马尔可夫链让链的平稳分布恰好等于我们要采样的分布然后在链上走足够久之后采出来的样本就近似来自目标分布。有一个很能帮助理解的类比你想知道一个会场里的人群分布与其精确计算每个人的位置不如在场内随机走动走到哪里停下来就把那个位置记录一下走得越久记录点的密度就越接近真实分布。吉布斯采样就是MCMC里最常用的算法之一每次固定其他变量、只采样一个变量反复迭代。变分推断的思路完全不同。它不采样而是把推断问题变成一个优化问题找一个形式简单的分布 q让它尽可能接近真正的后验分布 p然后用 q 代替 p 做后续计算。衡量两个分布距离的工具是KL散度但直接最小化 KL(p||q) 是走不通的因为涉及p的证据项所以实际操作中优化的是证据下界ELBO。你可以把变分推断理解为“既然精确算不出那个复杂分布我就找一个长得像的简单分布来近似”代价是引入偏差收益是可扩展性强、计算速度快。现代深度学习里的变分自编码器用的就是这套思路。4. 参数学习从极大似然到贝叶斯估计4.1 数据完整时贝叶斯网络的参数怎么学推断解决的是“已知模型参数求概率”的问题而参数学习解决的是“已知数据求模型参数”的问题。有向图模型的一大优势是当数据完整每个变量都有观测值时参数估计可以分解成每个节点独立的极大似然估计。你只需要对每一个节点统计它的父节点组合下各类取值的频率做归一化就能得到条件概率表。这个过程本质上就是朴素贝叶斯分类器做的事情。朴素贝叶斯做了一个很强的假设给定类别后所有特征条件独立。于是它的联合分布就分解成 P(类别) 乘上一串 P(特征|类别)每个 P(特征|类别) 都能独立地从数据里统计出来。虽然这个独立性假设在现实中几乎不成立但它照样在很多文本分类任务上表现不错原因在于即使概率估计有些偏差类别之间的相对大小关系往往还能保持住。4.2 数据缺失和隐变量存在时EM算法登场现实中的数据常常有缺失值更常见的是存在完全观测不到的隐变量。比如HMM里的状态序列就是隐变量你只能观测到每个时刻的发射结果看不到背后的真正状态。这种情况下直接做极大似然估计会遇到问题对数似然函数里因为有隐变量变成对隐变量求和的 log没法直接求导。这时候就需要EM算法。它的思路分两步循环E步骤用当前参数推断隐变量的后验分布相当于“补全”缺失信息M步骤用这些补全后的信息重新估计参数相当于“更新模型”重复直到收敛。HMM里的鲍姆-韦尔奇算法就是EM在HMM上的特例。我最初学EM时总觉得它像魔术后来想通了它其实是在反复执行“猜隐变量—根据猜测改进参数—再猜”每一步都能保证对数似然不会下降所以最终会收敛到一个局部最优解。4.3 无向图模型的学习为什么更麻烦无向图模型的参数学习比有向图麻烦得多根本原因就是那个配分函数Z。极大似然估计对每个参数求梯度时配分函数的梯度项来自模型自身的期望而这个期望又涉及高维求和没法直接算。实际工程里常用对比散度算法用吉布斯采样跑几轮马尔可夫链用采样得到的经验分布来近似那个棘手的期望项。这也是受限玻尔兹曼机训练时的标准做法。另外一个务实技巧是加先验。不管有向图还是无向图参数学习里都建议做平滑。以朴素贝叶斯为例如果某个词在训练数据里没出现在“垃圾邮件”类中那么 P(词|垃圾邮件) 会算成0一旦预测时遇到这个词整封邮件的概率乘积直接变成0非常不鲁棒。常用的解决方案就是拉普拉斯平滑分子加一个正数α分母加 α×类别数。这个看起来不起眼的操作在实际分类器里救过我好几次。5. 实操自己动手搭一个Numpy朴素贝叶斯分类器5.1 问题定义与建模让理论落地最快的方式是做一个小项目。我用最简配置跑一个垃圾邮件分类器模型就是第十八章里的朴素贝叶斯特征是词袋Bag of Words目标是把邮件分成“垃圾”和“普通”两类。建模过程其实就是在定义一个最简单的贝叶斯网络类别节点C是根节点它同时是每个词节点 W1, W2, ..., Wn 的父节点。朴素贝叶斯假设给定C后所有词节点互相独立所以联合分布是 P(C) × ∏ P(Wi|C)。这个网络结构虽然简单但已经足够演示图模型的建立、参数估计和推断完整流程。5.2 实现细节与关键代码实现时有几个细节非常影响效果。首先是文本预处理把邮件转成小写、按空格和标点分词去掉长度小于1的无效词还可以按需去停用词。然后是构建词表词表大小直接影响特征维度一般会去掉出现次数小于某个阈值的低频词既降维又去噪。最后是训练时统计各类别的先验概率和每个词在各类别下的条件概率记得加平滑。下面是训练核心部分包括拉普拉斯平滑的关键处理。import numpy as np def train_naive_bayes(x_train, y_train, alpha1.0): num_docs, vocab_size x_train.shape num_classes 2 prior np.zeros(num_classes) cond_prob np.zeros((num_classes, vocab_size)) for c in range(num_classes): docs_c x_train[y_train c] prior[c] len(docs_c) / num_docs total_count_c docs_c.sum() alpha * vocab_size cond_prob[c] (docs_c.sum(axis0) alpha) / total_count_c return prior, cond_prob这里alpha就是拉普拉斯平滑的系数alpha1.0是最常见选择。cond_prob[c]里存的是每个词在类别c下的估计概率。预测时要用对数概率防止数值下溢。因为邮件里可能有几百个词几百个小于1的概率连乘浮点数会直接变成0在log空间里把这些概率相加就不会有这个问题。def predict_naive_bayes(x_test, prior, cond_prob): log_prior np.log(prior) log_cond np.log(cond_prob) log_prob_c0 log_prior[0] x_test log_cond[0] log_prob_c1 log_prior[1] x_test log_cond[1] return np.where(log_prob_c1 log_prob_c0, 1, 0)5.3 实验结果与调参心得我用这个简单模型在经典邮件数据集上试过不加任何工程优化时准确率大约在88%左右加了低频词裁剪和停用词过滤之后能到93%上下再把alpha从1.0调大到2.0准确率又能涨零点几个百分点。调参过程中我总结了几条亲测有效的经验。第一平滑系数alpha太小比如0.01在词表很大的时候会让概率估计非常极端出现过拟合太大比如10会让所有概率往均匀方向拉淹没真实信号。合理范围通常在0.5到2之间具体要靠验证集试。第二低频词裁剪的阈值一般设成2或3保留出现次数太少的词只会增加噪声。第三去停用词对准确率的提升非常明显因为像“的”“了”“the”“a”这类词在每个类别里几乎同样频繁留着它们只会把概率稀释。6. 常见问题与避坑指南6.1 几个新手必踩的坑我见过很多同学学到第十八章时理论读得通一到作业和项目就卡壳问题大多出在下面几个地方。第一个坑是把观测变量和隐变量搞混。贝叶斯网络里节点本身没有“观测”和“隐”的固有标签同一个节点在这个数据里是观测到的在那个数据里可能就缺失了。你要清楚自己手里有哪些证据变量哪些是待推断变量这决定了你在图上做的到底是“推理”还是“学习”。搞反了这一步后续公式全乱。第二个坑是条件独立的判断方向搞错。无向图模型里条件独立的判断非常简单给定某个节点集合S后如果移除S能把两个节点分到不同连通分量那它们条件独立。但有向图模型的D-分离判断要复杂得多特别是遇到对撞结构时独立性方向会反转。很多人在“未观测对撞节点时父节点独立观测后反而依赖”这一点上反复出错。第三个坑是忽略配分函数Z。有人用无向图模型做推断时直接拿未归一化的势函数乘积当作概率算出来的“概率”加和根本不为1。如果只是比较相对大小不归一化问题不大但只要涉及期望、边缘概率或似然值就必须算Z或者用方法绕过它。第四个坑是对离散变量硬套高斯分布。有些同学习惯了正态分布看到连续型变量就直接假设高斯但很多真实数据是长尾或多峰的。第十八章里强调图模型只是骨架节点上的分布类型要根据数据特点来选择离散用伯努利或多项分布计数数据用泊松连续数据才考虑高斯这一步选错整个模型都会被带偏。第五个坑是只盯着准确率不看概率校准。分类器输出的概率值本身有没有意义在很多业务场景里很重要。比如你要根据模型输出概率决定是否触发某个策略概率偏高或偏低都会造成损失。朴素贝叶斯输出的概率通常不够校准如果业务上需要可靠的置信度建议再做一次Platt缩放或等分回归。6.2 问题排查思路速查表我把实操中经常遇到的问题按“现象、原因、排查方向”整理成一张表遇到类似情况可以直接对照排查。现象可能原因排查方向训练时损失不下降学习率过大或过小、数据未归一化检查梯度量级先调低学习率再试模型输出概率全为0或1数值下溢 / 未做平滑转log空间运算加拉普拉斯平滑推断结果与直觉不符图结构连边错误 / D-分离判断错误画出图结构逐个检查条件独立假设无向图模型训练极慢配分函数Z的计算量过大改用对比散度近似或减小批次规模预测时遇到训练中未见过的词词表外单词未处理构建词表时预留UNK项或直接忽略低频词两个模型效果差不多特征质量不足模型能力已经到瓶颈优先做特征工程再考虑换复杂模型6.3 学习建议与配套实践如果你在学这一章时觉得吃力我建议你按这个顺序做三件事。第一把前面概率论章节里的“条件概率、贝叶斯公式、全概率公式”翻出来再过一遍这一章所有内容都建立在这几个公式上基础不牢后面越看越晕。第二找任何一个电子表格工具自己手算一个小型贝叶斯网络的推断过程哪怕只有两个节点、两张条件概率表亲手把前向算法的每一步算出来理解深度完全不一样。第三动手写一个朴素贝叶斯分类器用到拉普拉斯平滑、对数概率这些技巧遇到真实数据里的各种坑之后你才会真正理解参数估计为什么需要那些看似多余的处理。拓展阅读方面我推荐配合第十八章一起看《Pattern Recognition and Machine Learning》里关于图模型的章节那本书的图模型部分讲得更系统如果对应用更感兴趣可以再找序列标注相关教程把HMM和条件随机场的应用案例过一遍。我个人在实际学习中的体会是第十八章最值得花时间的不是某个公式的推导过程而是建立起“用图来描述概率结构”这种思维模式。以前看到一个问题我的第一反应是找公式套上去学完这一章之后你会习惯性地先画变量、再画关系、然后才考虑算法的选择。这种思维上的转变才是这一章真正的收获。最后再分享一个小技巧读这一章时别用“看课件”的方式而是用“写代码”的方式检验自己。每学完一个模型就顺手实现一个极小的版本哪怕只是随机生成数据跑通流程也比盯着书上例题发呆有效得多。我当年就是在把HMM前向算法写成代码后才彻底想明白那些下标到底是怎么递推的。希望这一章也能成为你把数学基础转化为AI实战能力的关键一步。