Embedding 到底是什么?

Embedding 到底是什么?从词向量到语义向量
你有没有想过,当你对 Siri 说"今天天气怎么样"的时候,它是怎么"听懂"你的?
计算机只认识 0 和 1。它不像我们人脑,能瞬间理解"天气"两个字背后是温度、湿度、要不要带伞。而 Embedding,就是解决这个问题的关键。
简单说,Embedding 就是把人类语言"翻译"成数字的语言。翻译成什么?数字向量。
这篇文章,我们从头讲起。
为什么计算机"看不懂"语言?
要理解 Embedding,先得知道计算机以前是怎么"处理"文字的。
最直接的办法叫 One-Hot 编码。想象你有一本字典,收录了 1 万个字。怎么让计算机认识它们?
给每个字分配一个位置。
"天"在第 1 位,"气"在第 2 位,"怎"在第 3 位……然后把这个字变成一串数字。哪个位置是它,哪个位置就是 1,其他全是 0。
比如"天气"这个词,在 One-Hot 的世界里大概长这样:
天气 = [0, 0, 1, 0, 0, 0, ... 0, 0] # 只有第3位是1,其他9997位全是0问题来了。
这串数字能告诉你"天气"是什么意思吗?完全不能。
它只知道这是第 3 个词,别的什么都读不出来。"猫"和"狗"跟"天气"的距离,跟它们跟"飞船"的距离是一模一样的——因为都是"差了 9999 个位置"。
这就是 维度灾难 的问题。1 万个字,就是 1 万维。每个字都要占 1 万个格子,99.99% 都是 0。
浪费不浪费?太浪费了。
更严重的问题是:这种编码完全无法表达词和词之间的关系。

Embedding 的本质——一个神奇的"翻译词典"
能不能换一种方式?
能不能让每个词用一个更短、更"有料"的向量来表示?不是 0 和 1,而是一些有意义的数字?
Embedding 本质上就是一个查询表。你给我一个词,我返回一个 N 维的实数向量。
"天气" → [0.23, -0.45, 0.87, ... , 0.12] # 一个100维的向量这个过程就像查字典。你说"天气",我翻到第 3 页,上面写着它的"特征摘要"。
只不过这个"特征摘要"不是文字描述,而是一串数字。
这几个数字怎么来的?为什么"天气"是 [0.23, -0.45, ...] 而不是别的?
这些数字是模型从海量文本里学出来的。学会了什么?哪些词经常一起出现,它们的向量就应该接近。
这样一来,就把"有没有关系"这件事,用数字表示出来了。
维度也降下来了。原来要 1 万维,现在 100-300 维就够了。内存省了几十倍,还更好用了。

词向量是怎么炼成的?——Word2Vec 的两种训练方式
现在知道 Embedding 是个"翻译词典"了。但这些数字是怎么从文本里学出来的?
这里要介绍一个经典算法:Word2Vec。
它的核心思路很简单:一个词的性格,由它的朋友圈决定。
什么意思?
想象你认识一个人。你不知道他是干嘛的,但你知道他天天跟程序员、产品经理混在一起,写代码、聊需求、怼bug。那你大概能猜到——他是个互联网从业者。
词也是这样。"猫"经常跟"宠物""可爱""喵"一起出现,"狗"经常跟"宠物""忠诚""遛"一起出现。模型学会之后,"猫"和"狗"的向量就很接近,因为它们的"朋友圈"很像。
Word2Vec 有两种训练方式:
第一种:CBOW(Continuous Bag-of-Words)
也叫"完形填空"式学习。
给你一句话:"今天___很好喝"。让你填中间那个词。
模型也是这样学的。给它上下文"今天""很好喝",让它预测中间的词。猜对了就奖励,猜错了就惩罚。
学会之后,模型的"预测能力"就转化成了词向量。
第二种:Skip-gram
也叫"造句"式学习,跟 CBOW 反过来。
给你中间的词"咖啡",让你预测它周围可能出现什么词。
学会了什么?"咖啡"经常跟"今天""很好喝""提神"一起出现,那这些词的向量就跟"咖啡"靠近。
两种方式都能学到词向量。哪个更好?各有优势。Skip-gram 在数据少的时候表现更好,CBOW 训练速度更快。

