大模型教我成为大模型算法工程师之day19: NLP 基础与词表示
摘要:本文介绍了自然语言处理(NLP)中的文本向量化技术演进历程。从传统的One-Hot编码(高维稀疏、语义缺失)到分布式词嵌入(Word Embedding),重点讲解了Word2Vec的两种训练模式(CBOW和Skip-Gram)及其负采样优化技术。随后探讨了从单词级到子词级(Subword)的分词进化,特别是BPE算法如何解决未登录词问题。文章还概述了文本预处理的标准流程,并展示了PyTor
Day 19: NLP 基础与词表示 (NLP Basics & Word Embeddings)
摘要:欢迎进入自然语言处理 (NLP) 板块!如果说 CV 是教 AI “看”,那么 NLP 就是教 AI “读”和“写”。计算机无法直接理解人类的语言(符号),我们需要把文字变成数字。从最古老的 One-Hot 到经典的 Word2Vec,再到子词切分 (Subword),本文将带你走完文本向量化的进化之路。
1. 语言模型的核心难题:如何把词变成数?
计算机只认识 0 和 1,不认识 “Apple”。我们需要一种方法把单词映射到数学空间。
1.1 上古时代:One-Hot 编码
- 做法:假设字典里有 10000 个词。“Apple” 是第 3 个,向量就是
[0, 0, 1, 0, ...]。 - 缺点:
- 稀疏:维度太高,全是 0,浪费空间。
- 语义鸿沟:它认为 “Apple” 和 “Orange” 的距离,跟 “Apple” 和 “Car” 的距离是一样的(都是 2\sqrt{2}2)。实际上苹果和橘子应该更近。
1.2 分布式表示:Word Embedding
- 核心思想:一个词的含义由它的上下文决定(Distributional Hypothesis)。
- 目标:把每个词映射为一个低维、稠密的向量(如 256 维),且语义相似的词在空间距离更近。
2. Word2Vec:NLP 的第一个里程碑
2013年,Google 发布的 Word2Vec 让 NLP 突飞猛进。它不是一个深度神经网络,而是一个浅层的双层网络。
2.1 两种模式
- CBOW (Continuous Bag of Words):
- 任务:看周围的词(上下文),填中间的词。
- Example: The
?sat on the mat. →\to→cat
- Skip-Gram:
- 任务:看中间的词,猜周围的词。
- Example:
cat→\to→ The, sat, on…
2.2 训练黑科技:负采样 (Negative Sampling)
- 如果字典有 10万 个词,做 Softmax 分类计算量太大了(分母要算 10万 次指数)。
- 负采样:既然正确答案是 “cat” (正样本),我就随机挑 5 个不是 “cat” 的词(负样本,如 “car”, “sky”)。
- 任务变成了一个简单的二分类:分辨这个词是正样本还是负样本。计算量瞬间降下来了。
2.3 神奇的加减法
Word2Vec 训练出来的向量具有有趣的代数性质:
Vector(King)−Vector(Man)+Vector(Woman)≈Vector(Queen) Vector(\text{King}) - Vector(\text{Man}) + Vector(\text{Woman}) \approx Vector(\text{Queen}) Vector(King)−Vector(Man)+Vector(Woman)≈Vector(Queen)
3. 分词的进化:从 Word 到 Subword
在深度学习时代,我们很少直接用 Word(单词)做单位了,因为会有 OOV (Out of Vocabulary) 问题。
- Word-level:字典必须包含 “look”, “looks”, “looked”, “looking”。遇到 “lookup” 就傻了(Unknown Token)。
- Character-level:把单词拆成字母 ‘l’, ‘o’, ‘o’, ‘k’。粒度太细,序列太长,语义太散。
- Subword-level (子词):折中方案。这也是目前大模型(GPT/BERT)的标准配置。
3.1 BPE (Byte Pair Encoding)
- 原理:统计语料库,把最常一起出现的字符对合并成一个新的 Token。
- 过程:
- 初始状态:
l o o k,l o o k i n g - 发现
i和n经常在一起 →\to→ 合并为in。 - 发现
in和g经常在一起 →\to→ 合并为ing。 - 最后:
look是一个 Token,ing是一个 Token。
- 初始状态:
- 优势:
- 常见词(High frequency)保留完整单词:
Apple - 生僻词(Low frequency)拆成词根:
unfriendly→\to→un,friend,ly。 - 彻底解决了 OOV 问题。
- 常见词(High frequency)保留完整单词:
4. 文本预处理 Pipeline
做一个 NLP 任务,标准流程通常是:
- Normalization:转小写、去标点、去特殊符号。
- Tokenization:分词(使用训练好的 Tokenizer,如 BERT 的 WordPiece)。
- Indexing:把 Token 变成 ID (Lookup Table)。
- Padding/Truncating:把所有句子对齐到相同长度(短补 0,长截断)。
- Embedding:输入模型查找 Embedding Matrix。
5. 代码实践:使用 PyTorch 的 Embedding
nn.Embedding 本质上就是一个查表操作,它可以被训练。
import torch
import torch.nn as nn
# 1. 定义词表大小和向量维度
vocab_size = 10000
embed_dim = 256
# 2. 初始化 Embedding 层
# 这是一个 [10000, 256] 的矩阵,每一行代表一个词的向量
embedding_layer = nn.Embedding(num_embeddings=vocab_size, embedding_dim=embed_dim)
# 3. 输入数据 (必须是 LongTensor 类型的 ID)
# 假设是一个 Batch,包含两个句子,每个句子 4 个词
input_ids = torch.LongTensor([
[1, 523, 23, 9], # Sentence 1 IDs
[2, 44, 888, 0] # Sentence 2 IDs
])
# 4. 前向传播
# Output shape: [2, 4, 256]
vectors = embedding_layer(input_ids)
print(f"Input shape: {input_ids.shape}")
print(f"Output vectors shape: {vectors.shape}")
# 5. Word2Vec 的负采样 Loss 示例 (伪代码)
# pos_score = torch.sigmoid(torch.sum(center_vec * context_vec, dim=1))
# neg_score = torch.sigmoid(torch.sum(center_vec * negative_vec, dim=1))
# loss = -torch.log(pos_score) - torch.sum(torch.log(1 - neg_score))
6. 总结
- One-Hot 是过去式,Word Embedding(稠密向量)是现代 NLP 的基石。
- Word2Vec 利用上下文自监督学习词义,开启了 Embedding 时代。
- Subword (BPE/WordPiece) 解决了未登录词 (OOV) 问题,是 Transformer 模型的标配。
- 预告:虽然 Word2Vec 很强,但它有个致命缺陷——它是静态的。不管上下文怎么变,“Bank” 的向量永远不变(无法区分“银行”和“河岸”)。明天我们将学习 ELMo 和 BERT,看看如何解决多义词问题。
思考:为什么现在的 LLM (如 GPT-4) 还是用 Embedding?不能直接把文字当图像处理吗?
- 虽然有尝试(如 Pixel-based LLM),但文字本身是高度抽象的符号系统,Embedding 是目前最高效的将离散符号转化为连续语义空间的手段。
如果有更多问题,欢迎关注公众号【算法最TOP】进一步讨论!
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)