☰
AI-For-Beginners 第 13 课实战任务:用自定义数据集重跑文本表示 Notebook(BoW、N-Gram 与 TF-IDF)
2026/10/3 13:40:26 网站建设 项目流程
  • 教程
  • 人工智能
  • 机器学习
  • 深度学习

【免费下载链接】AI-For-Beginners

12 Weeks, 24 Lessons, AI for All!

项目地址:https://gitcode.com/GitHub_Trending/ai/AI-For-Beginners
点击查看免费下载

本指南围绕 AI-For-Beginners 第 5 单元第 13 课(NLP 文本表示)的课程作业展开,讲解如何把仓库内两套文本表示 Notebook(PyTorch 版与 TensorFlow 版)从 AG News 基准数据集迁移到你自己选择的数据集上重新运行,并说明在改写过程中如何记录与突出个人发现、如何遵守数据集来源标注要求。读完本指南,你将掌握"文本分类 + 词袋(BoW)/ N-Gram / TF-IDF 向量化"这一整套可迁移的动手流程,并能独立完成从数据加载、向量化到分类器训练与结果解读的闭环实验。

任务速览:这份 Assignment 到底要求什么

课程作业原文位于 作业文档,其核心要求可以拆解为四步:

  1. 选取 Notebook:使用本课附带的 PyTorch 版 Notebook 或 TensorFlow 版 Notebook(任选其一即可);
  2. 换数据重跑:用自己的数据集重新运行该 Notebook。数据可以来自 Kaggle 等公开平台,但必须注明出处(attribution);
  3. 改写以突出发现:不要只是机械地跑通,而是改造 Notebook 使其突出你自己的分析结论与观察;
  4. 尝试创新数据集:鼓励选取一些"出人意料、可能带来惊喜结论"的数据集,例如 NUFORC(美国国家不明飞行物报告中心)维护的 UFO 目击记录数据集——这类文本与常规新闻完全不同,往往能暴露文本表示方法的真实行为。

需要说明的是:本作业是 课程 README 中"🚀 Challenge"环节之后的正式实践任务,与课前/课后测验共同构成该课的完整学习闭环。作业所依赖的全部技术内容(文本分类、分词、词袋、N-Gram、TF-IDF)都沉淀在课程 README 与两套 Notebook 中,因此本文先梳理这条技术基线,再给出换数据的改造步骤。

先读懂要改造的 Notebook:文本表示的技术骨架

课程上下文:基于 AG News 的文本分类

整个第 13 课聚焦一个典型 NLP 任务——文本分类(text classification)。基线数据集为 AG News 新闻数据集,每条样本由「类别 + 标题 + 正文」组成,目标是把新闻分入 World、Sports、Business、Sci/Tech 四个类别之一。仓库内的示例样本形如:

  • 类别:Sci/Tech
  • 标题:Ky. Company Wins Grant to Study Peptides (AP)
  • 正文:AP - A company founded by a chemistry researcher at the University of Louisville won a grant to develop...

文本如何变成张量:从字符到 token 再到向量

要让神经网络处理文本,首先必须把文本表示为张量。计算机本身并不理解字母的语义——字符只是通过 ASCII/UTF-8 等编码映射为数字:

课程 README 给出了两类基础表示方案:

  • 字符级表示(character-level):把每个字符当作一个数字。若语料有C个不同字符,单词Hello将表示为一个 5×C的张量,每个字母对应 one-hot 编码中的一列;
  • 词级表示(word-level):先为语料中所有词建立词表(vocabulary),再用 one-hot 编码表示每个词。这种方式语义层次更高,但词表很大时会带来高维稀疏张量问题。

无论采用哪种表示,第一步都是把文本切分为tokens(token 可以是字符、单词,甚至词的一部分),再借助词表把 token 映射为数字,最终喂给神经网络。

N-Gram:把上下文纳入词表

单词的精确含义只能由上下文决定——neural network与fishing network含义完全不同。一种朴素做法是把词对当作独立 token:句子I like to go fishing会被切分为I like、like to、to go、go fishing。代价是词表急剧膨胀,且go fishing与go shopping虽是同一动词却毫无共享语义。这种词对、三词组合统称n-grams(bigram 为 2-gram,trigram 为 3-gram),同样也适用于字符级表示。

