想象一座小镇,每个词都是镇上的居民。Word2Vec 要做的第一件事,就是给每位居民发一张地图坐标:意思相近的词,坐标自然也靠得近。以前计算机只看得懂 one-hot 这种“门牌号”——全镇几万人里只把一个人对应的灯点亮,看不出任何人际关系;而词向量把每位居民的位置画成几十上百个数字组成的稠密坐标,让“王”和“国王”这样的词住进相邻街区。训练坐标有两种问路方式:CBOW 是看到一群人围在一起,猜圆心是谁;Skip-gram 是看到一个居民,猜他平时会和谁一起出现。为了避免每次都跑遍全镇,训练时可以用负采样只抽查几个路人,或用层次 Softmax 沿门牌树逐层搜索。学完这张地图后,还能玩出神奇操作:国王的坐标减去男人加上女人,落点刚好靠近女王。正是这个“给词发坐标”的想法,开启了现代词嵌入时代。
掌握 Word2Vec,等于拿到 NLP 从符号走向语义的第一把钥匙。理解词向量、训练目标与加速技巧,能为后续一切语言模型打下最直观的底座。
可视化演示
展示系统处理流水线、实时性能指标曲线及多方案对比分析,包含数据流转、吞吐延迟监控与方案评估。
本节配有交互动效(进入视口后自动加载,约 3KB)。
系统可视化 处理流程:输入→处理→模型→输出 性能监控:实时指标 P=L×T
词嵌入直觉
小镇居民如果只用门牌号互相称呼,那计算机看到的就是 one-hot:一个巨大向量里只有一位是 1,其余全是 0。这种表示像消防队的点名册——每个人都有唯一编号,但编号之间没有任何关系,“苹果”和“香蕉”都是两个离得很远的数字,计算机完全不知道它们都是水果。词嵌入要做的,是给每个词发一张真正的经纬度坐标:几个连续的实数,把“水果”们放进同一片街区,把“电器”们放进另一片街区。
技术上,词嵌入就是一张查找表:词表里有多少个词,就有多少行;每一行是一个低维稠密向量。维度通常只有几百,远小于词表大小,却能承载丰富的语义。训练这张表时,模型不断调整每个词的坐标,让语境相似的词越靠越近。这张表就是词向量矩阵,也是整座小镇的活地图。
回到小镇的比喻,门牌号只能用来找人,坐标却能用来认路:有了词向量,“水果”这个词不再孤立,而是天然站在“苹果”“香蕉”旁边。
- E 表示词向量矩阵它是整座小镇的门牌册,每一行记录一个居民的坐标。
- |V| 表示词表大小小镇居民总数,也是矩阵的行数。
- d 表示向量维度每个居民坐标的维数,通常远小于词表大小。
- 实数稠密向量每个格子里都是连续实数,不再是 0/1 门牌号。
分布式假设
你没见过某个小镇居民,但只要听说他常出现在书店、咖啡馆和图书馆,你就能猜到他多半爱读书。语言学里的分布式假设也是这个道理:一个词的意义,由它经常出现的上下文决定。Firth 那句名言“You shall know a word by the company it keeps”,说的就是“观其友,知其人”。
Word2Vec 把这个洞见变成了可计算的模型。最简单的理解方式是统计共现:如果两个词经常出现在同样的语境里,它们就是“邻居”,语义也相近。比如“高兴”和“开心”都常出现在“今天很____”后面,所以它们的语境画像高度重合。Word2Vec 不用真的数完全部共现次数,而是让神经网络去预测上下文,从而隐式逼近这种分布。
所以分布式假设是整座小镇的社交定律:想认识一个词,就去看看它和谁混在一起。CBOW 和 Skip-gram 都是在这个定律下设计的具体“问路方式”。
- C(w, ctx) 表示共现次数词 w 和这个语境一起出现的次数,像两个居民被看到同框的频率。
- 分母是归一化总和把同语境下所有词的共现次数加起来,让概率之和等于 1。
- P(w|ctx) 是条件概率给定语境后出现 w 的可能性。
- 模型要逼近它Word2Vec 用预测任务代替统计计数,本质上是学同一份“谁和谁常在一起”的社交关系。
CBOW模型
CBOW 全称 Continuous Bag-of-Words,可以想象成广场上围着一圈人,模型要猜圆心站的是谁。它输入的是窗口内上下文词的向量,先把它们平均成一个整体信号,再预测中心词。因为上下文词被当成一个“词袋”,顺序被打乱也无所谓,所以叫 Bag-of-Words。
训练时,模型不断调整坐标,让真实中心词在 softmax 打分中拿到最高概率。CBOW 的一个窗口只做一次预测,计算量小,训练速度快,对高频词特别友好;缺点是过于平滑,对生僻词的区分度不如 Skip-gram。它适合语料规模不大、希望快速得到稳定向量的场景。
用小镇的话说,CBOW 是“看到一群人,猜谁站在中央”。只要经常出现在同一群人中间,大家的坐标就会被拉得越来越近。
- h_t 是上下文平均向量把窗口内每个词的坐标相加取平均,得到“这群人共同指向的位置”。
- 分子是真实中心词的打分用中心词 w_t 的输出向量和 h_t 做内积,再取指数,相当于问“它站在圆心有多合理”。
- 分母是全词表归一化对词表所有词做同样的指数打分并求和,把分数变成概率。
- 训练目标让真实中心词的概率尽量大,也就是让这一圈人的公共印象越来越准。
Skip-gram模型
Skip-gram 的思路正好反过来:你在大街上遇见一个居民,要猜他平时会和哪些人一起出现。给定中心词,模型会独立预测窗口内的每一个上下文词,而不是只看一个平均结果。这意味着每个中心词会多次参与梯度更新,每次更新都针对它和一个具体上下文词的关系。
这个特性让 Skip-gram 对生僻词更友好:一个冷门词只要出现一次,就会带动多个上下文词的预测,得到远比 CBOW 更多的训练信号。代价是计算量更大,训练速度稍慢。它适合语料规模大、需要敏锐捕捉细粒度语义关系的场景。
Skip-gram 像是一位社交达人:每认识一个新朋友,都要根据这个人的性格推断他的朋友圈。朋友猜得越准,整个小镇的坐标体系就越可靠。
- 外层求和遍历所有位置t 从 1 到 T,相当于走遍语料里每个词。
- 内层求和遍历窗口j 取 -c 到 c 且不为 0,代表中心词左边右边各 c 个邻居。
- 分子是中心词和上下文词的匹配度两者向量内积越大,说明它们越“合拍”。
- 分母做全词表归一化把匹配度变成概率,再取对数求和,最终得到整个语料的训练目标。
负采样
每训练一步都做全词表 softmax,相当于每次都要敲遍全镇每一户人家的门,问“你认识中心词吗?”词表一大,计算量就爆炸。负采样把这件事改成了抽查:保留真实出现过的上下文词作为正样本,再从词表里随机抽 k 个和当前语境无关的词作为负样本,只对这几个人做二分类。
二分类的目标很简单:正样本要判断为“真的在一起”,负样本要判断为“不在一起”。于是原来的多分类问题被拆成几个轻量问题,每个训练步只更新少量向量,速度大幅提升。负采样并不会丢弃有用的正样本,而是用“反例”帮模型更快划清边界。
负采样就像餐厅品控人员:不必尝遍菜单上所有菜,只需要随机抽查几道本不该出现的菜和一道真实菜品做对比,就能快速判断厨师手艺。
- 正样本项w_O 是真实上下文词,让它的内积经过 sigmoid 后接近 1。
- 负样本项w_i 是随机抽出的负例,加上负号后希望它接近 0。
- sigmoid 函数把任意实数压缩到 0 和 1 之间,正好当二分类概率。
- 整体目标最大化正样本概率、最小化负样本概率,等价于“认出熟人、拒绝陌生人”。
层次Softmax
另一种加速思路是给小镇建一棵“门牌树”。Word2Vec 用词频构造一棵霍夫曼树:高频词挂在靠近根节点的位置,低频词沉在较深的分支。要计算某个词的概率,不需要遍历整张词表,只需要从树根出发,沿着路径逐层做出“向左还是向右”的判断,每个内部节点就是一个二分类器。
因为每个词的路径长度大约等于词表的对数,所以计算复杂度从 O(|V|) 降到了 O(log |V|)。高频词路径更短,训练时更快被更新;低频词虽然路径长一点,但依然比全词表 softmax 便宜得多。
层次 Softmax 像是一座按姓氏分层的大楼:你要找的人住在哪一层,先看姓氏首字母,再看第二个字母,逐层缩小范围,不必一层层敲遍所有房门。
- path(w) 是树上路径从根节点到词 w 叶子节点经过的所有内部节点。
- θ_n 是节点向量每个岔口都有一个可学习向量,相当于路口接待员。
- dir(n) 表示转向+1 表示向左,-1 表示向右,让 sigmoid 输出对应的方向概率。
- 路径概率连乘把每个岔口的判断概率乘起来,就得到这个词的条件概率。
词向量性质
训练完成后,小镇地图会出现一个惊人规律:语义关系变成了向量空间里的平移。国王到女王的移动方向,和男人到女人的移动方向几乎平行;移动男人到女人的距离,再叠加到国王身上,就会落在女王附近。这意味着词向量不仅知道“谁和谁住得近”,还把“男性—女性”“国王—女王”这类关系编码成了方向。
这种性质让词向量可以做算术:v(国王) − v(男人) + v(女人) ≈ v(女王)。实际应用中,两个词向量的余弦相似度被广泛用来衡量语义距离,值越接近 1,表示方向越一致、语义越相近。
小镇地图不再只是静态照片,而是一张可以导航的活地图:只要知道了“男人→女人”这条路,就能从“国王”一路导航到“女王”。
- v(king) 是国王坐标在语义地图上代表“国王”这个位置。
- 减去 v(man)去掉“男性”这个方向的分量。
- 加上 v(woman)补上“女性”方向的分量。
- 结果近似 v(queen)整个运算的落点接近“女王”的坐标。
词嵌入影响
Word2Vec 之后,词向量不再只是一个算法,而成了 NLP 世界的基础设施。预训练词向量可以在大规模无标注语料上先学出通用语义,再迁移到机器翻译、文本分类、情感分析等下游任务。对于标注数据稀少的场景,词向量就像一座现成的城市地图,让模型一出生就认识路,不用从零摸索。
后来的 GloVe、ELMo、BERT 等模型虽然换用了更复杂的表示方式,但底层依然继承了“用稠密向量表示词义”的核心理念。Word2Vec 的贡献在于证明了:不需要人工规则,只需要大规模文本,机器就能自己学到语义坐标。
用小镇的尺度来看,Word2Vec 不只是画了一张地图,还顺手修好了全镇的交通系统。后来的人只需在这张地图上盖楼,而不必担心居民根本找不到自己的家。
- E 是词向量查找表像一本联排别墅的门牌册,每一页是一个词。
- 每行是一个词的向量第一行是 w_1 的坐标,第二行是 w_2 的坐标。
- 行数等于词表大小词表有多少个词,矩阵就有多少行。
- 作为下游输入查表得到向量后,可以接 LSTM、CNN、Transformer,成为模型的底座。
AI 应用场景
电商搜索语义召回
阶段:召回与查询理解
解决的问题:传统搜索引擎靠字面匹配,用户搜“连衣裙”时,无法召回标题里写“one-piece”或“裙子”的商品。字面不同但语义相同的 query 和商品会被硬生生隔开。
具体案例:某电商平台把用户点击日志作为训练语料,用 Skip-gram 学习 query 词和商品标题词的向量。线上召回时,把用户 query 的向量与百万商品标题向量做余弦相似度计算,取 Top-K 进入排序阶段。结果“小红裙”和“红色连衣裙”被召回到同一结果流,搜索转化率明显提升。
智能客服意图识别
阶段:特征提取与文本分类
解决的问题:“我要退钱”和“申请退款”字面差异很大,传统 TF-IDF 特征下两者几乎没有交集,导致客服机器人分不清用户意图。
具体案例:先用大量客服对话语料训练 Word2Vec 词向量,再把用户句子中每个词的向量取平均作为句子特征,输入一个轻量分类器。模型能识别“退钱”“退款”“退单”都是退款意图,拦截率提升的同时,转人工率下降约两成。
新闻主题聚类
阶段:文本表示与无监督聚类
解决的问题:新闻每天新增成千上万条,人工打标签成本高;传统词频向量高维稀疏,聚类结果碎片化。
具体案例:训练好词向量后,把每篇新闻的所有词向量取平均得到新闻向量,再做 KMeans 聚类。财经、体育、科技类新闻自动分成不同簇,即使标题里用了“总决赛”“夺冠”“争冠”等不同词,也能因为语义相近而聚在一起。
Python 演示
# 极简版 Skip-gram: 用小语料学习词向量import numpy as npfrom collections import Counter corpus = [ ["king", "is", "a", "man"], ["queen", "is", "a", "woman"], ["man", "loves", "woman"], ["king", "loves", "queen"],] def build_vocab(): counter = Counter() for sentence in corpus: counter.update(sentence) vocab = [w for w, _ in counter.most_common()] word2idx = {w: i for i, w in enumerate(vocab)} return vocab, word2idx vocab, word2idx = build_vocab()V = len(vocab)D = 4np.random.seed(0)W_in = np.random.uniform(-0.5, 0.5, (V, D))W_out = np.random.uniform(-0.5, 0.5, (D, V)) def train_skipgram(center_idx, context_idx, lr=0.1): h = W_in[center_idx] scores = h @ W_out logits = scores - scores.max() exp_logits = np.exp(logits) probs = exp_logits / exp_logits.sum() grad = probs.copy() grad[context_idx] -= 1 W_out[:, :] -= lr * np.outer(h, grad) W_in[center_idx, :] -= lr * W_out @ grad for epoch in range(300): for sentence in corpus: for i, center in enumerate(sentence): left = sentence[max(0, i - 1): i] right = sentence[i + 1: i + 2] for context in left + right: train_skipgram(word2idx[center], word2idx[context]) def closest(h): scores = W_out.T @ h return vocab[int(np.argmax(scores))] analogy = W_in[word2idx["king"]] - W_in[word2idx["man"]] + W_in[word2idx["woman"]]print("king - man + woman =>", closest(analogy))
h = W_in[center_idx]取出中心词的稠密向量,作为“当前镇民坐标”。scores = h @ W_out用中心词坐标对词表里所有词打分。probs = exp_logits / exp_logits.sum()softmax 将分数转成概率。grad[context_idx] -= 1正确上下文词应概率为 1,这里记录误差。W_out[:, :] -= lr * np.outer(h, grad)更新输出矩阵,让打分更接近真实。W_in[center_idx, :] -= lr * W_out @ grad把误差传回中心词向量,更新它的坐标。analogy = ...向量加减实现 king-man+woman 的语义类比。
常见误区
误区它明明有输入层、隐藏层、输出层,还有反向传播,所以它是深度神经网络。
正解Word2Vec 是浅层模型,中间只有一层没有激活函数的投影层,本质是一次查表和平均;反向传播不等于深度。用小镇比喻,它只是给居民发坐标的登记处,不是需要多层审批的市政大楼。深度模型的关键是隐藏层数量多,而 Word2Vec 的隐藏层几乎没有非线性变换。
为何常见:看到“神经网络”“反向传播”这些词,就默认和深度学习划等号。
误区CBOW 用上下文预测中心词,Skip-gram 用中心词预测上下文,方向反过来,训练结果应该相同。
正解两者数据组织方式不同。CBOW 把一个窗口的上下文合并成一次预测,训练快、对高频词平稳;Skip-gram 让每个中心词独立预测多个上下文词,一个词出现一次就能得到多次梯度,因此对生僻词更友好。就像同样的镇子,CBOW 是围着一群人猜圆心,Skip-gram 是见到一个人猜他常去的店铺,得到的街区印象并不一样。
为何常见:只看到输入输出互换,忽略了每个词参与训练的次数和梯度更新方式差异。
误区负采样就是训练时把一些不重要的词丢掉,只保留正样本,让数据量变小。
正解负采样没有丢正样本,而是从词表中随机抽几个与当前语境无关的词作为“负例”,让模型学会区分“真的在一起”和“碰巧没在一起”。它把多分类 softmax 变成几个二分类,因此不用对全词表归一化。好比餐厅做菜品检验,不用尝遍所有菜,只需抽查几道不该出现的菜和一道真实菜品对比。
为何常见:“负”字让人误以为是被丢弃的样本,其实是额外引入的反向样例。
误区如果两个词的向量距离很近,它们就一定可以互相替换,是同义词。
正解距离近只说明它们经常出现在相似语境中,反义词也常出现在相似语境,比如“开心”和“难过”都会出现在“今天我很____”的句子里。词向量更像“住同一条街的邻居”,邻居不见得性格相同,只是生活习惯相似。
为何常见:把语义相似和分布相似混为一谈,忽略了“平行但相反”的语境共现关系。
面试题
Q1. Word2Vec 中“分布式假设”指的是什么?
- A.词语在句子中随机出现
- B.语境相似的词意义相近← 正确答案
- C.所有词共享同一个向量
- D.高频词排列在词表前部
答案:B。分布式假设的核心是“观其友,知其人”:一个词的意义由它经常出现的上下文决定,所以语境相似的词语义也相近。A 与假设无关,C 与词向量思想相反,D 是对词频排序的误解。
Q2. 下列哪项是 CBOW 的输入输出关系?
- A.中心词预测上下文词
- B.上下文词预测中心词← 正确答案
- C.全句词汇预测中心词
- D.中心词预测全句词汇
答案:B。CBOW 是 Continuous Bag-of-Words,输入窗口内的上下文词,输出中心词。A 是 Skip-gram,C 和 D 扩大或歪曲了窗口范围。记忆口诀:CBOW 猜圆心,Skip-gram 猜朋友圈。
Q3. 负采样每次训练会更新哪些权重?
- A.正样本和多个负样本对应向量← 正确答案
- B.词表中所有词向量一起更新
- C.只更新中心词对应的向量
- D.只更新上下文词对应的向量
答案:A。负采样只选一个正样本和 k 个随机负样本参与二分类,因此只更新这些样本对应的向量。B 是全词表 softmax 的做法,C 和 D 漏掉了另一侧需要更新的向量。
Q4. 层次 Softmax 的核心加速原理是什么?
- A.用霍夫曼树的路径代替全词表← 正确答案
- B.只计算高频词的条件概率
- C.丢弃生僻词对应的损失项
- D.用矩阵分解近似所有概率
答案:A。层次 Softmax 把词表组织成霍夫曼树,每个词的概率由根到叶子的路径上多个二分类器连乘得到,复杂度从 O(|V|) 降到 O(log|V|)。B、C 会丢失信息,D 是矩阵分解类方法的思想。
Q5. 词向量运算 v(国王) − v(男人) + v(女人) 的结果最接近?
- A.v(女王)← 正确答案
- B.v(王子)
- C.v(贵族)
- D.v(国王)
答案:A。词向量的类比性质让国王减去男人再加女人后,落点靠近女王。原因是“男人→女人”的性别方向被叠加到了国王身上,其他选项不满足这个线性关系。
Q6. Skip-gram 对生僻词更友好的主要原因是什么?
- A.中心词独立产生多组上下文预测← 正确答案
- B.每个词的输入窗口可以任意扩大
- C.损失函数自带平滑正则项
- D.输出层使用更加稀疏的梯度
答案:A。Skip-gram 每看到一个中心词,就会对窗口内每个上下文词分别做一次预测,生僻词出现一次也能获得多次梯度更新,因此学得更充分。B 是窗口设置问题,C、D 都不是 Skip-gram 特有的机制。
Q7. 把 one-hot 向量变成低维稠密向量的过程叫什么?
- A.词嵌入← 正确答案
- B.词频统计
- C.句法分析
- D.主题建模
答案:A。词嵌入(Word Embedding)就是把稀疏的 one-hot 表示映射成低维稠密向量的过程。B 只统计次数,C 研究语法结构,D 是另一种文档表示方法。
Q8. 训练 Word2Vec 常用的加速方法有哪些?
- A.负采样法← 正确答案
- B.霍夫曼树← 正确答案
- C.归一化法
- D.卷积池化
答案:AB。负采样用随机负例做二分类,霍夫曼树对应层次 Softmax,二者都避免了全词表 softmax 的巨额计算。归一化只是 softmax 的一步,卷积池化属于 CNN,不是 Word2Vec 的加速技巧。
Q9. 关于 Word2Vec 生成词向量的性质,下列说法正确的有?
- A.语义相近词向量距离接近← 正确答案
- B.类比关系近似线性运算← 正确答案
- C.向量维度大于词表大小
- D.向量保持稀疏编码特征
答案:AB。词向量让语义相近的词距离接近,也支持 king-man+woman 这类线性类比。向量维度通常远小于词表大小,而且稠密而非稀疏,所以 C、D 错误。
Q10. 下列哪些说法正确反映了 Word2Vec 的局限或应用?
- A.无法解决一词多义← 正确答案
- B.向量可作预训练特征← 正确答案
- C.训练不需人工标注← 正确答案
- D.可完全替代语言模型
答案:ABC。每个词只有一个固定向量,所以“苹果”的水果义和公司义会混在一起,A 正确;词向量可作为下游模型输入特征,B 正确;训练只需大规模无标注文本,通过预测任务自监督完成,C 正确;D 夸大了 Word2Vec 的能力,它只是表示学习模型,不是生成式语言模型。