词嵌入#
术语解释#
词嵌入(Embedding),又叫嵌入向量说白了就一句话:把「没法直接比较的东西」变成一串数字,并让这串数字之间的距离,能代表语义上的远近。
计算机不认识“猫”这个字,它只认识数字。最早的办法是独热编码(one-hot encoding):假设词表里有 5,000 个词,就给每个词配一个 5,000 维的向量,只有它自己那个位置上是 1,其余全是 0。
$$ [0,0,0,1,0,0,0,\cdots,0,0,0,0,0,0,0,0,0] $$但是这套编码有两个硬伤:
维度太高:5,000 个词就是 5,000 维,词表再大还得继续翻倍。
没有语义:在独热编码里,“猫”和“狗”之间的距离,跟“猫”和“汽车”之间的距离完全一样, 因为谁跟谁都不挨着谁。向量里的数字只说清楚了“它是谁”,但没有说明“它像谁”。
嵌入换了个思路:它不给每个词发一个专属编号,而是给每个词学一个几百维的稠密实数向量,训练目标就一条: 让上下文里经常一起出现的词,在向量空间里也靠得近。训完之后,“猫”和“狗”的向量挨得很近,“猫”和“汽车”离得很远。没人显式告诉过模型「猫和狗都是宠物」,它是从大量文本里自己把这层关系学出来的。

当然,嵌入也不只是词的专利,任何只要能变成向量的东西都能嵌入:句子、图片、音频、用户、商品、代码片段。

这里有一点需要注意,嵌入向量的单个维度基本读不出含义 (这类似于图片像素一样),你能看懂坐标轴的意思,但没法说「第 3 维就是 XX」。有意义的是向量整体所在的位置,以及它跟别的向量之间的距离。
相似度计算#
现在你手上有任意两个样本的嵌入向量了。要比较它们像不像,就需要一个相似度度量(similarity measure),把两个向量变成一个数字。
因为嵌入向量就是一串数字,所以相似度度量本质上是「两个向量之间的关系」。
进一步,设两个向量为 $A = [a_1, a_2, \dots, a_n]$ 和 $B = [b_1, b_2, \dots, b_n]$,下面是 3 种常见的相似度度量方法。
| 度量 | 含义 | 公式 | 相似度越高,值 |
|---|---|---|---|
| 欧氏距离(Euclidean distance) | 两个向量末端的直线距离 | $\sqrt{(a_1-b_1)^2+(a_2-b_2)^2+\dots+(a_n-b_n)^2}$ | 越小 |
| 余弦相似度(Cosine similarity) | 两向量夹角 $\theta$ 的余弦 | $\frac{a^{T}b}{\lVert a\rVert \cdot \lVert b\rVert}$ | 越大 |
| 点积(Dot product) | 余弦再乘上两个向量各自的长度 | $a_1b_1+a_2b_2+\dots+a_nb_n = \lVert a\rVert\lVert b\rVert\cos(\theta)$ | 越大,而且会随向量变长而变大 |
最直白的记法:
欧氏距离量的是“离得有多远”,如果两个点几乎重合,它们的距离就趋近于 0。
余弦相似度量的是“方向差多少”,它完全不看长度,一个长向量和一个短向量,只要方向一致,它们之间的距离就算 1。
点积等于“方向差多少”乘上“两个向量各有多长”,此时既看方向也看长度。
相似度度量选择#
与余弦不同的是,点积在计算时与向量长度成正比,而这一点很重要。因为在训练集中出现频率非常高的实体(例如热门的 YouTube 视频)往往具有长度较大的嵌入向量。 如果你想抓住热门趋势,那就可以选择点积作为相似度指标。
不过,这样做有一个风险,那就是热门实体可能会导致相似性指标出现偏差。 为了平衡这种偏差可以将向量长度乘以一个幂次 $\alpha<1$,最终计算的点积就变成了 $\lVert a\rVert^{\alpha}\lVert b\rVert^{\alpha}\cos(\theta)$,此时,幂次越小,长度的影响就被压得越低,也就越接近纯余弦 [1]。
当然,如果把每个向量的长度都归一化到 1 ,那么这三种度量就都跟 $\cos(\theta_{ab})$ 成正比了。
设 $\lVert a\rVert = 1$ 且 $\lVert b\rVert = 1$:
欧氏距离 = $\lVert a-b\rVert = \sqrt{\lVert a\rVert^2+\lVert b\rVert^2-2a^{T}b} = \sqrt{2-2\cos(\theta_{ab})}$
点积 = $\lVert a\rVert\lVert b\rVert\cos(\theta_{ab}) = 1 \cdot 1 \cdot \cos(\theta_{ab}) = \cos(\theta_{ab})$
余弦 = $\cos(\theta_{ab})$
所以三者本质上是等价的,区别只在“相似度”这个数字的刻度不一样。
这也解释了一个常见做法:很多 Embedding 模型在输出向量前会先做一次 L2 归一化操作,因为一旦归一化,点积就等于余弦相似度,算起来还更快。
相关术语#
引用#
[1] https://developers.google.com/machine-learning/clustering/dnn-clustering/supervised-similarity