Bag-of-Words:固定长度向量 + 词频

做分类任务时,我们需要用一个固定长度的向量表示整段文本。最简单的方式是把所有词的 one-hot 向量直接相加——得到的就是一个词频向量,即Bag-of-Words(BoW)。BoW 记录"文本里出现了哪些词、各出现多少次",这往往已能很好指示文本主题:政治新闻常含president、country,科研文献则多collider、discovered等词。

BoW 的缺陷在于高频停用词(如and、is)会掩盖真正重要的词,这正是下一节 TF-IDF 要解决的问题。

TF-IDF:按文档频率压低常见词权重

TF-IDF(term frequency–inverse document frequency)是 BoW 的变体:不再用 0/1 或纯频数,而是用浮点权重,词i在文档j中的权重为:

$$w_{ij} = tf_{ij}\times\log({N\over df_i})$$

其中tf_ij是词i在文档j中出现的次数(即 BoW 值),N是文档总数,df_i是包含词i的文档数。权重随词在文档中出现次数增多而增大,同时被包含该词的文档数抵消——若某词出现在每一篇文档中(df_i = N),则w_ij = 0,该词被完全忽略。

无论是 BoW 还是 TF-IDF,都无法表达语义与词序。正如语言学家 J. R. Firth 在 1935 年所言:"一个词的完整含义总是语境化的,脱离语境的词义研究不足为信。"课程的后续单元(语言建模、词嵌入)将解决这一问题——这也在提醒你:作业中观察到的"BoW/TF-IDF 的上限"是方法本身的固有边界,而非你的实现缺陷。

两套 Notebook 的完整处理链路:改造的基准线

作业要求你"重跑并改写"的 Notebook,其内部处理链路值得先完整梳理,因为换数据时你改动的正是这条链路的输入环节。

PyTorch 版链路(TextRepresentationPyTorch.ipynb)

  1. 加载数据:通过torchtext.datasets.AG_NEWS(root='./data')加载数据集,训练/测试集均为迭代器,每条样本返回(label, text)元组;classes = ['World', 'Sports', 'Business', 'Sci/Tech']。由于迭代器只能消费一次,随后用list(...)固化;
  2. 分词:torchtext.data.utils.get_tokenizer('basic_english')把文本切为 token 列表(如'He said: hello'→['he', 'said', 'hello']);
  3. 建词表:用collections.Counter统计 token 频率后调用torchtext.vocab.vocab(counter, min_freq=1);AG News 全量词表约95,810个词(Notebook 输出原话为 "Vocab size if 95810")。通过vocab.get_stoi()拿到 token→索引映射,实现encode()函数把文本编码为索引序列;
  4. BoW 向量化:to_bow()对编码后的索引序列做词频累加,返回长度等于vocab_size的 float32 张量。Notebook 特别提示:调低词表大小再训练,观察准确率如何变化——预期会有一定下降但不剧烈,换取更高训练性能;
  5. 组织 batch:把bowify函数作为collate_fn传入torch.utils.data.DataLoader,其中标签统一t[0]-1(AG News 标签从 1 开始,转为 0 基),特征用torch.stack([to_bow(...)])堆叠;
  6. 定义分类器:单线性层torch.nn.Sequential(torch.nn.Linear(vocab_size,4), torch.nn.LogSoftmax(dim=1)),输入维度 = 词表大小,输出维度 = 4 个类别;
  7. 训练循环:train_epoch()用 Adam 优化器(默认 lr=0.01)、NLLLoss损失,支持epoch_size截断训练(教学用只训部分数据)与report_freq控制进度打印。Notebook 中在 15,000 条样本上训练一个 epoch 后得到约86.2%的训练准确率(loss ≈ 0.0261)。

