COMP5318 Week 04 朴素贝叶斯与模型评估讲课总结
COMP5318 Week 04 讲课总结:朴素贝叶斯与模型评估
课程:COMP5318/COMP4318 — Machine Learning and Data Mining,Semester 2 2026 讲师:Imdad Ullah(幻灯片由 Irena Koprinska 准备) 参考:1)Witten ch.4.2、Tan ch.5.3;2)Witten ch.5: 161–172、Tan ch.4.5、Müller & Guido ch.5
本讲两个独立的部分: 前半 = 朴素贝叶斯(一个具体算法);后半 = 模型评估(与今天的算法无关,适用于至今学过的所有 ML 方法)。
第一部分:朴素贝叶斯
一、概率分类器与贝叶斯定理
概率分类器在做什么
回答的问题:「这个数据点属于某个类别的概率是多少?」
垃圾邮件例子:
0.85 更大 ⇒ 判为 Spam。
💡 老师提到的实际好处:正因为输出的是概率而非硬判定,邮箱才能把「疑似垃圾」放进垃圾箱但仍让你翻看并手动恢复。
贝叶斯定理与四个概率
花朵例子:特征 color ∈ {red, yellow}、stem ∈ {long, short};证据 E = 红色且长茎,假设 H = 这是一朵玫瑰。
| 项 | 名称 | 含义 | 例子 |
|---|---|---|---|
| 后验概率(posteriori) = 条件概率 |
看到证据之后,假设成立的概率 | 已知它红且长,它是玫瑰的概率 | |
| 先验概率(prior of H) | 没看证据时该事件的概率,与 E 无关 | 100 朵花里 30 朵玫瑰 → |
|
| 似然(likelihood) | 已知是玫瑰,它红且长的概率 | — | |
| 先验概率(prior of E) | 任一朵花红且长的概率,与 H 无关 | — |
我们真正想算的是
,而 、 都从训练数据里数出来。
二、朴素贝叶斯的两条假设
| # | 假设 | 内容 |
|---|---|---|
| 1 | 条件独立(Independence) | 给定类别时,各特征之间条件独立 |
| 2 | 特征重要性(Feature importance) | 所有属性(按比例)同等重要 |
这两条假设几乎从来不成立——这正是它叫「Naive(朴素)」的原因。 但它们让算法变得简单、易实现,而且实践中效果好得出奇。
课堂关键问答:假设错的,为什么还好用?
学生问:假设都不成立,为什么实践中效果这么好?
老师的回答:恰恰是因为独立性假设。 设想证据 E =(sunny, cool, high, true)。如果整体地去数「同时满足这四个条件」的训练样本,很可能一条都没有 ⇒
。 拆成单个特征后,每个特征各自都有足够的样本可数,概率就不会整体塌成 0。 换句话说:独立性假设换来的是「可估计性」。(学生追问「可它们本来就不独立啊」——老师承认,但朴素贝叶斯就是按独立来算的。)
核心目标
不必算出精确的概率,只需知道:哪个类别的概率最大。
三、完整算例:天气数据(Weather Data)
训练数据(14 条)
| # | outlook | temp | humidity | windy | play |
|---|---|---|---|---|---|
| 1 | sunny | hot | high | false | no |
| 2 | sunny | hot | high | true | no |
| 3 | overcast | hot | high | false | yes |
| 4 | rainy | mild | high | false | yes |
| 5 | rainy | cool | normal | false | yes |
| 6 | rainy | cool | normal | true | no |
| 7 | overcast | cool | normal | true | yes |
| 8 | sunny | mild | high | false | no |
| 9 | sunny | cool | normal | false | yes |
| 10 | rainy | mild | normal | false | yes |
| 11 | sunny | mild | normal | true | yes |
| 12 | overcast | mild | high | true | yes |
| 13 | overcast | hot | normal | false | yes |
| 14 | rainy | mild | high | true | no |
共 14 条:yes = 9,no = 5。
新样本 E =(sunny, cool, high, true),预测 play = ?
第 1 步:拆分证据
由条件独立假设:
第 2 步:为什么可以扔掉
两式分母都是同一个
老师还补了一条理由:如果真去算
,很可能得到 0,那就变成除以 0 了。
第 3 步:从训练数据数概率
class = yes(共 9 条):
| 概率 | 计数 | 值 |
|---|---|---|
| 第 9、11 条 | 2/9 | |
| 第 5、7、9 条 | 3/9 | |
| 第 3、4、12 条 | 3/9 | |
| 第 7、11、12 条 | 3/9 | |
| 只看 play 列 | 9/14 |
class = no(共 5 条):
| 概率 | 值 |
|---|---|
| 3/5 | |
| 1/5 | |
| 4/5 | |
| 3/5 | |
| 5/14 |
第 4 步:比较
💡 若归一化(
): , 。
四、零频问题(Zero-Frequency Problem)
问题
如果某个属性值从未与某个类别一起出现,比如训练数据中
outlook=sunny 从未与 play=yes
同现:
无论其他概率多高,整个乘积被一个 0 归零。 后果:所有 sunny 的新样本都会被判成 no,其他属性的值被完全无视。
解决:Laplace 修正(平滑)
其中
例:outlook 有 sunny / overcast / rainy 三个取值 ⇒
保证概率永远不为 0。 其推广形式称为 m-estimate。
五、缺失值处理
朴素贝叶斯处理缺失值非常自然。
| 阶段 | 做法 |
|---|---|
| 分类时(新样本有缺失) | 直接不包含该属性 |
| 训练时 | 计数时跳过缺失值,按该属性实际有值的样本数算概率 |
例:E =(outlook=?, cool, high, true)
outlook 项被整个略去,结论仍为 play = no。
⚠️ 老师提醒:如果缺失值太多,就该退回去做数据清洗 / 特征工程,而不是一味地略过。
六、Tutorial 4 Ex.1:贷款违约(名义属性)
| # | home owner | marital status | income | loan default |
|---|---|---|---|---|
| 1 | yes | single | very high | yes |
| 2 | no | married | high | yes |
| 3 | no | single | medium | no |
| 4 | yes | married | very high | no |
| 5 | yes | divorced | high | yes |
| 6 | no | married | low | no |
| 7 | yes | divorced | very high | no |
| 8 | no | single | high | yes |
| 9 | no | married | medium | no |
| 10 | no | single | low | yes |
新样本:home owner = no,marital status = married,income = very high
yes 共 5 条,no 共 5 条 ⇒
| 概率 | yes | no |
|---|---|---|
| 3/5 | 3/5 | |
| 1/5 | 3/5 | |
| 1/5 | 2/5 |
⇒ 预测 loan default = no。
七、数值属性:高斯朴素贝叶斯
为什么不能直接数频率
若温度 = 66,你无法问「训练集里出现过多少次 66」——连续值在 60 到 60.01 之间就有无穷多个取值,精确匹配几乎必然是 0 次。
解决:假设服从正态分布,用概率密度函数
做法:对每个「数值属性 ×
类别」的组合,分别算出
⚠️ 重要澄清:概率密度函数的值不完全等于概率,但密切相关——用于比较大小足够了。
老师给的最好的直觉: 高斯朴素贝叶斯问的不是「我见过多少次恰好 66」,而是「66 离这个类别的典型温度有多近」。
| 特征类型 | 概率来源 |
|---|---|
| 名义(categorical) | 频率 / 计数 |
| 数值(numeric) | 高斯密度 |
算例:天气数据数值版
新样本:outlook = sunny,temperature = 66,humidity = 90,windy = true
| 密度 | 参数 | 值 |
|---|---|---|
| 0.0340 | ||
| 0.0221 | ||
| 0.0279 | ||
| 0.0380 |
⇒ 预测 play = no。(名义属性用分数,数值属性用密度,两者直接相乘。)
Tutorial 4 Ex.2:贷款违约(income 改为数值)
income 数据(单位 K):yes = {125, 100, 95, 85, 90};no = {70, 120, 60, 220, 75}
第 1 步:分类别算
| 类别 | ||
|---|---|---|
| yes | 99 | 15.57 |
| no | 109 | 66.18 |
注意 no 类的
极大(66.18),因为里面有个 220 的极端值——分布被拉得很平很宽。
第 2 步:算密度(income = 120)
第 3 步:代入(名义属性的概率沿用 Ex.1)
⇒ 预测 loan default = no。
八、朴素贝叶斯:优缺点讨论
✅ 优点
- 概率计算简单——独立性假设让一切变成单变量计数
- 快:只需扫描一遍训练数据就能算出全部统计量(名义与连续属性都是)
- 常常胜过更复杂的方法
- 对孤立噪声点稳健——孤立点对条件概率的影响微乎其微
⚠️ 缺点与对策
| 缺点 | 对策 |
|---|---|
| 相关属性削弱其能力(违背独立性假设) | 事先做特征选择,剔除相关(冗余)属性 |
| 数值属性的正态分布假设——很多特征并非正态 | ① 先离散化(数值 →
名义) ② 换其他密度函数:Poisson、binomial、gamma |
第二部分:模型评估
老师明确说:这部分和朴素贝叶斯无关,适用于目前学过的所有机器学习算法。
两个层面: - 评估流程(procedure) → 你对整套做法有多大信心 - 性能度量(measure) → 模型有多好
九、评估流程
1. Holdout 方法
随机把数据分成训练集和测试集,通常 2/3 和 1/3。训练集建模,测试集评估。
训练集准确率过于乐观,不是泛化性能的好指标;测试集准确率才用来评估泛化性能。
2. 验证集与超参数
| 集合 | 用途 |
|---|---|
| Training set | 建分类器 |
| Validation set | 调超参数 |
| Test set | 评估准确率 |
测试数据不能用于超参数调优——否则测出的准确率就不诚实了。
参数 vs 超参数:
| 定义 | 例子 | |
|---|---|---|
| 参数(parameter) | 模型的一部分,由算法从数据中学出来 | 线性回归的 |
| 超参数(hyperparameter) | 由我们选择/调优,模型不会从数据中学到它 | kNN 的 |
💡 实践中大家常笼统地说 "parameter tuning",虽然严格讲应该叫 hyperparameter tuning。
3. 分层抽样(Stratification)
问题:随机划分可能导致某些类别在训练集或测试集中缺失或严重欠代表。
解决:分层——保证每个类别在训练集和测试集中的比例与全集大致相同。
例:100 条数据,Class 1 占 60、Class 2 占 40,按 70/30 划分。
| 方式 | 训练集 | 测试集 |
|---|---|---|
| 随机(可能出现) | 50 / 20 | 10 / 20 ← 比例严重失真 |
| 分层 | 42 / 28(70×0.6, 70×0.4) | 18 / 12(30×0.6, 30×0.4) |
为什么这很要命(老师的医疗例子):95 个健康病人 + 5 个患病病人。 纯随机划分可能把 5 个患病样本全分到测试集 ⇒ 分类器根本没学过「患病」这个类别 ⇒ 面对患病病人却判为健康 ⇒ 给出完全错误的治疗建议或干脆不治疗。
4. 重复 Holdout(Repeated Holdout)
重复 10 次随机划分(每次可结合分层),取 10 次准确率的平均。
必须同时报告标准差: 均值 → 平均表现有多好;标准差 → 表现有多稳定。
课堂题:79% ± 0.8% 和 79% ± 11% 哪个更好? 前者——后者可能这次 99%、下次 60%,平均一样但完全不可靠。
⚠️ 老师的提醒:标准差小也不代表就万事大吉——有可能是碰巧。要多看几个指标。
局限:各次的测试集会重叠(Run 1 测 {1,2,3},Run 2 测 {2,4,5},Run 3 测 {1,4,6} —— 1、2、4 重复出现)。
5. 十折交叉验证(10-fold Cross-Validation)
| 步骤 | 内容 |
|---|---|
| 1 | 把数据分成 10 个大小近似相等的子集 |
| 2 | 建 10 次分类器:每次用 1 个子集测试、其余 9 个合起来训练 |
| 3 | 交叉验证准确率 = 10 次准确率的平均 |
核心优势:避免了测试集重叠——每个样本恰好被测试一次。
为什么是 10? 大量实验表明 10 是获得准确估计的最佳选择,也有一定的理论依据。
业界标准做法 = 分层十折交叉验证(Stratified 10-fold CV)。
更好:重复的分层十折交叉验证 —— 十折做 10 遍 = 100 次评估,取平均,降低数据划分带来的方差。
6. 留一法(Leave-One-Out CV)
n 折交叉验证的特例:折数 = 训练样本数。n 个样本就建 n 次分类器,每次留 1 个做测试。
| 内容 | |
|---|---|
| ✅ 优点 1 | 最充分利用数据——每次训练用的数据量最大,小数据集的最佳选择 |
| ✅ 优点 2 | 确定性过程——不涉及随机抽样,每次跑结果完全相同 |
| ⚠️ 缺点 | 计算代价极高——n = 100,000 时要建 10 万个模型 |
7. 网格搜索调参(Grid Search with CV)
以 kNN 为例,调两个超参数:
∈ {1, 3, 5, 11, 13} —— 5 个取值 - 距离度量 ∈ {Manhattan, Euclidean} —— 2 个取值
共 5 × 2 = 10 种组合。
流程:
建立参数网格(所有参数组合) |
PPT 给出的结果表(示例):
| 距离 | CV 准确率 | |
|---|---|---|
| 1 | Euclidean | 82% |
| 1 | Manhattan | 84% |
| 3 | Euclidean | 87% |
| 3 | Manhattan | 86% |
| 5 | Euclidean | 90% |
| 5 | Manhattan | 88% |
| 11 | Euclidean | 85% |
| 11 | Manhattan | 86% |
| 13 | Euclidean | 83% |
| 13 | Manhattan | 82% |
选
三个必须记牢的要点: 1. 交叉验证循环只在训练数据上跑,测试集全程不参与调参 2. 每个参数组合都要建 10 个模型(90% 训练 / 10% 验证)⇒ 10 组 × 10 折 = 100 次训练 3. 选出最优参数后,要用整个训练集重新训练一个新模型,再在测试集上评估
sklearn 里用
GridSearchCV。
💡 老师课上提的一个很好的现实问题:现在
最好,但明年数据变了呢? 用 2021–2026 的数据预测悉尼房价,到了 2027 政府政策变了、出现了新的特征, 可能就不再最优。 答案:必须用新观测重新训练。「维护」是真实部署中的一大挑战——有时甚至要靠合成数据。
十、性能度量
混淆矩阵(Confusion Matrix)
| 实际 预测 | 预测为 yes | 预测为 no |
|---|---|---|
| 实际 yes | TP(true positive) | FN(false negative) |
| 实际 no | FP(false positive) | TN(true negative) |
混淆矩阵本身不是性能度量——它是用来计算各种性能度量的。
算例:100 个测试样本,TP = 30,FN = 10,FP = 5,TN = 55
多分类(iris 数据):
a b c <-- classified as |
对角线是正确预测。
Precision、Recall、F1
💡 用上面的算例代入(PPT 只给了公式):
, , 。
老师的指纹门禁例子(理解 FP 与 FN 的代价)
| 情形 | 含义 | 后果 |
|---|---|---|
| False Negative | 我是合法用户,系统却拒绝我 | 手指有伤口 / 潮湿 → 进不了门 |
| False Positive | 非法用户却被放行 | 安全事故 |
核心洞见:你不能只看总体准确率。 - 讲堂门禁 → 5%~10% 的错误可以接受 - 高安全区域 → 绝不能有 FP
必须在两类错误之间找一个平衡点,而这个平衡点是靠混淆矩阵来定的。
💡 老师顺带解释了为什么手机人脸解锁有时认不出你——那正是 false negative。
十一、考点重点
朴素贝叶斯
- 贝叶斯定理及四个概率的名称与含义:后验
、先验 、似然 、 。 - 两条假设:条件独立 + 特征同等重要;都不现实 → 所以叫 Naive;但正因独立假设才避免了概率整体归零。
- 完整算例要会手算:拆证据 → 数条件概率 → 乘上先验 →
约掉
→ 比大小。天气例子 0.0053 vs 0.0206 ⇒ no。 - 为什么能扔掉
:两个类别的分母相同,只比较大小。 - 零频问题 + Laplace 修正
, = 该属性的取值个数。 - 缺失值:分类时直接略过该属性;训练时计数跳过缺失值。
- 高斯朴素贝叶斯:数值属性假设正态,用
PDF;每个「属性×类别」组合分别算
、 ;密度不等于概率但密切相关。 - 优缺点:快(一遍扫描)、抗孤立噪声;怕相关属性(→ 先做特征选择)、怕非正态(→ 离散化或换分布)。
模型评估
- Holdout:通常 2/3 训练、1/3 测试;训练集准确率过于乐观。
- 参数 vs 超参数:
是参数(学出来的); 、隐藏层数是超参数(调出来的)。 - 分层(stratification):保持类别比例;罕见类可能被随机划分整个丢掉。会算 42/28、18/12。
- 重复 holdout:报均值和标准差;79% ± 0.8% 优于 79% ± 11%;缺点是测试集重叠。
- 十折交叉验证:10 等份、建 10 次、平均;避免测试集重叠;为什么是 10 —— 实验证明最佳。标准做法是分层十折,更好的是重复分层十折(100 次评估)。
- 留一法:折数 = 样本数;优点是数据利用最充分 + 确定性(无随机);缺点是计算代价极高;适合小数据集。
- 网格搜索:5×2 = 10 组;CV 只在训练集上做;选出最优参数后要在整个训练集上重新训练;10 组 × 10 折 = 100 次训练。
- 混淆矩阵 TP/FN/FP/TN、accuracy =
(tp+tn)/总数、
、 、 。会算 85%、94%。 - 混淆矩阵不是性能度量,而是计算性能度量的工具。
- FP 与 FN 的代价不对称——只看准确率是不够的(指纹门禁例子)。
十二、本讲与前后的衔接
| Week | 内容 | 关键词 |
|---|---|---|
| 2 | 数据预处理、kNN | 相似度、特征选择 |
| 3 | 线性/逻辑回归、正则化 | 最小二乘、最大似然、过拟合 |
| 4 | 朴素贝叶斯 + 模型评估 | 概率分类、交叉验证、混淆矩阵 |
两处与 Week 3 的呼应: 1. 过拟合是通用概念——有同学问「回归里讲的过拟合在分类里一样吗」,老师答:完全一样,看训练与测试准确率的差距,这适用于所有机器学习方法。 2. 验证集的作用在两周里是一致的:Week 3 用它调正则化强度
,Week 4 用它调 kNN 的 —— 都是超参数调优,都不能碰测试集。