简介南大出品的《机器学习导论》第07章贝叶斯分类器课件面向机器学习入门者与人工智能方向学生系统讲解在概率框架下如何进行分类决策帮助读者理解贝叶斯决策论与贝叶斯风险等核心概念。内容从贝叶斯定理与先验概率、似然、证据因子讲起厘清判别式模型与生成式模型的差异随后深入极大似然估计与朴素贝叶斯分类器介绍拉普拉斯修正、连续属性概率密度估计等处理细节再拓展到半朴素贝叶斯中的SPODE、TAN与AODE策略以及贝叶斯网络的结构表达、道德图、条件独立性和推断方法完整呈现从基础假设到复杂依赖建模的知识链路。资源为1个PDF文件共23页压缩包大小约1.05MB排版清晰、公式完整方便随时查阅、打印或作为课件补充。目前已有118人学习下载适合在备考、课程复习或项目实战前快速构建贝叶斯分类器部分的系统认识。1. 为什么说贝叶斯分类器是机器学习里最“反直觉”的一条路很多入门机器学习的朋友学完线性回归和决策树之后拿到这份《机器学习导论》第07章贝叶斯分类器讲义第一感觉是懵前面那些算法全是盯着输入到输出的映射关系硬学怎么到了贝叶斯这里突然开始讲概率、讲先验、讲似然了这份23页的PPT恰恰是帮你从“判别式思维”切换到“生成式思维”的关键一章——它不直接学决策边界而是先给每一类数据建模回答“这堆数据是怎么产生的”再反过来推断新样本该归哪一类。看懂这一章你才算真正把机器学习从“找规律”升级到“做推断”。这篇笔记就是把23页讲义展开成能落地的方案公式怎么理解、代码怎么写、参数怎么调、哪些地方新手容易翻车一步步讲清楚。2. 先看懂第07章的核心贝叶斯决策论到底在干什么2.1 从贝叶斯公式到后验概率机器学习的“上帝视角”贝叶斯分类器的一切推导都建立在贝叶斯公式上。公式本身很简单P(ωᵢ|x) P(x|ωᵢ) · P(ωᵢ) / P(x)其中ωᵢ表示第i个类别x是样本特征向量。这里每个符号在机器学习语境下都有明确含义PPT里通常会花好几页来回解释它们之间的关系我整理成一张速查表符号名字机器学习里的含义哪里来P(ωᵢ)先验概率不看样本时类别i本身出现的比例训练集里数一数P(xωᵢ)类条件概率密度假设已知是类别ix长成这样的可能性P(x)证据因子所有类别下x出现的总概率全概率公式通常不用真算P(ωᵢx)后验概率看到样本x之后它属于类别i的概率初看这个公式你可能会觉得这就是个条件概率的简单变形没什么了不起。但放在机器学习里它的思维方式是革命性的判别式模型比如逻辑回归直接学 P(ωᵢ|x) 这个边界生成式模型则是先学 P(x|ωᵢ) 和 P(ωᵢ)再通过贝叶斯公式反推后验。换句话说贝叶斯分类器试图理解“每一类数据长什么样”而不是“两类数据之间画在哪”。这个区别在数据量少、噪声大的时候尤其重要。理解了生成式模型的思路再看吴恩达、李宏毅这些课里的贝叶斯部分你会发现大家讲的都是同一套概率语言只是侧重不同。2.2 最小错误率决策为什么后验概率最大就是最优分类问题最终要落到决策上给定一个样本x我该把它判给哪个类别最朴素也最合理的准则就是最小化分类错误率。可以证明把样本判给后验概率最大的那个类别期望错误率最小。这就是最小错误率贝叶斯决策规则决策结果 argmax over i P(ωᵢ|x)这个结论看起来平淡但它有一个隐藏前提经常被忽略它默认所有分类错误的代价是相同的。换句话说把A错判成B和把B错判成A对你来说损失一样。实际工程里根本不是这么回事——医疗诊断中漏诊的代价远大于误诊风控场景里放走坏人的代价远大于误伤好人。所以《机器学习导论》这门课在讲完最小错误率之后一般会紧接着引入风险的概念。引入损失函数λ(αᵢ|ωⱼ)表示“真实类别是ωⱼ却做出决策αᵢ”的代价于是条件风险变成R(αᵢ|x) Σⱼ λ(αᵢ|ωⱼ) · P(ωⱼ|x)这时候最优决策就变成了最小化条件风险而不是单纯最大化后验概率。当损失函数是0-1损失时最小风险决策恰好退化成最小错误率决策前后逻辑就闭环了。这个“0-1损失退化成后验最大”的推导是期末复习和面试八股里高频出现的考点建议你亲手推一遍。2.3 判别式与生成式的分岔口贝叶斯分类器的定位学这一章的时候脑子里要有一张全局地图机器学习算法可以分为两大类。判别式模型直接学习决策边界典型代表是逻辑回归、支持向量机、决策树生成式模型则对每一类的数据分布分别建模典型代表是贝叶斯分类器、高斯判别分析、隐马尔可夫模型。两者的关系不是谁替代谁而是适用场景不同。生成式模型有它的独特优势数据量小的时候先验和类条件概率的估计比较稳定不容易过拟合对缺失数据天然友好因为可以基于概率分布做推断还能输出“样本属于每个类别的置信度”而不是只给一个硬标签。缺点也明显当特征维度很高、分布假设不符合实际时类条件概率密度很难估准性能反而不如判别式模型。我在实际项目里的经验是特征维度低于50、数据量几千到几万这个区间贝叶斯分类器是值得优先试的baseline但如果是图像、文本这类高维稀疏数据就别指望朴素贝叶斯打天下了它的独立性假设会被现实狠狠教育。这个分寸感等你看完后面几章会更清楚。3. 把公式变成能算的机器概率密度估计这条主线3.1 为什么必须假设分布形式参数化估计的思路贝叶斯决策规则在理论上很完美但落地时立刻遇到一个现实问题P(x|ωᵢ) 是个概率密度函数你手里只有训练数据怎么知道它长什么样最常见也最实用的做法是参数化估计——先假设类条件概率密度服从某种已知分布最常见的是高斯分布再用训练数据估计这个分布的参数。这就是“参数化估计”四个字的含义。选择哪种分布假设决定了贝叶斯分类器的具体形态假设参数形式分类器名字特点每类特征独立且同方差每类一个均值共享方差朴素贝叶斯高斯版最简单参数少小样本友好每类高斯协方差矩阵共享每类均值共享协方差线性判别分析LDA决策边界是线性的每类高斯协方差各自独立每类均值各自协方差高斯判别分析QDA决策边界是二次曲线更灵活这里有个新手容易迷路的点高斯朴素贝叶斯和高斯判别分析都是假设高斯分布为什么P(x|ωᵢ)的式子长得不一样区别就在协方差矩阵上。朴素贝叶斯假设特征之间相互独立协方差矩阵是对角阵非对角元素全为0高斯判别分析则允许特征之间存在相关性协方差矩阵是完整的。这个差异直接决定了决策边界的形状。参数化估计的好处是效率高——高斯分布只要估计均值和方差两个参数几百个样本就能估得比较稳。坏处是假设可能不符合实际比如数据其实是多峰的硬用单峰高斯去拟合模型就废了。遇到这种情况可以考虑混合高斯模型或者核密度估计那属于非参数估计的范畴这门课的23页PPT一般是不会展开的但你要知道有这么条路。3.2 高斯分布下的极大似然估计均值与协方差的公式推导假设我们选定用高斯分布建模某一类的数据下一步就是用极大似然估计MLE来求解参数。给定类别ωᵢ的训练样本集合Dᵢ假设样本独立同分布似然函数写成L(μᵢ, Σᵢ) ∏ₖ (1 / ((2π)^(d/2) |Σᵢ|^(1/2))) · exp(-0.5 (xₖ-μᵢ)ᵀ Σᵢ⁻¹ (xₖ-μᵢ))直接对这个连乘求导很麻烦通常取对数把连乘变成连加然后分别对μᵢ和Σᵢ求偏导并令其为0。推导结果非常干净均值μᵢ的MLE估计就是样本均值协方差矩阵Σᵢ的MLE估计就是样本协方差矩阵。公式不复杂但推导过程极容易算错尤其是对Σ求导那一大串矩阵微积分很多人在期末复习时在这里卡壳。一个值得注意的细节MLE估计的协方差矩阵是有偏的分母除以的是样本数n而不是n-1。对于判别分析这类算法这个偏差影响不大因为分母的n和n-1在样本量几百以上时几乎没有区别。但如果你在极端小样本场景下用贝叶斯分类器建议手动改成无偏估计也就是分母用n-1可以让数值更稳。3.3 朴素贝叶斯的“独立性假设”到底牺牲了什么朴素贝叶斯之所以带“朴素”二字是因为它做了一个很强的简化假设给定类别时特征之间相互独立。数学上写作P(x|ωᵢ) ∏ⱼ P(xⱼ|ωᵢ)这个假设在实际数据里几乎从来都不成立——现实生活中很少有什么特征是完全独立的。但神奇的是朴素贝叶斯在文本分类、垃圾邮件过滤这些场景下表现得非常好甚至碾压一些复杂模型。原因有两方面一是很多任务里决策边界对概率估计的误差并不敏感只要各类后验概率的相对大小没错绝对值偏一点也没关系二是参数少、估计方差小偏差换方差的这笔交易在数据量有限时往往划算。工程上还有一个隐藏的好处特征独立假设让计算变得极其廉价。每个特征可以单独建模支持增量更新遇到缺失特征时只需要跳过那一项乘积实现起来非常灵活。所以在做垃圾邮件过滤、情感分析这类高维稀疏特征任务时先跑一个朴素贝叶斯baseline几乎不费什么力气。不过这个假设也有翻车的时候。当特征之间强相关时朴素贝叶斯会“过度自信”——它把重复的相关特征当作多条独立证据后验概率被推得过于极端。比如分类电影《唐人街探案》时如果把“王宝强出演”“喜剧演员王宝强出演”“王宝强唐仁”这三个高度相关的特征都算进特征向量朴素贝叶斯会把喜剧类的概率算得奇高无比。这种错误在分类决策上可能不致命但如果你的下游任务需要校准过的概率输出就要格外当心了。这个坑我会在第5章展开讲。4. 用Python复现PPT里的贝叶斯分类器从公式到可运行代码4.1 数据准备为什么用鸢尾花而不是自己造数据理解了公式之后最快的验证方式就是写代码把分类器跑通。这里我选择鸢尾花数据集原因是它只有4个特征、3个类别、150条样本分布接近高斯非常适合验证贝叶斯分类器的效果。更关键的是这个数据集足够小手写的贝叶斯分类器可以在毫秒级跑完方便你边写边对照公式。import numpy as np from sklearn.datasets import load_iris data load_iris() X data.data # 形状 (150, 4)四维特征 y data.target # 三类setosa, versicolor, virginica # 划分训练集和测试集保持类别比例一致 from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.3, random_state42, stratifyy ) print(X_train.shape, X_test.shape)这里有一个容易忽略的参数stratifyy。它保证训练集和测试集里三个类别的比例和原始数据一致避免某个类别在训练集中样本过少导致先验概率估计跑偏。random_state42不是随便写的它让数据划分可复现你和我的实验结果才能对得上。跑代码的人如果发现结果不一致先检查这两个参数是不是一样的。4.2 手写高斯判别分析核心逻辑只有三步接下来不借助sklearn手写一个高斯判别分析分类器。整个算法可以拆成三步估计每一类的先验概率、估计每一类的高斯参数、做决策时计算后验概率取最大。理解了这三步你就把PPT里那几页公式真正吃透了。class GDA: def __init__(self): self.priors {} # 每类的先验概率 self.params {} # 每类的 (均值, 协方差) def fit(self, X, y): classes np.unique(y) n_total len(y) for c in classes: X_c X[y c] # 先验 该类别样本数 / 总样本数 self.priors[c] len(X_c) / n_total # 均值 该类别样本的均值向量 mean np.mean(X_c, axis0) # 协方差 该类别样本的协方差矩阵MLE估计分母n cov np.cov(X_c.T, biasTrue) # 加一个小的对角项防止奇异 cov 1e-6 * np.eye(X.shape[1]) self.params[c] (mean, cov) def predict(self, X): log_posteriors [] for c, (mean, cov) in self.params.items(): # 计算多元高斯对数似然 对数先验 n_dim X.shape[1] diff X - mean inv_cov np.linalg.inv(cov) log_likelihood -0.5 * np.sum(diff inv_cov * diff, axis1) log_likelihood -0.5 * np.log(np.linalg.det(cov)) log_likelihood -0.5 * n_dim * np.log(2 * np.pi) log_posteriors.append(log_likelihood np.log(self.priors[c])) return np.argmax(np.array(log_posteriors), axis0) model GDA() model.fit(X_train, y_train) y_pred model.predict(X_test) print(准确率:, np.mean(y_pred y_test))这里有两个细节值得讲清楚。第一代码里用的是对数似然而不是直接乘概率密度原因是高斯密度的连乘每个样本乘一次很容易数值下溢——几十个0.001连乘结果就变成0了再取对数就变成负无穷。变量名写成log_posteriors就是提醒自己先取对数再做加法。第二协方差矩阵加了一个1e-6 * np.eye()的对角扰动这是防止某类样本量太少导致协方差矩阵不可逆。加了之后协方差矩阵不再精确等于MLE估计值但换来的是数值稳定性工程上是值得的。跑完这个代码你会发现准确率在95%左右。这个数字可以作为你验证代码是否正确的一个基准值。如果偏差太大优先检查上面的三个细节先验有没有归一化、协方差是不是按类别分别计算的、有没有用对数似然。4.3 用sklearn做对照GaussianNB与LDA的选择差异手写代码验证了原理接下来的标准动作是用sklearn里的现成实现做对照。这个对照是有价值的库的实现经过大量优化数值处理更稳健跑出来的结果可以作为你手写代码的“标准答案”。from sklearn.naive_bayes import GaussianNB from sklearn.discriminant_analysis import LinearDiscriminantAnalysis # 高斯朴素贝叶斯假设特征独立协方差对角化 gnb GaussianNB() gnb.fit(X_train, y_train) print(GaussianNB 准确率:, gnb.score(X_test, y_test)) # 线性判别分析各类共享协方差决策边界为线性 lda LinearDiscriminantAnalysis() lda.fit(X_train, y_train) print(LDA 准确率:, lda.score(X_test, y_test))GaussianNB和手写的GDA区别在于协方差矩阵的处理方式高斯朴素贝叶斯强行把协方差矩阵的非对角元素全部置零参数数量只有4个均值加4个方差LDA则假设所有类别共享同一个协方差矩阵手写的GDA允许每个类别有自己完整的协方差矩阵。三种策略的决策边界复杂度依次递增朴素贝叶斯是轴对齐的曲线LDA是直线GDA是二次曲线。在鸢尾花这个数据集上三者准确率差别不大都在95%左右。但换成更复杂的数据集差别会显现出来。我的经验是先用LDA跑一遍如果效果不行再上QDA即手写的GDA最后才考虑朴素贝叶斯。原因很简单朴素贝叶斯的独立性假设太强特征相关性一高就掉链子而LDA只假设共享协方差比朴素贝叶斯宽松得多又比QDA更不容易过拟合是性价比最高的起点。5. 贝叶斯分类器避坑指南5个高频问题和排查方法5.1 协方差矩阵奇异行列式直接变0预测报错或乱给结果现象代码运行到np.linalg.det(cov)或者np.linalg.inv(cov)时报错LinAlgError: Singular matrix或者不报错但预测结果随机。原因当某个类别的样本数小于特征维度时样本协方差矩阵的秩不够矩阵不可逆。另一个常见原因是特征之间存在完全线性相关比如两个特征总是一样的值。解决优先检查类别样本量至少保证每个类别的样本数大于特征数。然后给协方差矩阵的对角线加一个小的正则项也就是我在第4章代码里写的cov 1e-6 * np.eye(d)。如果问题还在把正则项调大到1e-3。这个操作在统计学里叫岭正则化本质是给你不充分的样本量“补一点方差”。5.2 先验概率估计偏差小样本下数数并不靠谱现象某个类别在训练集中只出现了3次但实际场景里这个类别占比30%。模型预测时把这个类别的后验概率压得极低几乎永远不会预测这个类别。原因先验概率的MLE估计就是样本频率。样本量小时频率估计的方差极大——抽到3个和抽到8个算出来的先验差快3倍。这个误差会通过贝叶斯公式直接放大到后验概率上。解决对先验做平滑处理。拉普拉斯平滑是最常用的方法P(ωᵢ) (nᵢ α) / (N α·K)其中K是类别总数α通常取1。更稳的做法是干脆不依赖先验用验证集重调决策阈值这点我在第5.5节展开讲。5.3 特征强相关时朴素贝叶斯过度自信现象分类文本时某条样本的后验概率算出来高达0.9999但实际验证时发现是错的。用gnb.predict_proba()查看概率输出发现极端值远多于其他模型。原因特征独立性假设在强相关特征面前失效相关的特征被当作独立证据重复累计导致似然连乘被高估。这就是我在3.3节提到的“重复计数”问题。解决特征工程上下功夫——做相关性分析把相关系数超过0.8的特征只保留一个或者改用LDA/QDA让协方差矩阵去建模特征相关性。如果必须用朴素贝叶斯至少要用predict_proba()输出的概率做一次校准比如Platt scaling别把原始概率直接当下游置信度用。5.4 数值下溢连乘似然变成0后验全乱了现象特征维度很高比如文本分类的几万维某个类的似然连乘结果在计算机里变成0取对数变成-inf最终各类别后验概率全是NaN或0。原因每个特征的条件概率都在0到1之间几千个小数连乘结果必然突破浮点数下限。解决全程使用对数空间计算永远不要算原始似然。把贝叶斯公式改成加法log P(ωᵢ|x) log P(x|ωᵢ) log P(ωᵢ) - log P(x)。别忘了log P(x)也用对数求和得到。sklearn的实现已经做了这个处理但你自己手写代码时最容易在这翻车。判断标准很简单如果代码里出现了多个概率变量直接相乘的语句大概率就有数值风险。5.5 样本不平衡后验概率有偏决策阈值需要重调现象二分类任务里正样本只占5%模型准确率95%但仔细看全部预测成了负类正样本一个没抓出来。原因先验概率本身就不平衡后验概率自然偏向多数类。这是贝叶斯分类器在类别不平衡场景下最典型的故障模式算法本身没问题是决策准则没适配任务目标。解决不要直接用0.5作为决策阈值。先算出每个样本的后验概率然后在验证集上扫描不同阈值选F1分数或召回率最优的那个点。如果任务对召回率有硬指标比如必须抓到90%的正样本直接按这个指标反推阈值。用公式表达就是argmax over threshold of Metric(P(ωᵢ|x) threshold)。6. 把23页PPT吃透之后一个验证分类器是否真学会的进阶技巧前面五章解决了“能跑起来”的问题最后这一步解决“跑对了没有”的问题。很多人训练完贝叶斯分类器只看一个准确率准确率高就认为万事大吉。这里我建议你多做一个动作画出决策边界和样本分布亲眼确认分类器学到的边界符合你对该问题域的直觉。具体做法是用二维数据。把鸢尾花数据集降到前两个特征训练一个LDA模型然后在平面上生成密集的网格点对每个网格点做预测用等高线画出分类区域。再把训练样本散点图画在同一个坐标系里观察样本是否落在对应的决策区域内、边界是否平滑、有没有异常突出的尖角。这个可视化虽然简单但能一次性暴露出多个问题协方差估计是否合理、决策边界是否过于复杂、数据点是否被错误地挤到边界的另一边。一个值得检查的现象是决策边界的形状是否与你的特征分布直觉一致。如果特征是近似高斯分布的LDA的决策边界应该是一条平滑直线QDA是一条平滑抛物线。如果你画出来的边界剧烈抖动、呈锯齿状通常意味着模型过拟合了——协方差矩阵被少量异常样本带偏这时候应该回退到共享协方差的LDA或者干脆用朴素贝叶斯。我的个人习惯是每个贝叶斯模型上线前都会用predict_proba输出后验概率的分布直方图看一眼。正确校准的模型预测正确的那些样本后验概率应该集中在0.8到1.0预测错误的样本后验概率应该集中在0.5附近。如果所有样本的后验概率都在0.99以上或者都在0.6以下说明概率没有校准好下游任务不能信任这个数值。这一步做完模型能不能上线我心里基本就有数了。贝叶斯分类器在23页PPT里只是一个章节但背后的生成式建模思想会让你之后看混合高斯模型、隐马尔可夫模型甚至是生成对抗网络时都受益。先把这个基础打牢后面的路会顺畅很多。希望帮到你。本文还有配套的精品资源点击获取