训练完成之后,模型的权重矩阵 W1 就是词向量表。每个词的向量,就是它在这个矩阵里对应的那一行。
为什么"麦克"离"话筒"比离"天气"更近?
学到了词向量之后,我们来看看它们怎么用。
最重要的能力:语义相似性。
相似的词,在向量空间里的距离更近。
怎么定义"距离"?最常用的是余弦相似度。这个概念我们下一篇会详细讲,现在先建立直觉。
简单说:两个向量越"指向同一个方向",它们代表的意思就越接近。
来看几个例子。
"麦克"和"话筒"的向量很接近。为什么?因为它们经常在类似的语境里出现。你搜"麦克风",很可能也会搜"话筒"。
但"麦克"跟"天气"呢?完全不搭界。它们的向量指向完全不同的方向。
还有一个经典例子:
"国王" - "男人" + "女人" ≈ "女王"这是什么运算?
"国王"的向量减去"男人"的向量,再加上"女人"的向量,得到的新向量跟"女王"非常接近。
这不是数学巧合。这是模型从文本里学到的人类社会结构:"国王"对应"男人",那"女人"对应什么?对,应"女王"。
模型不仅记住了词,还记住了词与词之间的关系。
把词向量空间想象成一张地图。同类型的词汇会聚集在一起。"动物"区域、"天气"区域、"科技"区域……

Embedding 不只是词向量——万物皆可嵌入
讲到这里,你可能觉得 Embedding 就是用来处理文字的。
但它的威力远不止于此。
Embedding 的本质是:将任何离散对象映射到连续的向量空间。
词可以,句子也可以。一段话、一篇文章、一个商品、一部电影、一个用户画像——都可以变成向量。
这带来了无限可能。
推荐系统怎么工作的?
把用户变成一个向量——根据他看过什么电影、买过什么商品、点过什么赞。把商品也变成一个向量。
然后在向量空间里找:哪些商品离这个用户的向量最近?那些就是推荐给他的。
你刷抖音,算法推荐的视频之所以"刚好"是你感兴趣的,就是因为你和那些视频在向量空间里是"邻居"。
语义搜索怎么工作的?
以前搜索靠关键词匹配。你搜"苹果",它不知道你指的是水果还是手机。
现在不一样了。把你的搜索 query 变成向量,把文档库里的每篇文档也变成向量。然后找哪个文档的向量最接近你的 query。
语义相近的文档,就算没有出现你搜的词,也能被找出来。
RAG(检索增强生成) 更进一步。
大模型回答问题之前,先从知识库里检索相关的内容。怎么检索?把问题和知识都变成向量,在向量空间里找最匹配的片段。
找到之后,把这些片段喂给大模型,大模型再生成答案。
这就是为什么现在的 AI 助手能回答你公司的内部问题——因为它不是"背"出来的,是"查"出来的。

动手试试 PyTorch 的 Embedding
讲完了原理,来点实战。
PyTorch 提供了 nn.Embedding 模块,用起来特别简单。
import torch
import torch.nn as nn
# 创建一个词表大小为10000、向量维度为100的Embedding表
embedding = nn.Embedding(num_embeddings=10000, embedding_dim=100)
# 输入一个词的索引,比如5
word_index = torch.tensor([5])
# 查找这个词的向量
word_vector = embedding(word_index)
print(word_vector.shape) # 输出: torch.Size([1, 100])就这样。一个索引进去,一个向量出来。
num_embeddings 就是词表大小,有多少个词。embedding_dim 就是每个向量的维度,通常是 100、256、512 这些值。
你也可以直接加载预训练好的词向量,比如 GloVe、Word2Vec 训练好的向量表。拿来直接用,不用自己从头训练。
就像用现成的翻译软件,不用自己从零学外语。
这就是 Embedding 的秘密
现在你知道了 Embedding 在做什么。
它就是一个超级翻译器。把人类语言——或者说,把任何离散的对象——翻译成计算机能理解、计算的数学向量。
翻译之后,"相似"变成了"距离近","关系"变成了"向量运算","语义"变成了"空间位置"。
一切都是数字。一切都可以被计算。
但问题是:当 Embedding 把一切都变成数字之后,那些文字背后的情感、隐喻、文化共鸣,真的能被完整翻译吗?
下一篇我们会深入这个问题——相似度到底是怎么算出来的?余弦相似度是什么?为什么向量空间的"距离"能代表语义的距离?
这就是下一篇要聊的了。