TensorFlow 版链路(TextRepresentationTF.ipynb)

  1. 加载数据:tfds.load('ag_news_subset')加载 TensorFlow Datasets 版 AG News,经dataset['train']/dataset['test']取子集,样本字段为label、title、description;
  2. 向量化:使用keras.layers.experimental.preprocessing.TextVectorization(max_tokens=vocab_size),先adapt(ds_train.take(500).map(extract_text))在部分数据上建立词表——Notebook 中把vocab_size限制为 50,000,最终实际词表长度约5,335。Notebook 明确提醒:只用子集建词表是为了提速,全量adapt会小幅提升最终准确率;
  3. BoW 向量化:to_bow()用tf.reduce_sum(tf.one_hot(vectorizer(text), vocab_size), axis=0)对 one-hot 向量求和;随后用map(...).batch(batch_size)(batch_size=128)构造训练/测试数据集;
  4. 定义分类器:keras.Sequential([keras.layers.Dense(4, activation='softmax', input_shape=(vocab_size,))]),损失为sparse_categorical_crossentropy,优化器 Adam,指标acc。Notebook 指出:4 分类问题准确率超过 80% 已是好结果;
  5. 端到端单网络:由于TextVectorization本身是 Keras 层,可以把它并入模型输入侧(keras.Input+ 向量化层 + one-hot 求和 + Dense),免去map预处理,训练时直接喂原始文本;
  6. 自动 BoW / TF-IDF:TextVectorization(max_tokens=..., output_mode='count')可自动输出词频向量,output_mode='tf-idf'则可自动计算 TF-IDF 权重——这是该 Notebook 提供的最便捷实验开关,用于对比"手动 one-hot 求和"与"内置向量化"两种实现。

两版对比小结

环节PyTorch 版TensorFlow 版
数据源torchtext.datasets.AG_NEWStfds.load('ag_news_subset')
分词/建词表get_tokenizer('basic_english')+vocab(counter, min_freq=1)TextVectorization(max_tokens=...)+adapt()
BoW 计算to_bow()手动累加词频one-hot 求和,或output_mode='count'
TF-IDF用 sklearn 的TfidfVectorizer(ngram_range=(1,2))演示内置output_mode='tf-idf'
分类器Linear(vocab_size,4) + LogSoftmax+ NLLLoss + AdamDense(4, softmax)+ sparse_categorical_crossentropy + Adam
关键超参min_freq、vocab_size、epoch_size、report_freq、batch_sizemax_tokens、adapt样本数、batch_size

用自己的数据集替换 AG News:具体操作步骤

第 1 步:选择并获取数据集(注意出处标注)

Kaggle 等平台上有大量适合文本分类的公开数据集。作业特别鼓励"创新"选题——不一定要再选新闻,可以选社会观测、历史档案、事件记录等非常规语料。使用他人数据时务必在 Notebook 中注明来源与作者(题目中的"used with attribution"是硬性要求)。

第 2 步:统一数据格式为 (label, text)

两套 Notebook 的后续代码都依赖统一的样本协议,这是替换的核心:

  • PyTorch 版要求训练/测试集是返回(label, text)元组的可迭代对象,且标签按classes列表的 0 基索引组织(bowify中t[0]-1的减一逻辑需与你的标签体系保持一致——若你的数据已是 0 基,可去掉减一或调整 classes 排列);
  • TensorFlow 版要求样本是包含label、title、description(或可映射出文本)字段的结构。最省事的方式是用tf.data.Dataset.from_tensor_slices构造,再复用现有的extract_text/tupelize辅助函数(注意extract_text中x['title']+' '+x['description']的拼接逻辑,需对应你数据的文本字段名)。

第 3 步:替换数据加载入口

  • PyTorch 版:把train_dataset, test_dataset = torchtext.datasets.AG_NEWS(root='./data')替换为你的数据读取代码(如 pandas/CSV 读取后构造元组列表),并同步替换classes列表与torchtext.datasets.AG_NEWS相关的所有引用;
  • TensorFlow 版:把tfds.load('ag_news_subset')替换为你的数据集构造代码,随后dataset['train']/dataset['test']的取子集方式也需相应调整。

第 4 步:按数据集特点调整关键参数

  • 词表规模:PyTorch 版用min_freq控制最低词频(Notebook 建议观察提高min_freq后词表长度如何显著下降);TensorFlow 版用max_tokens直接截断。对自定义数据集,建议先打印词表长度再决定截断值;
  • N-Gram 规模:bigram 会让词表爆炸——PyTorch 版在 AG News 上构建 bigram 词表得到约1,308,842个 token(Notebook 输出 "Bigram vocabulary length = 1308842")。TF 版同样提示 bigram 词表超过 130 万 token。除非与 embedding 降维结合,否则不建议对小语料直接上高维 n-gram;
  • 训练量:你的数据集可能远小于 AG News(约 12 万条训练样本)。此时可把epoch_size调大或不设(PyTorch 版默认None表示完整跑一个 epoch),并增加 epoch 数;report_freq决定进度打印频率,小数据集可调小以观察更多中间结果。

