1404 综合练习
Part A:给定数据集的精讲精练(共 6 题)
练习 1:“天气预测 —— 贝叶斯定理手算与代码验证”
🎯 目标:通过手算 + 代码验证,深刻理解贝叶斯定理的每个组成部分。 📂 数据集:给定下面的“天气与打球”数据表(10 条记录)
【数据表】 :某同学记录了过去 10 天的天气情况和是否去打球的决策。
| 日期 | 天气(Outlook) | 温度(Temp) | 是否打球(Play) |
|---|---|---|---|
| D1 | 晴天(Sunny) | 热(Hot) | 否(No) |
| D2 | 晴天(Sunny) | 热(Hot) | 否(No) |
| D3 | 阴天(Overcast) | 热(Hot) | 是(Yes) |
| D4 | 雨天(Rainy) | 温和(Mild) | 是(Yes) |
| D5 | 雨天(Rainy) | 凉爽(Cool) | 是(Yes) |
| D6 | 雨天(Rainy) | 凉爽(Cool) | 否(No) |
| D7 | 阴天(Overcast) | 凉爽(Cool) | 是(Yes) |
| D8 | 晴天(Sunny) | 温和(Mild) | 否(No) |
| D9 | 晴天(Sunny) | 凉爽(Cool) | 是(Yes) |
| D10 | 雨天(Rainy) | 温和(Mild) | 是(Yes) |
【详细操作步骤(Step-by-Step)】 :
第 1 步:统计先验概率
先填写以下计数:
| 类别 | 计数 | 概率 P(类别) |
|---|---|---|
| Play = Yes | ____ 天 | ____ / 10 = ____ |
| Play = No | ____ 天 | ____ / 10 = ____ |
第 2 步:统计条件概率(似然)
在“打球=是”的条件下,各种天气出现的次数和概率:
| 天气 | Yes 组中计数 | P(天气 | Yes) | | :— | :— | :— | | Sunny | ____ | ____ / ____ = ____ | | Overcast | ____ | ____ / ____ = ____ | | Rainy | ____ | ____ / ____ = ____ |
在“打球=否”的条件下,各种天气出现的次数和概率:
| 天气 | No 组中计数 | P(天气 | No) | | :— | :— | :— | | Sunny | ____ | ____ / ____ = ____ | | Overcast | ____ | ____ / ____ = ____ | | Rainy | ____ | ____ / ____ = ____ |
第 3 步:计算证据因子 P(天气=Sunny)
$$P(\text{Sunny}) = P(\text{Sunny}|\text{Yes}) \times P(\text{Yes}) + P(\text{Sunny}|\text{No}) \times P(\text{No}) = \_\_\_\_ $$第 4 步:使用贝叶斯定理计算后验概率
当天气为 Sunny 时,打球的概率:
$$P(\text{Yes}|\text{Sunny}) = \frac{P(\text{Sunny}|\text{Yes}) \times P(\text{Yes})}{P(\text{Sunny})} = \frac{\_\_\_\_ \times \_\_\_\_}{\_\_\_\_} = \_\_\_\_$$当天气为 Sunny 时,不打球的概率:
$$P(\text{No}|\text{Sunny}) = \frac{P(\text{Sunny}|\text{No}) \times P(\text{No})}{P(\text{Sunny})} = \frac{\_\_\_\_ \times \_\_\_\_}{\_\_\_\_} = \_\_\_\_$$第 5 步:做出决策
当天气为 Sunny 时,P(Yes|Sunny) = ____,P(No|Sunny) = ____。
因为 ____ > ,所以预测为:****(打球/不打球)。
第 6 步:代码验证
代码输出的结果是否与你手算的一致?______(填“是”或“否”,如有差异请说明原因)
练习 2:“先验敏感性分析 —— 当先验概率发生变化”
🎯 目标:理解先验概率对后验概率的影响程度,培养“先验选择需谨慎”的工程意识。 📂 数据集:沿用练习 1 的“天气与打球”数据。
【详细操作步骤(Step-by-Step)】 :
第 1 步:回顾练习 1 中计算出的条件概率
从练习 1 中抄录以下数值:
- P(Sunny | Yes) = ____
- P(Sunny | No) = ____
- P(Yes) = ____(原始先验)
- P(No) = ____(原始先验)
第 2 步:改变先验概率 —— 场景 A(极端乐观)
假设这位同学是个“球痴”,无论天气如何都倾向于打球。设定先验为:
- P(Yes) = 0.9
- P(No) = 0.1
重新计算:
- P(Sunny) = P(Sunny|Yes) × 0.9 + P(Sunny|No) × 0.1 = ____
- P(Yes|Sunny) = P(Sunny|Yes) × 0.9 / P(Sunny) = ____
- P(No|Sunny) = P(Sunny|No) × 0.1 / P(Sunny) = ____
此时,晴天时预测为:____(打球/不打球)
第 3 步:改变先验概率 —— 场景 B(极端悲观)
假设这位同学是个“宅男”,无论如何都不想出门。设定先验为:
- P(Yes) = 0.1
- P(No) = 0.9
重新计算:
- P(Sunny) = P(Sunny|Yes) × 0.1 + P(Sunny|No) × 0.9 = ____
- P(Yes|Sunny) = P(Sunny|Yes) × 0.1 / P(Sunny) = ____
- P(No|Sunny) = P(Sunny|No) × 0.9 / P(Sunny) = ____
此时,晴天时预测为:____(打球/不打球)
第 4 步:填写对比表格
| 先验设置 | P(Yes) | P(No) | P(Yes|Sunny) | P(No|Sunny) | 预测结果 | | :— | :— | :— | :— | :— | :— | | 原始(数据统计) | 0.5 | 0.5 | ____ | ____ | ____ | | 场景 A(乐观) | 0.9 | 0.1 | ____ | ____ | ____ | | 场景 B(悲观) | 0.1 | 0.9 | ____ | ____ | ____ |
第 5 步:回答以下问题
- 在场景 A 中,即使 P(Sunny|Yes) 较低,后验 P(Yes|Sunny) 仍然很高。这说明了什么?
- 如果这是一个实际项目,先验概率应该从哪里获取?
- 当先验数据不足时,通常假设 P(类别) 相等(均匀先验)。这种做法的潜在风险是什么?
练习 3:“从零构建词袋模型 —— 手动分词与向量化”
🎯 目标:通过手动操作,彻底理解“文本 → 词频向量”的完整过程。 📂 数据集:以下 4 条短文本(关于“体育”和“科技”两类)
| 文档编号 | 文本内容 | 类别 |
|---|---|---|
| D1 | 足球比赛精彩绝伦 | 体育 |
| D2 | 篮球巨星夺得冠军 | 体育 |
| D3 | 人工智能改变世界 | 科技 |
| D4 | 程序员编写代码 | 科技 |
【详细操作步骤(Step-by-Step)】 :
第 1 步:中文分词
使用 jieba 对每条文本进行分词(也可手动切分),将结果填写在下表中。
| 文档 | 分词结果(用空格分隔) |
|---|---|
| D1 | ______ |
| D2 | ______ |
| D3 | ______ |
| D4 | ______ |
第 2 步:构建词典
汇总所有文档中出现的不重复词语,建立词典并编号。
| 编号 | 词语 |
|---|---|
| 1 | ______ |
| 2 | ______ |
| 3 | ______ |
| 4 | ______ |
| 5 | ______ |
| 6 | ______ |
| 7 | ______ |
| 8 | ______ |
词典大小 V = ______(共 ____ 个词)
第 3 步:生成词频向量(Count Vector)
对每个文档,统计词典中每个词在该文档中出现的次数,填入下表。
| 文档 | 词1 | 词2 | 词3 | 词4 | 词5 | 词6 | 词7 | 词8 |
|---|---|---|---|---|---|---|---|---|
| D1 | ____ | ____ | ____ | ____ | ____ | ____ | ____ | ____ |
| D2 | ____ | ____ | ____ | ____ | ____ | ____ | ____ | ____ |
| D3 | ____ | ____ | ____ | ____ | ____ | ____ | ____ | ____ |
| D4 | ____ | ____ | ____ | ____ | ____ | ____ | ____ | ____ |
第 4 步:生成 One-Hot 向量(二值向量)
将上表中的所有非零值改为 1,得到 One-Hot 向量。
| 文档 | 词1 | 词2 | 词3 | 词4 | 词5 | 词6 | 词7 | 词8 |
|---|---|---|---|---|---|---|---|---|
| D1 | ____ | ____ | ____ | ____ | ____ | ____ | ____ | ____ |
| D2 | ____ | ____ | ____ | ____ | ____ | ____ | ____ | ____ |
| D3 | ____ | ____ | ____ | ____ | ____ | ____ | ____ | ____ |
| D4 | ____ | ____ | ____ | ____ | ____ | ____ | ____ | ____ |
第 5 步:代码验证
代码输出的词典和矩阵是否与你手动构建的一致?如有差异,请分析原因(可能是 jieba 的分词结果与你的手动分词不同)。
练习 4:【独立实战】“垃圾短信分类 —— 完整项目流程”
🎯 目标:使用真实(或模拟)的短信数据,完成从数据加载到模型评估的完整项目。 📂 数据集:使用
sklearn内置的fetch_20newsgroups的子集,或自行构造短信数据。
任务要求:
-
准备数据:自行构造或从网络收集 50 条短信(25 条垃圾,25 条正常),保存为 CSV 格式(两列:
text,label)。 -
完整代码实现:
- 使用
pandas读取数据。 - 使用
jieba进行中文分词。 - 使用
CountVectorizer进行向量化(设置max_features=500限制特征数)。 - 使用
train_test_split划分训练集和测试集(test_size=0.2)。 - 使用
MultinomialNB训练模型。 - 输出测试集准确率和分类报告。
- 使用
-
测试与展示:
- 输入 5 条新短信(自己编写),展示预测结果和各类别概率。
- 从测试集中找出 2 条被分错的样本,分析可能的原因。
-
提交物:
- 完整代码(
.ipynb或.py)。 - CSV 数据文件。
- 运行结果截图。
- 完整代码(
练习 5:【独立实战】“CountVectorizer vs TfidfVectorizer —— 谁是文本分类的更好选择?”
🎯 目标:通过控制变量实验,对比两种向量化方法在文本分类任务中的表现差异。 📂 数据集:练习 4 中构造的短信数据集。
任务要求:
-
实验设计:
- 使用完全相同的数据划分(固定
random_state=42)。 - 使用完全相同的模型(
MultinomialNB(alpha=1.0))。 - 唯一变量:向量化方法(
CountVectorizervsTfidfVectorizer)。
- 使用完全相同的数据划分(固定
-
执行实验:
-
输出对比表格:
| 向量化方法 | 特征数 | 训练集准确率 | 测试集准确率 |
|---|---|---|---|
| CountVectorizer | ____ | ____ | ____ |
| TfidfVectorizer | ____ | ____ | ____ |
- 分析报告(100 字以内):
- 哪种方法在你的数据集上表现更好?
- 分析可能的原因(提示:数据集中是否存在大量停用词/通用词?)
练习 6:【独立实战】“超参数探索 —— alpha 值对模型性能的影响”
🎯 目标:理解拉普拉斯平滑参数 α(alpha)的作用,并通过实验找到最佳取值。 📂 数据集:自行选择(建议使用练习 4 的短信数据集或 sklearn 内置的
fetch_20newsgroups)
任务要求:
-
背景知识:
MultinomialNB(alpha=α)中的alpha是拉普拉斯平滑参数。alpha=0:无平滑,未见过的词会导致概率为 0。alpha=1:标准拉普拉斯平滑(默认值)。alpha>1:更强的平滑,概率分布更均匀。alpha<1:较弱的平滑,更依赖训练数据中的频率。
-
实验设计:
- 固定向量化方法(建议使用
TfidfVectorizer)。 - 在
alpha = [0, 0.01, 0.1, 0.5, 1.0, 2.0, 5.0, 10.0]范围内进行实验。 - 记录每个 alpha 值对应的测试集准确率。
- 固定向量化方法(建议使用
-
绘制曲线:
- 横轴:
alpha值(使用对数刻度,因为 alpha 跨度大)。 - 纵轴:测试集准确率。
- 标注出最佳 alpha 值。
- 横轴:
-
分析:
alpha=0时是否出现错误(提示:某些测试词的 P=0)?- 在当前数据集上,推荐的 alpha 值是多少?
- 如果你有 100 万条训练数据,你认为 alpha 应该调大还是调小?为什么?
Part B:不给定数据集的开放设计挑战(共 3 题)
练习 7:【造数据挑战】“美食评论情感分类 —— 自建数据集与模型训练”
背景:某餐饮平台想要自动识别用户评论的情感倾向(好评/差评),以便快速了解客户满意度。你需要自建数据集并训练朴素贝叶斯分类器。
任务要求:
-
自行构造数据:
- 编写 30 条关于餐厅/美食的中文评论。
- 其中 15 条为好评(如“味道很棒”、“服务热情”、“环境优雅”等)。
- 其中 15 条为差评(如“太难吃了”、“价格太贵”、“上菜太慢”等)。
- 将数据保存为 CSV 格式(列:
text,label)。
-
模型训练:
- 使用
jieba分词。 - 使用
TfidfVectorizer向量化。 - 使用
MultinomialNB训练模型。 - 划分训练集(70%)和测试集(30%)。
- 使用
-
模型评估:
- 输出测试集准确率。
- 输出分类报告(精确率、召回率、F1 分数)。
-
测试新评论:
- 编写 3 条新的评论(1 条明显好评、1 条明显差评、1 条中性/模糊)。
- 展示模型对每条评论的预测结果和概率。
-
错误分析:
- 找出至少 1 条被错分的评论。
- 分析错分原因(如:用词模糊、训练数据不足、特征选择不当等)。
练习 8:【造数据挑战】“多分类新闻标题分类器”
背景:某新闻聚合 App 需要将新闻标题自动归类为:体育、科技、财经、娱乐 四个类别之一。
任务要求:
-
自行构造数据:
- 每个类别至少编写 10 条新闻标题(共 ≥ 40 条)。
- 数据保存为 CSV(列:
title,category)。
-
模型训练(完整流程):
- 中文分词(
jieba)。 - 向量化(从
CountVectorizer和TfidfVectorizer中选择一个,并说明理由)。 - 训练
MultinomialNB。 - 评估模型(准确率 + 分类报告)。
- 中文分词(
-
多分类概率分析:
- 选一条测试标题,输出它在 4 个类别上的完整概率分布(
predict_proba)。 - 用柱状图可视化这个概率分布。
- 如果最高概率与第二高概率的差值很小(如 0.35 vs 0.32),说明什么问题?
- 选一条测试标题,输出它在 4 个类别上的完整概率分布(
-
数据量实验:
- 仅使用每类 5 条数据训练一个模型(使用
random_state=42随机抽取子集)。 - 使用完整数据训练另一个模型。
- 对比两个模型的准确率,讨论数据量对朴素贝叶斯的影响。
- 仅使用每类 5 条数据训练一个模型(使用
练习 9:【综合设计挑战】“甲方需求 —— 工单自动分派系统”
背景:某 IT 服务公司每天收到大量客户报修/咨询工单。需要开发一个自动分类系统,将工单分派给对应的处理部门(3 个部门:硬件维修、软件支持、网络运维)。
【甲方需求书】
| 项目 | 内容 |
|---|---|
| 数据情况 | 公司提供 200 条已标注的历史工单,但数据格式不规范,部分工单的标题和描述混在一起。 |
| 类别 | 3 类:硬件维修(如“电脑无法开机”、“打印机卡纸”)、软件支持(如“Excel 崩溃”、“系统蓝屏”)、网络运维(如“无法上网”、“VPN 连不上”)。 |
| 硬性要求 | ① 分类准确率 ≥ 85%;② 必须能输出“置信度”(即各类别概率),方便人工复核;③ 模型需要在 0.5 秒内完成单条工单分类。 |
| 软性要求 | 最好能分析出每个类别中最具有区分度的 Top 5 关键词,供业务方参考。 |
任务要求:
-
自行生成数据:
- 模拟 200 条工单数据(可以重复使用一些模板,但要保证每个类别至少 50 条)。
- 可以适当加入一些“边界案例”(如描述模糊的工单),增加分类难度。
-
模型选型论证:
- 从以下模型中选择最合适的一个:
MultinomialNB、GaussianNB、BernoulliNB。 - 说明为什么选它,为什么放弃另外两个(从特征类型角度分析:文本词频属于离散计数数据,适用 MultinomialNB)。
- 从以下模型中选择最合适的一个:
-
完整实现:
- 数据加载与预处理(文本清洗、分词、去停用词)。
- 向量化(
TfidfVectorizer或CountVectorizer)。 - 模型训练与评估。
- 输出准确率和各类别的精确率/召回率。
-
交付物:
- 模型文件:保存训练好的模型和向量化器(使用
joblib.dump)。 - 分类函数:封装一个
predict_ticket(text)函数,输入工单文本,输出“类别 + 各类别概率”。 - 特征分析:使用
model.feature_log_prob_提取每个类别中概率最高的 Top 5 关键词,输出到表格中。 - 速度测试:测量单条文本的预测耗时,确认 < 0.5 秒。
- 模型文件:保存训练好的模型和向量化器(使用
-
扩展挑战(加分项) :
- 尝试使用
Pipeline将“向量化 + 模型”封装为一个整体流程。 - 使用
GridSearchCV对alpha进行调优,并比较调优前后的准确率变化。
- 尝试使用
📌 使用指南
| 练习题 | 难度 | 建议课时 | 对应教案 | 带步骤 |
|---|---|---|---|---|
| 练习 1 | ★☆☆ | 0.5 课时 | 第一次课(14.1) | ✅ 是 |
| 练习 2 | ★★☆ | 0.5 课时 | 第二次课(14.2.1) | ✅ 是 |
| 练习 3 | ★★☆ | 0.5 课时 | 第二次课(14.2.2) | ✅ 是 |
| 练习 4 | ★★☆ | 1 课时 | 第三次课(14.3) | ❌ 否 |
| 练习 5 | ★★☆ | 1 课时 | 第三次课(14.3) | ❌ 否 |
| 练习 6 | ★★★ | 1 课时 | 第三次课(14.3) | ❌ 否 |
| 练习 7 | ★★☆ | 1 课时 | 综合(14.2-14.3) | ❌ 否 |
| 练习 8 | ★★★ | 1.5 课时 | 综合(全章) | ❌ 否 |
| 练习 9 | ★★★★ | 2 课时 | 综合(全章 + 工程化) | ❌ 否 |
建议:
- 练习 1-3 作为 课后作业 布置(每次课后布置 1 题),巩固基础概念。
- 练习 4-6 作为 实训课任务,让学生独立完成代码实现。
- 练习 7-8 作为 小组项目(2 人一组),培养协作能力。
- 练习 9 作为 期末大作业/机考题目,综合考察全章知识 + 工程化能力。
- 练习 1-3:重点检查手算结果是否正确,公式是否用对。
- 练习 4-6:重点检查代码是否可运行,是否记录了实验数据并做出了分析。
- 练习 7-8:重点检查数据构造是否合理、选型论证是否充分。
- 练习 9:重点检查是否满足了甲方所有需求(准确率 ≥ 85%、速度 < 0.5s、概率输出、特征分析)。