计算机如何理解"国王"和"女王"之间的关系?如何知道"学习"和"研究"比"苹果"更相似?答案藏在词向量中。
词向量是自然语言处理领域最重要的突破之一,它让机器第一次真正"理解"词汇之间的语义关系。从最早的独热编码到如今的上下文化表示,词向量的演进推动了整个 NLP 领域的发展。本文将深入探讨词向量的核心技术: Word2Vec 如何通过简单的神经网络学习语义, GloVe 如何利用全局统计信息, FastText 如何处理未登录词,以及语言模型如何为这一切提供理论基础。
我们不仅会分析算法原理和数学推导,还会通过代码实战、可视化分析和实际案例,让你真正掌握词向量技术。无论你是想理解"king - man + woman = queen"背后的数学原理,还是想动手训练自己的词向量模型,这篇文章都会给你答案。
从独热编码到词向量
独热编码的困境
最直观的词表示方法是独热编码( one-hot encoding)。假设词汇表大小为
这种表示有三个致命缺陷:
维度灾难:英语常用词汇约 5
万个,专业领域可达数十万。每个词需要一个超高维稀疏向量,计算和存储成本极高。假设词汇表有
50,000 个词,每个文档平均 500 个词,那么文档的向量表示就是
语义鸿沟:任意两个不同词的独热向量内积为
0,无法表达语义相似性。"猫"和"狗"应该比"猫"和"汽车"更相似,但在独热编码中,它们与任何词的距离都相等:
无法泛化:模型在训练集上学到的关于"猫"的知识,无法迁移到"狗"上,即使它们都是动物。这导致模型需要大量数据才能学习相似概念的相似行为。
分布式假设
词向量的理论基础是分布式假设( Distributional Hypothesis),由语言学家 Harris 在 1954 年提出:
"出现在相似上下文中的词,具有相似的语义。"
换句话说,一个词的意义由它的邻居决定。"猫"经常出现在"宠物"、"喵喵叫"、"抓老鼠"等上下文中,"狗"出现在"宠物"、"汪汪叫"、"看家"等上下文中。虽然具体行为不同,但它们共享"宠物"这个核心上下文,因此语义相近。
这个假设让可以从大规模无标注语料中学习词的表示:通过统计词的共现模式,将语义信息压缩到低维稠密向量中。
词向量的优势
词向量( word
embeddings)将每个词映射到一个低维稠密的实数向量空间
这种表示具有三大优势:
低维稠密:从 50,000 维的独热向量降到 100-300 维的稠密向量,减少了 99%以上的存储空间,同时每个维度都携带信息。
语义相似:相似的词在向量空间中彼此接近。可以用余弦相似度度量:
典型结果:
向量代数:词向量支持语义运算,最著名的例子是:
这意味着词向量不仅捕捉了词的意义,还捕捉了词之间的关系(如性别、时态、单复数等)。
Word2Vec:革命性的突破
Word2Vec 由 Google 的 Mikolov 等人在 2013 年提出,它用浅层神经网络从大规模语料中学习词向量。核心思想极其简单:通过预测上下文来学习词的表示。
两种架构
Word2Vec 有两种训练架构:
Skip-gram(跳字模型):给定中心词,预测周围的上下文词。
CBOW(连续词袋模型):给定上下文词,预测中心词。
直观对比:
- Skip-gram:已知"学习",预测可能出现"深度"、"机器"、"算法"等词
- CBOW:已知"深度...算法",预测中间可能是"学习"
Skip-gram 详解
模型定义
给定长度为
其中
条件概率使用 softmax 定义:
这里每个词有两个向量:
-
为什么需要两套向量?
这是一个常被忽视但很重要的设计。考虑一个极端情况:如果只用一套向量,当词
两套向量的分工:
- 输入向量:学习词的核心语义(最终我们用的就是这个)
- 输出向量:作为预测上下文的参数矩阵
训练结束后,通常只保留输入向量
训练过程
假设词汇表为
对于中心词 "love"(位置
- 上下文词:
, - 目标:最大化
前向传播计算 :
反向传播更新向量
softmax 的计算瓶颈
问题在于分母:对于词汇表中的每个词都要计算
训练一个模型通常需要处理数十亿个词,如果每个词的每次预测都要遍历整个词汇表,训练时间将长到无法接受。
负采样:高效的近似
负采样( Negative Sampling)是 Word2Vec 最重要的优化技巧,它将多分类问题转化为二分类问题。
核心思想:从考试类比理解
直觉类比:
想象你在准备考试,有两种复习策略:
- 完整训练( Full Softmax):对题库中所有 10000 道题都逐一练习 → 时间成本太高
- 负采样策略:只练习几道确定会考的题(正样本) + 几道随机抽取的题(负样本) → 高效且覆盖面广
在 Word2Vec 中的应用:
原始问题:给定中心词"king",需要从 50000 个候选词中预测哪个词是真实的上下文词。这需要计算 50000 个 softmax 概率,计算量巨大。
负采样的转化:将问题变为"判断某个词是否是真实上下文"的二分类:
- 正样本:"king"旁边确实出现"queen" → 标签为 1
- 负样本:随机选 5 个词(如"apple", "car", "run", "happy", "blue") → 标签为 0
数学形式化:
对于一个正样本对
其中
公式深度解读:
- 第一项
:最大化正样本的概率 - 当
越大时, 越接近 1, 越接近 0(损失越小) - 直觉含义:"queen"确实应该出现在"king"附近,让它们的向量内积尽可能大
- 数值示例:若内积=5,则
, (损失很小);若内积=-2,则 , (损失很大)
- 当
- 第二项
:最小化负样本的概率 - 当
越小(甚至为负)时, 越接近 1,损失越小 - 直觉含义:"apple"不应该出现在"king"附近,让它们的向量内积尽可能小
- 数值示例:若内积=-3,则
, (损失很小);若内积=2,则 , (损失很大)
- 当
为什么这样有效?
核心洞察:只要模型能区分"真实上下文词"和"随机噪声词",就能学到有意义的词向量。不需要精确建模每个词出现的概率,只需要知道"哪些词应该接近,哪些词应该远离"。
数学上,负采样是在近似完整的 softmax 目标。 Mikolov 等人的论文证明,当负样本数量足够多时,负采样的目标函数收敛到 softmax 的目标函数。
负样本如何采样?
简单的均匀采样效果不好,因为高频词(如"the"、"is")会被过度采样。
Word2Vec 使用修正的 unigram 分布:
其中
实例:假设"the"出现 10,000 次,"deep"出现 100 次。
- 均匀采样:
- 幂采样: 低频词的采样概率提升了 3 倍。
计算量对比
- 原始 softmax:每个样本需要
次计算, 是词汇表大小 - 负采样:每个样本需要
次计算, 通常取 5-20
当
层次 softmax:另一种加速方案
层次 softmax( Hierarchical Softmax)用一棵二叉树代替 flat 的 softmax
层,将计算复杂度从
霍夫曼树构造
将词汇表组织成一棵霍夫曼树( Huffman Tree),频率高的词靠近根节点,频率低的词在叶子深处。每个词对应一个叶子节点,从根到该叶子的路径定义了一个唯一的二进制编码。
例如,对于词汇表
1 | root |
路径编码: - "the": 左左 → 00 - "is": 左右 → 01
- "cat": 右左 → 10 - "learning": 右 → 1
概率计算
从根到词
假设路径为
其中
复杂度分析
- 计算:每个词的路径长度平均为
,计算量比 flat softmax 的 小得多 - 频繁词优势:高频词(如"the")路径短,低频词路径长,训练自动聚焦于常见词
负采样 vs 层次 softmax
| 特性 | 负采样 | 层次 softmax |
|---|---|---|
| 计算复杂度 | ||
| 小语料 | 表现一般 | 表现较好 |
| 大语料 | 表现优秀 | 速度较慢 |
| 低频词 | 可能训练不足 | 路径长,更新充分 |
| 实现复杂度 | 简单 | 需要构建树 |
实践建议:大规模语料用负采样(
CBOW 详解
CBOW( Continuous Bag of Words)是 Skip-gram 的逆过程:给定上下文词,预测中心词。
模型定义
目标函数:
上下文表示是上下文词向量的平均:
条件概率:
Skip-gram vs CBOW
数据效率:
- CBOW 将多个上下文词平均,每个样本利用
个词的信息,训练更快 - Skip-gram 对每个上下文词单独预测,生成更多训练样本
低频词处理:
- CBOW 对上下文词做平均,低频词的信号被高频词淹没,学习效果差
- Skip-gram 单独处理每个词,低频词有专门的训练样本
语义细节:
- CBOW 倾向于学习语法和词性信息(因为上下文是模糊的平均)
- Skip-gram 学习更细致的语义关系
实验结果( Mikolov 论文):
- 小数据集: CBOW 略优(训练样本更充分)
- 大数据集: Skip-gram 显著更好(尤其是低频词)
推荐:默认使用 Skip-gram + 负采样,除非数据量极小或只关注高频词。
超参数调优
向量维度
- 太小(
):表达能力不足,无法捕捉复杂语义 - 太大(
):过拟合,训练慢,对下游任务帮助不大 - 推荐:
,通用语料用 100-150,专业领域用 200-300
窗口大小
- 小窗口(
):捕捉语法和词性,相似词倾向于可替换("好"和"优秀") - 大窗口(
):捕捉主题和领域,相似词倾向于相关("医生"和"医院") - 推荐:
(平衡语法和语义)
负采样数量
- 小数据集:
- 大数据集:
(大数据下梯度估计已经足够准确)
采样阈值
高频词(如"the")对语义贡献小,但大量出现会支配梯度。 Word2Vec
用子采样策略以概率
其中
GloVe:全局统计的力量
GloVe( Global Vectors for Word Representation)由 Stanford 的 Pennington 等人在 2014 年提出。它结合了矩阵分解方法(如 LSA)的全局统计优势和局部上下文方法(如 Word2Vec)的预测能力。
核心思想
Word2Vec 从局部窗口中学习,每次只看中心词和邻近上下文,没有充分利用全局统计信息。
GloVe 的洞察:词的共现统计蕴含丰富的语义关系。
考虑三个词:"ice"(冰)、"steam"(蒸汽)、"water"(水)。统计它们的共现次数:
| 上下文词 | ice | steam |
|---|---|---|
| solid | 高 | 低 |
| gas | 低 | 高 |
| water | 高 | 高 |
| fashion | 低 | 低 |
观察比值
-
结论:共现概率的比值比原始概率更能区分语义关系!
目标函数
GloVe 构建词-词共现矩阵
目标函数:
关键组件:
词向量与偏置:每个词有中心向量
目标:让内积
权重函数
参数通常取
为什么需要权重函数?
权重函数
问题 1:零共现的处理
如果
GloVe 的解决方案:设置权重
这意味着我们不惩罚零共现的预测误差,但也不完全忽略它(因为模型仍需要学习这些词对的表示)。
问题 2:高频词对主导优化过程
考虑两个词对: - "the" 和 "a" 共现 100,000 次 - "quantum" 和 "entanglement" 共现 100 次
如果使用相同权重,损失函数会被高频词对主导:
即使
GloVe 的权重函数设计:
这个设计有三个巧妙之处:
低频共现(
):权重随共现次数增加而增加,符合直觉——共现次数越多,统计越可靠,应该给更大权重。 高频共现(
):权重固定为 1,避免极高频词对过度主导。这是一种"截断"策略。 指数
:让权重增长速度比线性慢。为什么不用线性( )?看一个数值例子:
数值示例:假设
可以看到,指数
实际效果:
对于"quantum"和"entanglement"(
现在两者对损失函数的贡献相当,低频词的语义也能得到充分学习。
训练细节
共现矩阵构建:
遍历语料库,对每个词
对于窗口大小
优化算法:
使用 AdaGrad 自适应学习率,初始学习率
最终向量:
训练完成后,每个词有两个向量:
实验表明,求和比单独使用或求平均效果更好。
GloVe vs Word2Vec
| 维度 | Word2Vec | GloVe |
|---|---|---|
| 训练方式 | 在线学习,逐个窗口 | 批量优化,全局统计 |
| 信息利用 | 局部上下文 | 全局共现 |
| 训练速度 | 快(单次遍历) | 慢(需多次迭代矩阵) |
| 内存占用 | 小(只存模型参数) | 大(需存共现矩阵) |
| 低频词 | Skip-gram 较好 | 通过权重函数改善 |
| 可解释性 | 较弱 | 较强(直接建模共现) |
理论联系: Levy 等人证明, Word2Vec 的 Skip-gram +
负采样实际上是在隐式分解一个移位的点互信息矩阵( PMI):
其中
这表明 Word2Vec 和 GloVe 本质上都在从共现统计中提取信息,只是方式不同:
- Word2Vec:隐式、增量式、随机化
- GloVe:显式、批量式、确定性
实践选择:
- 大规模语料: Word2Vec 更快,性能相近
- 中小规模语料: GloVe 可能更稳定(充分利用全局信息)
- 增量更新: Word2Vec 支持, GloVe 需重建矩阵
- 预训练向量:两者都提供,可以都试试
FastText:子词的威力
FastText 由 Facebook AI Research 在 2016 年提出,核心创新是将词表示为字符 n-gram 的组合,而不是单一向量。
问题背景
Word2Vec 和 GloVe 的共同缺陷:
OOV 问题:训练时未出现的词( Out-Of-Vocabulary),无法得到向量表示。医学文献中的"methylprednisolone"如果训练集没见过,就完全没有表示。
形态信息丢失:忽略词的内部结构。"teach"、"teacher"、"teaching"是独立的三个词,无法共享"teach"这个词根的语义。
复合词处理差:德语"Lebensversicherungsgesellschaftsangestellter"(人寿保险公司员工),即使未见过,人类也能从子词推断含义。
子词表示
FastText 将每个词拆分成字符 n-gram 的集合。对于词
- 字符 3-gram:
<wh,whe,her,ere,re> - 加上完整词本身:
<where>
特殊符号 < 和 >
标记词的边界,区分"her"(独立词)和"her"("where"的子串)。
每个 n-gram 有独立的向量
其中
训练目标
FastText 使用 Skip-gram 框架,但把词向量
其中评分函数:
训练时更新的是 n-gram 向量
OOV 词处理
FastText 最强大的能力之一是处理OOV( Out-Of-Vocabulary)词,即训练时未见过的词。这是 Word2Vec 和 GloVe 无法做到的。
OOV 处理流程
当测试时遇到未登录词
步骤 1:提取字符 n-gram
将未登录词拆分成字符 n-gram 集合:
特殊符号<和>标记词的边界,确保子词的唯一性。
步骤 2:查找 n-gram 向量
在训练好的 n-gram 向量表中查找这些 n-gram 的向量
步骤 3:求和生成词向量
完整实例:处理"teaching"
背景:训练集包含"teacher"和"preaching",但没有"teaching"。测试时遇到"teaching",如何生成向量?
步骤 1:提取 3-gram
"teaching"的 3-gram(
1 | <te, tea, eac, ach, chi, hin, ing, ng> |
步骤 2:识别共享的 n-gram
与训练集词汇的 n-gram 对比:
- "teacher"的
3-gram:
<te, tea, eac, ach, che, her, er> - "preaching"的
3-gram:
<pr, pre, rea, eac, ach, chi, hin, ing, ng>
"teaching"与它们共享的 n-gram:
| n-gram | 出现在"teacher"? | 出现在"preaching"? |
|---|---|---|
tea |
✅ | ❌ |
eac |
✅ | ✅ |
ach |
✅ | ✅ |
chi |
❌ | ✅ |
hin |
❌ | ✅ |
ing |
❌ | ✅ |
步骤 3:组合生成向量
假设训练后的 n-gram 向量为:
则"teaching"的向量为:
由于大部分 n-gram 与"teacher"共享,
为什么这样有效?
语义继承:相似的词通常共享相似的子词。"teaching"和"teacher"都包含"teach"的语义核心。
泛化能力:即使整词未见过,只要其子词在训练集中出现过(通过其他词), FastText 就能生成合理的表示。
实际应用场景:
- 专有名词:新人名、地名(如"Zuckerberg")可以从子词"berg"等推断
- 拼写错误:用户输入"recieve"(正确是"receive"),仍能生成接近"receive"的向量
- 新词:社交媒体上的新词(如"selfie")可以从"self"等子词推断
- 复合词:德语复合词可以从组成部分推断
这让 FastText 特别适合处理动态变化的语言环境。
超参数选择
n-gram 长度:
- 太短(
):噪声大,"th"出现在太多无关词中 - 太长(
):过于稀疏,很多词的 n-gram 独一无二 - 推荐:
,英语常用 3-4,形态丰富的语言(如土耳其语)用 4-6
子词数量限制:
完整存储所有 n-gram 会占用大量内存(百万级)。 FastText 用哈希技巧将 n-gram 映射到固定大小的向量表(如 200 万桶),冲突的 n-gram 共享向量。
形态语言的优势
FastText 在形态丰富的语言上表现尤为出色:
土耳其语:大量后缀附加,如"evlerinizden"(从你们的房子),拆分为"ev"(房子)+"ler"(复数)+"iniz"(你们的)+"den"(从)。即使整词未见过, FastText 可以从子词推断。
芬兰语: 15 种格变,如"talo"(房子)可以变化为"talossa"(在房子里)、"talosta"(从房子)、"taloon"(到房子)。 FastText 共享词干"talo"的语义。
德语复合词:"Donaudampfschifffahrtsgesellschaftskapit ä n"(多瑙河蒸汽船公司船长),虽然罕见,但可以从"Donau"(多瑙河)、"dampf"(蒸汽)、"schiff"(船)等子词推断。
FastText 的权衡
优点:
- 可以处理 OOV 词
- 利用形态信息,拼写相近的词向量相近
- 对拼写错误有一定鲁棒性
缺点:
- 训练和存储开销更大(需要几百万个 n-gram 向量)
- 词义不受限于上下文,"bank"(银行)和"bank"(河岸)的子词完全相同,无法区分
- 中文等字符语言需要特殊处理(通常用字或词作为单位,而不是字符)
实践建议:
- 形态丰富语言、专业领域、 OOV 严重:选 FastText
- 大规模通用语料、英语: Word2Vec 或 GloVe 足够
- 需要上下文化表示(多义词):用 BERT 等预训练模型
统计语言模型
词向量的学习目标是预测上下文,这实际上是在建模语言的概率分布。理解语言模型对于理解词向量至关重要。
语言模型的定义
语言模型的任务是建模一个句子的概率
语言模型的核心问题:如何估计条件概率
N-gram 模型
完整的历史
Unigram(
Bigram(
Trigram(
参数估计
使用最大似然估计( MLE)从训练语料中统计:
Bigram 概率:
其中
实例:语料库中"I love"出现 100 次,"I"出现 1000
次,则
平滑技术
稀疏性问题:很多 n-gram 在训练集中从未出现, MLE 估计的概率为 0,这会导致整个句子的概率为 0(因为是连乘)。
平滑技术给未见过的 n-gram 分配一个小的非零概率。
加法平滑( Add-k Smoothing)
在所有计数上加一个小的常数
其中
问题:给所有未见 n-gram 分配相同概率太粗糙,实际效果不佳。
Kneser-Ney 平滑
最先进的平滑方法之一,核心思想是使用低阶模型补充高阶模型。
绝对折扣:
其中
直觉:对于常见 n-gram,减去固定折扣
评价指标:困惑度
困惑度( Perplexity)衡量语言模型的预测能力:
解释:困惑度表示模型在每个位置平均需要从多少个词中选择。 PPL=100 意味着模型平均在 100 个词中"纠结"。困惑度越低,模型越好。
实例:
- 随机猜测( Unigram 均匀分布):
(词汇表大小) - 完美模型:
(总能正确预测) - 实际 Trigram 模型:
(英语)
N-gram 的局限
长距离依赖缺失: Trigram 只看前两个词,无法捕捉"The cat, which was sitting on the mat, ____"中"cat"和空白位置的关系。
数据稀疏: 4-gram 、 5-gram 的大部分组合从未出现,即使使用平滑,估计也不可靠。
维度爆炸: Trigram 需要存储
无泛化能力:"I love cats"和"I love dogs"完全独立,即使"cats"和"dogs"语义相近,模型也无法利用这一点。
这些问题驱动了神经语言模型的诞生。
神经语言模型
神经语言模型用神经网络直接估计
前馈神经语言模型( NNLM)
Bengio 等人在 2003 年提出的 NNLM 是第一个成功的神经语言模型,也是词向量的早期尝试。
模型结构
输入层:前
隐藏层:
输出层( softmax):
关键优势
参数共享:词向量在所有位置共享,"love"无论出现在哪个位置,都用同一个向量表示。这大幅减少了参数量(从
平滑泛化:相似词的向量相近,导致它们的条件概率分布也相近。如果模型学到"I love cats"概率高,自动推断"I love dogs"概率也高(只要"cats"和"dogs"向量接近)。
连续空间:不同于离散的 N-gram 计数,神经模型在连续空间中插值,对未见序列也能给出合理概率。
与 Word2Vec 的联系
NNLM 训练的副产品是词向量矩阵(输入层的查找表),这些词向量捕捉了词的语义。但 NNLM 的主要目标是语言模型,训练开销大( softmax 层遍历整个词汇表)。
Word2Vec 简化了 NNLM:
- 去掉隐藏层(浅层网络)
- 用负采样或层次 softmax 代替 softmax
- 专注于学习词向量,而不是完整的语言模型
可以说,Word2Vec 是 NNLM 的轻量级、专用化版本。
RNN 语言模型
循环神经网络( RNN)可以处理任意长度的历史,突破了 N-gram 的固定窗口限制。
模型结构
在每个时间步
隐藏状态
优势
无限历史:理论上可以记忆整个句子的信息,不受固定窗口限制。
参数共享:所有时间步共享权重矩阵
动态表示:相同的词在不同上下文中的隐藏状态不同,自然处理多义词。
实践中的问题
梯度消失/爆炸:反向传播时梯度指数衰减或增长,导致长距离依赖难以学习。
训练慢:循环结构无法并行化,训练大规模语料非常耗时。
解决方案: LSTM 和 GRU 引入门控机制缓解梯度问题; Transformer 用自注意力机制实现并行化(这已经超出本文范围,是现代 NLP 的主流)。
词向量的几何性质
词向量最令人惊叹的性质是它们的几何结构蕴含语义关系。这不是偶然,而是训练目标的必然结果。
余弦相似度
最常用的相似度度量是余弦相似度:
取值范围
实例(使用预训练的 Word2Vec):
1 | sim('king', 'queen') = 0.71 |
向量代数:类比推理
词向量最神奇的性质是支持向量运算来推理语义关系。
经典案例
解释:
-$v_{} - v_{}
用最近邻搜索验证:
更多类比
地理关系:
语法关系:
比较级:
为什么有效?
从训练目标看, Skip-gram 最大化:
如果"king"和"queen"共享大部分上下文("royal"、"throne"、"crown"),但"king"更常与"man"、"he"共现,"queen"更常与"woman"、"she"共现,那么:
因此:
这暗示了向量的不同维度捕捉不同的语义属性(如性别、时态、数量等),类比推理本质上是在这些语义维度上的线性变换。
可视化: t-SNE 降维
词向量通常是 100-300 维,无法直接可视化。 t-SNE( t-distributed Stochastic Neighbor Embedding)将高维向量降到 2D 或 3D,同时尽量保持局部邻域结构。
t-SNE 原理
高维相似度:将欧氏距离转换为概率
低维相似度:用 t 分布(自由度为 1)
优化目标:最小化 KL 散度
使得低维表示
实践要点
困惑度参数:控制关注的邻居数量,通常设为 5-50 。困惑度小,关注极近邻;困惑度大,保留更全局的结构。
随机性: t-SNE 对初始化敏感,多次运行可能产生不同的图形(但聚类结构应该稳定)。
不保留全局距离: t-SNE 保留局部结构,不同聚类之间的距离没有意义。
可视化示例:
1 | from sklearn.manifold import TSNE |
典型观察:
- 语义相近的词聚成簇(国家名、动物名、颜色词)
- 同义词紧密聚集( big/large/huge)
- 反义词有时也聚在一起( hot/cold,因为共享相似的上下文)
实战:用 gensim 训练 Word2Vec
理论讲完了,现在动手训练自己的词向量模型。 gensim 是 Python 中最流行的词向量库。
环境准备
1 | pip install gensim nltk |
数据准备
使用 NLTK 的 Brown 语料库作为示例:
1 | import nltk |
输出:
1 | Total sentences: 57340 |
训练 Skip-gram 模型
Word2Vec 训练是将大规模文本语料转换为词向量的过程。 gensim 库封装了 Word2Vec 的完整实现,包括 Skip-gram 、 CBOW 、负采样、层次 softmax 等算法,使用简单但功能强大。
问题背景:需要从原始文本语料中学习词的稠密向量表示。这个过程需要处理数百万到数十亿个词,计算词与上下文的共现关系,通过梯度下降优化词向量。 gensim 的 Word2Vec 类封装了所有这些复杂性,提供了简洁的 API 。
解决思路: Word2Vec 通过预测上下文来学习词向量。 Skip-gram 架构给定中心词预测周围词,通过最大化预测概率来更新词向量。负采样将多分类问题转化为二分类,大幅提升训练速度。训练过程是迭代的,需要多轮遍历语料才能收敛。
设计考虑:参数选择至关重要。 vector_size 控制表达能力, window 控制语义范围, min_count 过滤噪声词, negative 控制负采样数量。这些参数需要根据数据规模和任务需求调整。 gensim 支持多线程训练( workers 参数),可以充分利用多核 CPU 加速训练。
1 | from gensim.models import Word2Vec |
深入解读: Word2Vec 训练的关键细节
Word2Vec 训练看似简单,但涉及许多重要的设计决策和优化技巧:
1. 数据格式要求
gensim 的 Word2Vec 要求输入是词列表的列表:
1 | # ✅ 正确格式 |
2. 参数选择的经验法则
| 参数 | 小数据集(<1000 万词) | 中等数据集( 1000 万-1 亿词) | 大数据集(>1 亿词) |
|---|---|---|---|
vector_size |
50-100 | 100-200 | 200-300 |
window |
5-10 | 5 | 5 |
min_count |
1-2 | 5 | 10 |
negative |
10-20 | 5-10 | 2-5 |
epochs |
15-20 | 10-15 | 5-10 |
3. 训练速度优化
1 | # 方法 1:使用生成器(节省内存) |
4. 常见问题与解决方案
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 内存溢出 | 语料太大,一次性加载 | 使用生成器或分批处理 |
| 训练速度慢 | workers 设置不当或算法选择不当 | 增加 workers,使用负采样而非层次 softmax |
| 词向量质量差 | 数据量不足或参数不当 | 增加数据量,调整 window 和 vector_size |
| 某些词没有向量 | 词频低于 min_count | 降低 min_count 或增加数据量 |
| 结果不可复现 | 未设置随机种子 | 设置 seed 参数 |
5. 训练监控
1 | # 方法 1:使用回调函数监控训练 |
6. 增量训练
gensim 支持在已有模型基础上继续训练:
1 | # 加载已有模型 |
7. 模型评估
训练完成后,需要评估词向量质量:
1 | # 方法 1:词相似度 |
8. 生产环境部署
实际部署时需要考虑:
- 模型大小:大型模型(数百万词)可能占用数 GB 内存
- 加载时间:模型加载可能需要几秒到几分钟
- 推理速度:查找相似词、计算相似度等操作的速度
- 版本管理:记录模型版本、训练参数、数据来源
1 | # 优化模型大小:只保留常用词 |
理解 Word2Vec 训练的每个参数和步骤,能够帮助你在实际项目中训练出高质量的词向量模型。
探索词向量
查找相似词
1 | # 加载模型 |
输出示例:
1 | woman: 0.7823 |
词向量类比
1 | # king - man + woman = ? |
注意: Brown 语料库较小,可能无法完美复现经典案例。使用大规模语料(如 Wikipedia 、 Common Crawl)效果更好。
计算相似度
1 | # 两个词的余弦相似度 |
获取词向量
1 | # 获取词的向量表示 |
训练 CBOW 模型
只需改变一个参数:
1 | model_cbow = Word2Vec( |
使用预训练向量
训练大规模语料耗时耗力,直接使用预训练向量更实用。 Google 提供的预训练 Word2Vec 包含 300 万个词和短语:
1 | import gensim.downloader as api |
其他预训练模型:
glove-wiki-gigaword-100: GloVe 向量, 100 维glove-twitter-25:推特语料训练, 25 维fasttext-wiki-news-subwords-300: FastText 向量, 300 维
评估词向量质量
词类比任务
使用标准数据集(如 Google 的 analogies dataset)评估:
1 | # 下载词类比数据集 |
词相似度任务
使用人工标注的相似度数据集(如 WordSim-353)评估:
1 | from scipy.stats import spearmanr |
相关系数越高,说明模型的相似度判断越接近人类。
中文词向量训练
中文需要先分词:
1 | import jieba |
推荐的中文预训练向量:
- 清华大学开源的中文词向量:Chinese Word Vectors
- 腾讯 AI Lab 开源的词向量:包含 800 万词汇, 200 维
❓ Q&A: 词向量常见问题
Q1: 为什么 Word2Vec 能捕捉语义,它又没有标注数据?
A: 这是自监督学习( self-supervised learning)的力量。虽然没有人工标注,但"预测上下文"这个任务本身就蕴含语义信息。根据分布式假设,共享相似上下文的词应该有相似表示。当模型学会预测上下文时,自然会将语义相近的词映射到附近的向量空间。这就像学习一门语言,你不需要字典,只需要大量阅读,就能从上下文推断词义。
Q2: 词向量的维度如何选择?越大越好吗?
A: 不是。维度太小(如 50)表达能力不足,无法区分细致的语义差异;维度太大(如 500)会过拟合,模型记住训练数据的噪声而不是真正的语义模式。实践中:
- 通用场景: 100-150 维足够,性价比最高
- 大规模语料: 200-300 维,可以捕捉更细致的语义
- 小数据集: 50-100 维,避免过拟合
- 下游任务微调:用交叉验证选择最佳维度
一个经验法则:当增加维度不再显著提升下游任务性能时,就到达了最佳点。
Q3: Skip-gram 和 CBOW 到底哪个好?什么时候用哪个?
A: 没有绝对答案,取决于数据和目标:
Skip-gram 优势:
- 大数据集上性能更好(充分的训练样本)
- 对低频词学习更充分(每个词有多个训练样本)
- 更擅长捕捉细致的语义关系
CBOW 优势:
- 小数据集上训练更快(样本利用效率高)
- 对高频词和语法信息学习更好
- 计算开销小(上下文词一次性处理)
推荐策略:默认使用 Skip-gram + 负采样,除非数据量很小(<1000 万词)或算力受限。
Q4: 负采样的负样本数量 K 应该设多少?
A: 看数据规模:
- 小数据集(<1 亿词):
,需要更多负样本来提供足够的对比信号 - 大数据集(>1 亿词):
,大量训练样本已经提供充足的梯度估计 - 极大数据集(>10 亿词):
足够
原则:数据越多,负样本越少;数据越少,负样本越多。但
Q5: 词向量能处理多义词吗?"bank"(银行/河岸)怎么办?
A: 传统词向量( Word2Vec/GloVe/FastText)不能区分多义词,"bank"只有一个向量,是所有义项的混合。这是它们的根本局限。
解决方案:
上下文化词向量: ELMo 、 BERT 等模型为每个词在特定句子中生成动态向量。"I went to the bank"和"The river bank"中的"bank"会得到不同的向量。
多原型词向量:为每个词学习多个向量(每个义项一个),如 Huang et al. (2012)的聚类方法。但需要确定义项数量,实践中较少使用。
实用建议:如果多义词是关键问题,直接用 BERT 等预训练模型;如果只是辅助特征,静态词向量足够。
Q6: FastText 对中文有用吗?
A: 效果有限。 FastText 为拼音文字(英语、德语、土耳其语)设计,利用字符 n-gram 捕捉形态信息。但中文是表意文字:
- 字符级 n-gram 无意义:"学习"拆成"学"和"习"还算有意义,但拆成笔画或部首 n-gram 就完全失去信息。
- 词级或字级更合适:对中文用词作为基本单位(需要分词),或用字(天然分隔)。
中文 FastText 改进:
- 用部首、笔画数等特征代替字符 n-gram
- 用词内部的字组合(如"学习"→"学"+"习"+"学习")
- 直接用字向量组合( BERT 等模型的做法)
实践中,对中文通常直接用基于字的模型或 BERT,效果优于强行套用 FastText 。
Q7: 如何判断训练的词向量质量好不好?
A: 多角度评估:
内在评估:
- 词类比任务: Google analogies dataset,测试"king - man + woman = queen"类推理,准确率越高越好
- 词相似度任务: WordSim-353 等数据集,计算模型预测与人工标注的相关系数
- 可视化检查: t-SNE 降维,看相似词是否聚类,反义词关系是否合理
外在评估(最重要):
- 将词向量用于下游任务(文本分类、命名实体识别等),看性能是否提升
- A/B 测试:与其他词向量或基线比较
常见问题排查:
- 如果高频词相似度好,但低频词很差 → 增加训练轮数或使用 Skip-gram
- 如果词类比任务差 → 增大窗口大小或向量维度
- 如果所有词都挤在一起 → 语料太小或训练不足
Q8: 为什么训练好的词向量需要归一化?
A: 并非必须,但有几个好处:
加速相似度计算:归一化后余弦相似度变成简单的内积
稳定数值:避免向量模长过大或过小导致的数值问题。
公平比较:高频词训练更多,向量模长可能更大。归一化消除这种偏差,让相似度只反映方向而非模长。
实现:
1 | # gensim 自动归一化 |
注意:如果用向量做特征输入到神经网络,不一定要归一化(网络会学习合适的缩放)。
Q9: 预训练词向量在特定领域(如医学)上效果不好,怎么办?
A: 通用语料(如 Wikipedia)训练的词向量在专业领域表现差,因为:
- 专业词汇可能不在词汇表( OOV)
- 词的分布和共现模式不同("cell"在生物学和电子学中语义不同)
解决方案:
领域语料微调:
1 | # 加载预训练模型 |
从头训练:如果有大量领域语料(>1 亿词),从头训练可能更好。
混合特征:同时使用通用词向量(捕捉基本语义)和领域词向量(捕捉专业知识)。
迁移到 BERT:用领域语料微调 BERT,效果通常优于静态词向量。
Q10: 词向量能捕捉情感吗?如何评估情感极性?
A: 部分可以,但不完美。词向量从上下文学习,"好"和"坏"可能因为都出现在评价场景中而相似("这个电影很好/坏")。
情感评估方法:
手动检查:
1 | # 查找"excellent"的相似词 |
情感词典对比:
加载情感词典(如 AFINN),计算同极性词的平均相似度是否高于异极性词。
分类任务测试:
在情感分类任务上评估,如 IMDB 影评分类。如果词向量有区分度,分类器性能会更好。
专用情感词向量:
用情感分类语料训练(如推特表情符号作为标签),或在目标函数中加入情感约束。
实践:对于情感分析任务,通常需要在通用词向量基础上微调,或直接用情感标注数据训练任务特定模型。
词向量是 NLP 从符号处理到深度学习转型的关键。从 Word2Vec 的简洁高效,到 GloVe 的全局视野,再到 FastText 的子词建模,每一步都在拓展我们对语言表示的理解。虽然如今更强大的上下文化模型( BERT 、 GPT)占据了主流,但词向量仍是理解现代 NLP 的基础,也是许多应用中简洁而有效的选择。
掌握词向量,你不仅学会了一项技术,更重要的是理解了如何让机器从数据中自动学习知识的范式——这正是深度学习的核心哲学。希望这篇文章能帮你打开通往 NLP 世界的大门。
- 本文标题:自然语言处理(二)—— 词向量与语言模型
- 本文作者:Chen Kai
- 创建时间:2024-02-08 14:30:00
- 本文链接:https://www.chenk.top/%E8%87%AA%E7%84%B6%E8%AF%AD%E8%A8%80%E5%A4%84%E7%90%86%EF%BC%88%E4%BA%8C%EF%BC%89%E2%80%94%E2%80%94-%E8%AF%8D%E5%90%91%E9%87%8F%E4%B8%8E%E8%AF%AD%E8%A8%80%E6%A8%A1%E5%9E%8B/
- 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!