实验设计:尝试"出人意料"的数据集

作业特意举例:NUFORC 的UFO 目击记录数据集(可在 Kaggle 检索到,使用须注明出处)。这类数据与新闻语料差异巨大,恰好能检验文本表示方法的泛化能力,你可以围绕它设计如下观察点:

  • 分类目标自定:UFO 目击记录包含目击形状、时长、地点、描述等文本字段,可自定义分类任务(例如按目击类型/地区分组),验证 BoW 是否同样有效;
  • 领域词汇差异:此类语料的高频词(时间、地点、形状描述词)与新闻完全不同,可对比"直接跑"与"清理停用词后跑"两种配置下词频分布的差异;
  • 方法与数据规模的交互:在小语料上对比 BoW、bigram、TF-IDF 三种表示的训练准确率,观察 n-gram 词表爆炸在小语料上的实际影响;
  • 不确定性与边界:目击描述常含自由文本噪声,可借此观察低频词、拼写变体对词表构建和分类结果的影响。

更一般的选题建议:选择类别数不同(≠4)、文本长度分布不同、含明显领域词汇的数据集,能让"替换数据"这一动作产生真正有信息量的对比结论。

突出个人发现:改写 Notebook 的落点

"Rewrite the notebook to underline your own findings"要求你留下可复现、可解释的证据链,建议至少包含以下四类输出:

  1. 训练过程记录:保留/改造训练循环的进度打印,呈现准确率随样本数上升的曲线数据(PyTorch 版示例输出:3200 条时 80.28%、6400 条时 83.72%、9600 条时 85.34%、12800 条时 85.77%,最终 86.2%)——换成你的数据后,这一组数字本身就是最有说服力的发现;
  2. 词汇表分析:打印你的数据集词表长度、Top-N 高频词,对比"限制vocab_size/max_tokens前后准确率与训练时间的变化"(Notebook 明确建议做这个实验);
  3. 方法横向对比:在相同数据上分别训练 BoW、bigram(若内存允许)、TF-IDF 三个分类器,用表格汇总各自的词表大小、训练耗时与准确率,并解释差异原因;
  4. 结论与边界:明确指出你的数据上哪种表示最有效、哪种场景下出现反直觉现象,并呼应课程结论——频次类方法无法表达语义与词序,若需要更强效果应走向词嵌入与语言模型(见 课程 README 的后续单元导览)。

提交前的自检清单

  • ✅ 明确选用了 PyTorch 版还是 TensorFlow 版 Notebook;
  • ✅ 用自己的数据集(而非 AG News)完成了从加载、向量化到训练的全流程;
  • ✅ Notebook 中注明了数据集来源与作者(attribution);
  • ✅ 记录了训练中间结果、词表规模等观察数据,而非只有最终准确率;
  • ✅ 对 BoW / N-Gram / TF-IDF 至少做了部分对比,并给出自己的解读;
  • ✅ 尝试了一个"出人意料"的数据集(如 NUFORC 的 UFO 目击数据),并说明其带来的新观察;
  • ✅ 全文与 作业原文 的四项要求逐一对应,可独立复现。

完成以上步骤,你就完整交付了这份作业:既吃透了 课程 README 中的文本表示理论,也通过亲手替换数据集,验证了 BoW、N-Gram 与 TF-IDF 三种经典表示在真实(甚至非常规)语料上的行为差异,为下一课学习词嵌入(Embeddings)打下了可对比的实践经验基础。

  • 教程
  • 人工智能
  • 机器学习
  • 深度学习

【免费下载链接】AI-For-Beginners

12 Weeks, 24 Lessons, AI for All!

项目地址:https://gitcode.com/GitHub_Trending/ai/AI-For-Beginners
点击查看免费下载

相关推荐

上一篇:AI-HF_Patch终极指南:5步解锁AI少女游戏的完整体验
下一篇:AI少女游戏优化终极指南:5个步骤让游戏体验提升300%

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询