news 2026/10/9 9:57:48

用自定义数据集重跑 Embeddings 实验:AI-For-Beginners 第 14 课作业实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用自定义数据集重跑 Embeddings 实验:AI-For-Beginners 第 14 课作业实战指南
  • 教程
  • 人工智能
  • 机器学习
  • 深度学习

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

12 Weeks, 24 Lessons, AI for All!

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

本文围绕 AI-For-Beginners 第 14 课「Embeddings(词嵌入)」的 Notebooks 作业展开:你将学会如何用自有数据集(例如来自 Kaggle 并遵循署名的文本语料)重跑 PyTorch 或 TensorFlow 版嵌入实验,改写 Notebook 突出自己的观察结论,并系统掌握词嵌入、EmbeddingBag、Word2Vec 与预训练嵌入的完整技术链路。读完本文,你不仅能高质量完成作业,还能独立复现从文本分词到嵌入分类的全流程。

作业任务解读

该作业要求你完成以下四件事(详见 作业原文):

  1. 重跑配套 Notebook:选择 PyTorch 版 或 TensorFlow 版 中的任意一套,用你自己的数据集重新执行。
  2. 遵循数据出处规范:若数据来自 Kaggle 等平台,必须在交付物中注明来源并遵守相应署名(attribution)要求。
  3. 改写 Notebook:不要原样照搬,而是围绕你自己的观察与结论重构 Notebook 的结构、注释与说明文字。
  4. 尝试不同类型的语料:建议选用与默认 AG News 新闻数据集差异较大的数据,例如文本歌词(原文示例为 Beatles 歌词),并文档化你的发现(如词表规模、训练曲线、准确率差异、缺词率等)。

默认实验中使用的数据集是 AG News(PyTorch 版经torchtext.datasets.AG_NEWS加载,见 torchnlp.py;TensorFlow 版经tfds.load('ag_news_subset')加载),类别为 World、Sports、Business、Sci/Tech 四类。更换数据集后,类别数、语料语言、文本长度分布都会发生变化,这正是作业想要你观察和记录的差异点。

前置知识:为什么从词袋转向嵌入

要完成作业,首先要理解 Notebook 前半部分的技术背景。在第 14 课之前的实验中,分类器基于 BoW(词袋)或 TF/IDF,操作的是长度为vocab_size的高维稀疏向量,且需要把词的位置表示显式转换成 one-hot 编码。这种表示有两个明显缺陷(详见 课程 README):

  • 内存效率低:one-hot 向量大部分元素为 0,词表越大越浪费;
  • 无语义关联:每个词被独立对待,任意两个词的 one-hot 向量距离完全相等,无法表达词之间的语义相似性。

嵌入(Embedding)的核心思想是用低维稠密向量表示词,让向量在一定程度上反映词的语义。嵌入层接收一个词的编号作为输入,输出长度为embedding_size的向量。它从结构上类似Linear/Dense层,但输入不再是 one-hot 编码,而是词编号,从而避免构造巨大的 one-hot 向量。

将嵌入层作为网络第一层后,模型就从「词袋」升级为embedding bag(嵌入袋)模型:先把文本中每个词转换为对应嵌入,再对所有嵌入计算某种聚合函数(sum、average或max),得到整段文本的向量表示,最后交给线性分类器:

变长序列的两种处理方式(作业中必须理解的关键设计)

切换到嵌入后,一个立刻浮现的问题是:每个样本的单词数量不同,如何组织成 minibatch?之前 BoW 张量在 minibatch 中都是等长的vocab_size,而嵌入模型下文本序列长短不一。Notebook 给出了两种方案,你在改写时可以选择其一,并在文档中说明各自的取舍。

方案一:填充(padding)

PyTorch 版通过collate_fn=padify实现:先对每条文本编码成 token 序列,求出当前 minibatch 内序列的最大长度l,再用 0(PAD token)把较短序列补齐到等长。核心代码见 EmbeddingsPyTorch.ipynb:

def padify(b): # b 是长度为 batch_size 的元组列表 # - 元组第一个元素 = 标签 # - 第二个元素 = 特征(文本序列) v = [encode(x[1]) for x in b] l = max(map(len, v)) return ( torch.LongTensor([t[0]-1 for t in b]), torch.stack([torch.nn.functional.pad(torch.tensor(t), (0, l-len(t)), mode='constant', value=0) for t in v]) ) train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=16, collate_fn=padify, shuffle=True)

TensorFlow 版则由TextVectorization层自动完成同样的填充,两个不同长度的句子被向量化后得到 (2, 6) 的矩形张量,空位以 0 填充。Notebook 还给出了一个优化建议:可以按序列长度递增排序,使每个 minibatch 内序列长度相近,从而减少填充量。

方案二:偏移向量(offset)

填充会带来冗余计算。另一种更高效的表示是偏移向量:把所有序列拼接进一个大向量,再用一个offsets向量记录每个序列的起始位置:

PyTorch 中对应的是EmbeddingBag层,它同时接收内容向量和偏移向量,内部还集成了mean、sum或max聚合。改造后的分类器极其简洁:

class EmbedClassifier(torch.nn.Module): def __init__(self, vocab_size, embed_dim, num_class): super().__init__() self.embedding = torch.nn.EmbeddingBag(vocab_size, embed_dim) self.fc = torch.nn.Linear(embed_dim, num_class) def forward(self, text, off): x = self.embedding(text, off) return self.fc(x)

配套的offsetify用累积求和计算偏移:EmbeddingsPyTorch.ipynb

def offsetify(b): x = [torch.tensor(encode(t[1])) for t in b] o = [0] + [len(t) for t in x] o = torch.tensor(o[:-1]).cumsum(dim=0) return ( torch.LongTensor([t[0]-1 for t in b]), # 标签 torch.cat(x), # 文本 o # 偏移 )

注意:改用EmbeddingBag后,dataloader 一次返回 3 个值(标签、文本、偏移),网络前向也接受两个参数,因此必须配套使用专门的训练函数(PyTorch 版为train_epoch_emb,见 torchnlp.py),这一点在更换数据集时同样适用。

语义嵌入:Word2Vec 与 gensim

作业要求你「文档化自己的观察」,而这部分正是观察点最丰富的实验环节。前面训练的嵌入层只是把词映射到向量,并不保证向量具有语义含义。要让同义词的向量在欧氏距离等度量下彼此接近,需要用大规模语料以特定方式预训练嵌入模型,最经典的方法就是 Word2Vec,其两种架构为:

  • 连续词袋(CBoW):给定 n-gram $(W_{-2},W_{-1},W_0,W_1,W_2)$,用上下文 $(W_{-2},W_{-1},W_1,W_2)$ 预测中心词 $W_0$。训练更快。
  • 连续跳元(skip-gram):与 CBoW 相反,用中心词预测周围窗口内的上下文词。训练更慢,但对低频词的表征更好。

Notebook 使用 gensim 加载在 Google News 语料上预训练的word2vec-google-news-300模型进行实验,首次加载需要下载,耗时较长。你可以复现并观察:

  • w2v.most_similar('neural')返回最相似词(neuronal、neurons、neural_circuits…),相似度约在 0.65~0.78 之间;
  • w2v['play'][:20]展示 300 维向量的前 20 个分量;
  • 经典的向量运算:king - man + woman ≈ queen,gensim 直接给出结果('queen', 0.7118...);手动实现则是求目标向量与词表中所有向量距离的argmin。

在作业文档中,你可以记录以下对比:更换数据集后,同一单词的邻近词是否发生变化?你的语料是否包含 Word2Vec 预训练词表中缺失的领域词?另外,Notebook 还对比了 FastText(额外学习字符 n-gram,编码子词信息)和 GloVe(基于共现矩阵分解),gensim 均支持,可以替换模型加载代码做消融实验。

预训练嵌入落地:词汇表不一致问题(作业改写的核心难点)

Word2Vec/GloVe 预训练嵌入可以直接替代嵌入层,但面临一个关键问题:预训练模型的词表与你的语料词表大概率不一致。Notebook 给出了两条解决路径,你在重跑自有数据集时必然要处理这个问题:

路径 A:用自己的词表,缺词随机初始化

以 PyTorch 为例,遍历自己语料构建的词表(vocab.get_itos()),命中的词拷贝预训练向量,缺失的词用正态分布随机向量填充(见 EmbeddingsPyTorch.ipynb)。默认 AG News 实验中词表 95812,预训练命中 41080 个词,缺词 54732 个——这个「命中率」数据本身就是很好的观察记录点。需要说明的是,这会让嵌入层尺寸(如 300 维)远大于自训练方案(如 32 维),参数更多、训练更慢,也更容易过拟合。

TensorFlow(Keras)版思路相同:用vectorizer.get_vocabulary()遍历,构造vocab_size × embed_size权重矩阵W,缺失词可置零或随机初始化,再以keras.layers.Embedding(vocab_size, embed_size, weights=[W], trainable=False)冻结加载(注意trainable=False意味着不微调嵌入层,训练更快但准确率可能略低,见 EmbeddingsTF.ipynb)。

路径 B:用预训练模型的词表加载数据

PyTorch 版借助torchtext内置支持直接实例化 GloVe 词表:

vocab = torchtext.vocab.GloVe(name='6B', dim=50)

其基础操作包括:vocab.stoi(词 → 索引)、vocab.itos(索引 → 词)、vocab.vectors(嵌入向量矩阵,取词s的向量用vocab.vectors[vocab.stoi[s]])。随后用 GloVe 词表重新编码数据(encode(t[1], voc=vocab)),并直接把整个矩阵拷贝进嵌入层:

net = EmbedClassifier(len(vocab), len(vocab.vectors[0]), len(classes)) net.embedding.weight.data = vocab.vectors

Keras 版则用w2v.get_keras_embedding(train_embeddings=False)自动生成对应嵌入层,并用vectorizer.set_vocabulary(vocab)指定预训练词表。

两条路径的观察要点

两个 Notebook 的结论一致:换用预训练嵌入后准确率提升并不显著(PyTorch 版约 75% 上下,与自训练嵌入接近),主要原因是数据集中部分词在预训练词表中缺失、被忽略。这正指向作业要求的「记录你的发现」——请在你的改写版本中量化:

  • 语料词表与预训练词表的重合率;
  • 缺失词的占比及其对准确率的影响;
  • 若改为在自有语料上从头训练嵌入,效果是否更好。

上下文嵌入:一个必须写进结论的局限

课程明确指出了一个重要局限:词义消歧(word sense disambiguation)问题。Word2Vec 这类静态预训练嵌入把所有可能的词义编码进同一个向量,例如play在下面两个句子中含义完全不同:

  • I went to aplayat the theatre.(名词:戏剧)
  • John wants toplaywith his friends.(动词:玩耍)

但两个含义共享同一个嵌入向量,可能误导下游模型。克服方案是使用基于语言模型的上下文嵌入(contextual embeddings),课程将其留到后续语言模型单元讲解。在作业报告中,建议用你自己数据集中真实的歧义词举例,说明静态嵌入的局限,作为结论部分的升华。

完成作业的实操步骤清单

综合以上分析,一份合格的作业交付物建议包含以下步骤,请结合所选 Notebook 落地:

  1. 选定并获取数据集:从 Kaggle 等平台挑选与新闻文本类型不同的语料(如歌词、影评、法律文书、多语言文本),记录来源、许可证与署名信息。
  2. 替换数据加载代码:将 Notebook 中AG_NEWS/ag_news_subset的加载逻辑替换为你的数据读取逻辑,同步更新classes类别列表;若使用 PyTorch,torchnlp.py 的load_dataset与encode均可复用,只需替换数据源。
  3. 重建词表:记录新的词表规模与min_freq过滤效果;对比 AG News 的 95812,观察歌词等小语料的词表差异。
  4. 按步骤重跑:依次完成自训练嵌入分类器(padify + EmbeddingBag 两条路径)、gensim Word2Vec 语义实验、预训练嵌入(路径 A/B)三组实验,记录每组训练的 loss/acc 曲线与耗时。
  5. 改写与文档化:把每步的代码注释和 Markdown 说明改为「你的观察」——例如「更换数据集后命中率变化」「低资源语料上预训练嵌入是否仍然有效」「聚合函数 mean/sum/max 的选择对结果的影响」。
  6. 结论与局限:结合上下文嵌入的局限,给出针对该数据集的最终结论与后续改进方向。

交付自查清单

提交前对照以下要点检查你的改写成果:

  • 数据来源与署名是否明确标注;
  • 数据集类别/标签是否与分类器输出维度一致;
  • 词表不一致问题是否被显式处理并记录命中率;
  • 训练函数是否适配了EmbeddingBag的三元组输入(若选用偏移方案);
  • 每个实验是否包含你自己的观察注释与量化结论;
  • 是否对比了「自训练嵌入 vs 预训练嵌入」及不同数据集之间的表现差异。

完成以上步骤,你交付的将不再是对照源码的复制,而是一份结构完整、有独立观察与结论的嵌入技术实验报告。

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

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

12 Weeks, 24 Lessons, AI for All!

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

相关推荐

上一篇:解锁老旧Mac潜能:OpenCore Legacy Patcher终极技术指南
下一篇:OpenCore Legacy Patcher完整指南:四步让老旧Mac重获新生

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/9 9:53:00

组态王连接S7-200 SMART TCP通信实操指南

1. 项目概述:为什么这个连接案例值得花时间吃透?组态王——国内工业自动化领域绕不开的上位机软件,尤其在中小型产线、教学实训、设备改造场景里,它几乎是电气工程师和自动化调试人员的“默认选项”。而S7-200 SMART,则…

作者头像 李华
网站建设 2026/10/9 9:51:25

化工区无线传感器网络实战:高危环境下的可靠监测系统搭建

简介:本资源是一份面向物联网、环境工程及嵌入式系统方向本科生与毕业设计者的完整学术研究报告,聚焦化工区高危场景下的空气环境实时监测难题,提出基于无线传感器网络(WSN)的低功耗、远距离、自供电解决方案。报告涵盖…

作者头像 李华
网站建设 2026/10/9 9:51:16

美赛C题Wordle论文复现:GRU与随机森林全流程解析

简介:这是2023年美赛获奖C类论文《通过数据分析揭示Wordle的秘密》的完整PDF文档,面向参加美赛的学生、数学建模爱好者和数据分析学习者。论文以《纽约时报》热门游戏Wordle为案例,完整展示了数据分析驱动建模的流程:先利用门控循…

作者头像 李华
网站建设 2026/10/9 9:48:02

Python中的并发编程asyncio库入门使用

前言 asyncio 是 Python 标准库里的异步框架,但它不是「一个函数」,而是一整套协作式并发的基础设施。新手常犯的错,是把 asyncio 的 API 当成 threading 的等价物来用——随手 await 两下,却发现根本没有并发。 这篇是API 速查 …

作者头像 李华