Skip to content
L2 里面是什么

嵌入:意思相近的词在数字上也相近

「国王」和「女王」坐标只差一小段,和「拖拉机」差得远。

像在地图上找方位 ​

嵌入(embedding,也叫嵌入向量)——把词变成一串数字,让意思接近的词在数字上也接近。

还是那个地图的比方。给每个词标一个经纬度。给「北京」标在北边,「上海」标在稍南一点,「广州」更南。差得都不远,因为它们都是城市。给「拖拉机」标在另一个半球,那离「北京」就远了。

模型内部用的就是这个思路,只不过每个词不是两个数,是几百个、几千个数堆在一起。维度多,是为了能把语法关系、感情色彩、语体这些一起塞进去。

关键在于:这个坐标不是人定的,是从一堆文本里自己长出来的。

它是怎么长出来的 ​

训练任务说白了就一句话:让模型猜。给它一句话,把中间某个词盖住,让它填。填错就调参数(parameter,模型训练时被调的数字),反复几百万次。

几百万次之后,「猫」和「狗」的坐标自动挤到了相邻位置。为什么?因为语料里这两个词出现的上下文高度重合——「猫吃鱼」「狗吃骨头」,但出现它们的场合都是「家里有活物」。模型学到的不是字典定义,是「什么词会跟它一起出现」。

这个思路 2013 年被 Tomas Mikolov 那拨人推到极致。论文里最扎眼的一句是:在 16 亿词的语料上训练出高质量词向量,花了不到一天。他们把 word2vec 这个词留在了所有人的词汇表里。

向量能做算术 ​

这是嵌入最让人吃惊的地方,也是它至今没被取代的原因。

「国王」减去「男人」,加上「女人」,结果非常接近「女王」。不是差不多,是非常接近。

同样的式子还有:

  • 北京 − 中国 + 法国 ≈ 巴黎
  • 上 − 下 ≈ 大 − 小

我自己第一次在教程里看到这个演示时的反应是:不可能。然后我拿 gensim 加载了一版权威的中文词向量,敲了那行代码。真就挺像的。

不过这话得说完整:这类「向量算术」在数学上不是恒等式,只是经验上常常成立。相似度高的词里也有反例,词频差异大的时候偏差更明显。所以「AI 真的懂了」这个说法,我认为站不住——它算得很准,但它算的是什么,说不清楚。

现在的模型已经不这么查表了 ​

早期做法是把每个词映射到一个固定向量,查表取出来。这套叫静态嵌入——「苹果」的向量永远是那一个,不管它前面是「吃」还是「发布」。

现在的做法是动态的:同一个词在不同的句子里拿到不同的向量,由上一节的注意力机制现场算出来。这叫上下文嵌入。上面那个算术之所以还能玩,是因为算术的原料往往就是上下文嵌入。

所以「嵌入」这个词现在指的东西挺杂。读论文时如果看到「embedding layer」,一般是指最前面那层查表;看到「embedding」泛指,就是指整个向量空间。

延伸阅读 ​

  • Efficient Estimation of Word Representations in Vector Space(Tomáš Mikolov、Kai Chen、Greg Corrado et al.,2013,arXiv 预印本)—— word2vec 那一篇。提了两套模型:一个看上下文猜中心词(CBOW),一个看中心词猜上下文(Skip-gram)。真正的贡献是证明了在 16 亿词的规模上,一天之内就能训出好词向量,成本低到让所有人做得起。arXiv: 1301.3781

  • Glove: Global Vectors for Word Representation(Jeffrey Pennington、Richard Socher、Christopher D. Manning,2014,EMNLP)—— Stanford 三个人写的,指出了前面那篇没解释清楚的事:词向量里那些漂亮的关系到底是怎么冒出来的。他们把「全局矩阵分解」和「局部上下文窗口」两派合起来,用一个加权最小二乘目标让词共现的概率直接决定向量的距离。DOI: 10.3115/v1/d14-1162

动手试试 ​

这个真能跑,五分钟:

bash
pip install gensim

下载现成的中文词向量(Tencent_Ai_Lab_Embedding 或 sgns.wordvectors.300w 都在公开下载处,几百兆),然后:

python
from gensim.models import KeyedVectors
kv = KeyedVectors.load_word2vec_format("path/to/tencent.vec", binary=False)
for a, b, c in [("国王", "男人", "女人"), ("北京", "中国", "法国")]:
    print(a, "-", b, "+", c, "≈", kv.most_similar([c], positive=[a], negative=[b], topn=1)[0][0])

看输出里第一条是不是「女王」。不是也别急,换几个词对再试。我第一次试的时候「国王-男人+女人」给出的是「王子」,愣了半天。

下一站 ​

向量有了,注意力有了,结构也有了。可里面每一个数字现在都还是随机值。是谁、拿什么、在多久的时间里,把这些数字调成了现在这副样子。

内容用 VitePress 构建,站内链接全部为相对路径。