【深度学习】词嵌入技术_从Word2Vec到现代Embedding

文章目录

    • [一、从文字到数字:为什么需要 Embedding](#一、从文字到数字:为什么需要 Embedding)
    • [二、Embedding 本质上是查表](#二、Embedding 本质上是查表)
    • [三、Embedding 怎么通过训练学出来](#三、Embedding 怎么通过训练学出来)
    • [四、Word2Vec:CBOW 和 Skip-gram](#四、Word2Vec:CBOW 和 Skip-gram)
    • 五、负采样:不要每次比较整个词表
    • 六、用余弦相似度看语义距离
    • 七、从静态词向量到上下文相关表示
    • [八、Transformer 里的 Token Embedding](#八、Transformer 里的 Token Embedding)
    • 九、输出层和权重绑定
    • [十、RAG 里的 Embedding 和模型内部 Embedding](#十、RAG 里的 Embedding 和模型内部 Embedding)
    • [十一、Embedding 模型如何用于检索](#十一、Embedding 模型如何用于检索)
    • [十二、Embedding 的常见问题](#十二、Embedding 的常见问题)
      • [问题 1:语义相近但关键词不同](#问题 1:语义相近但关键词不同)
      • [问题 2:关键词相同但语义不同](#问题 2:关键词相同但语义不同)
      • [问题 3:长文档被压成一个向量会丢信息](#问题 3:长文档被压成一个向量会丢信息)
      • [问题 4:领域术语不匹配](#问题 4:领域术语不匹配)
      • [问题 5:向量相似不等于答案正确](#问题 5:向量相似不等于答案正确)
    • 十三、常见误区
    • 十四、你应该记住的最小心智模型
    • 总结
    • 大模型视角
    • 下一篇

摘要:模型不能直接理解文字,必须先把离散 token 变成连续向量。Embedding 的本质是一张可学习的查表矩阵:每个 token id 对应一行向量。Word2Vec 让我们看到"词的意义可以从上下文中学出来",Transformer 把 token embedding、位置编码和上下文表示进一步结合,现代 RAG 和语义检索又把 embedding 用作文本相似度搜索的基础。本文从 one-hot 为什么不够讲起,解释 embedding 查表、Word2Vec 的 Skip-gram/CBOW 直觉、余弦相似度、Transformer token embedding、上下文相关 embedding、权重绑定,以及模型内部 embedding 和检索 embedding 的区别。

前置知识 :向量与矩阵, Softmax,反向传播

阅读时间 :约 65 分钟

代码环境:Python 3.10+,numpy >= 1.24,torch >= 2.0

入门导读:先抓住主线

Embedding 要解决的问题很简单:文字是离散符号,神经网络需要连续向量。

例如:

text 复制代码
"猫" -> token id 2314 -> 向量 [0.12, -0.08, 0.31, ...]

这个向量不是人工写出来的,而是在训练中学出来的。训练目标会让经常出现在类似上下文里的词,向量逐渐靠近。

从 Word2Vec 到现代大模型,核心思想一直在:

一个 token 的意义,来自它在上下文中的使用方式。

但要注意,现代语境里的 embedding 有两个含义:

  1. 模型内部 token embedding:把 token id 查成向量,作为 Transformer 输入;
  2. 检索/语义 embedding:把一句话、一段文档编码成向量,用于相似度搜索。

它们相关,但不是同一件事。

读完先达到这个程度就够了

  • 能解释 one-hot 表示为什么不适合直接建模语义;
  • 能理解 embedding table 本质上是查表;
  • 能说清 Word2Vec 如何从上下文学习词向量;
  • 能用余弦相似度比较向量接近程度;
  • 能理解 Transformer token embedding 和 position embedding 的作用;
  • 能区分模型内部 embedding 和 RAG 里的语义 embedding。

带着这 3 个问题读

  1. 为什么 token id 不能直接当成模型输入?
  2. Word2Vec 为什么能让语义相近的词向量更接近?
  3. RAG 里用的 embedding 和大模型输入层 embedding 有什么区别?

一、从文字到数字:为什么需要 Embedding

神经网络处理的是数字张量,不是文字。

最直接的方法是给每个词一个编号:

text 复制代码
猫 -> 1
狗 -> 2
汽车 -> 3

但编号本身没有语义。猫=1狗=2汽车=3 不表示猫和狗比猫和汽车更接近。

另一种方法是 one-hot:词表有多大,向量就有多长。某个词对应位置为 1,其余为 0。

text 复制代码
猫   -> [1, 0, 0, 0]
狗   -> [0, 1, 0, 0]
汽车 -> [0, 0, 1, 0]

one-hot 的问题:

  • 维度巨大;
  • 非常稀疏;
  • 任意两个不同词距离都差不多;
  • 没有语义相似度。

Embedding 的做法是把每个 token 映射成一个低维稠密向量:

text 复制代码
猫   -> [0.2, -0.1, 0.7]
狗   -> [0.3, -0.2, 0.6]
汽车 -> [-0.5, 0.8, 0.1]

这样语义相近的词,有机会在向量空间里更接近。


二、Embedding 本质上是查表

在神经网络里,embedding table 是一个矩阵:

text 复制代码
[vocab_size, embedding_dim]

每个 token id 对应矩阵中的一行。

PyTorch 示例:

python 复制代码
import torch
import torch.nn as nn

vocab_size = 10000
embedding_dim = 16
embedding = nn.Embedding(vocab_size, embedding_dim)

token_ids = torch.tensor([[12, 35, 98], [7, 35, 102]])
x = embedding(token_ids)

print(token_ids.shape)  # [batch, seq_len]
print(x.shape)          # [batch, seq_len, embedding_dim]

nn.Embedding 本质上就是查表。输入是整数 id,输出是对应行向量。

这些向量一开始通常随机初始化,训练过程中通过反向传播更新。

如果某个 token 在训练中频繁出现在类似上下文里,它的向量会被推向能帮助模型完成预测的位置。


三、Embedding 怎么通过训练学出来

假设我们做一个很简单的任务:根据中心词预测上下文词。

句子:

text 复制代码
我 喜欢 机器 学习

如果中心词是"机器",上下文可能是"喜欢""学习"。模型训练目标是让"机器"的向量能预测它周围的词。

训练反复进行后,出现在相似上下文中的词会拥有相似向量。

例如:

text 复制代码
猫 喜欢 吃 鱼
狗 喜欢 吃 肉

"猫"和"狗"经常出现在类似语境里,它们的向量可能更接近。

这就是分布式语义假设的直觉:

词的意义由它出现的上下文决定。

Word2Vec 就是这个思想的经典代表。


四、Word2Vec:CBOW 和 Skip-gram

Word2Vec 有两种常见训练方式。

CBOW

CBOW 用上下文预测中心词。

text 复制代码
上下文:我 喜欢 [MASK] 学习
目标:机器

Skip-gram

Skip-gram 用中心词预测上下文。

text 复制代码
中心词:机器
目标:喜欢、学习

两者都在学习一个目标:让语义相关、上下文相似的词在向量空间中更接近。

简化 Skip-gram 训练样本生成:

python 复制代码
sentence = ["我", "喜欢", "机器", "学习"]
window = 1
pairs = []

for i, center in enumerate(sentence):
    for j in range(max(0, i - window), min(len(sentence), i + window + 1)):
        if i != j:
            pairs.append((center, sentence[j]))

print(pairs)

输出类似:

text 复制代码
("喜欢", "我")
("喜欢", "机器")
("机器", "喜欢")
("机器", "学习")

真实 Word2Vec 会用负采样等技巧避免对整个词表做完整 softmax,从而提升训练效率。


五、负采样:不要每次比较整个词表

如果词表有 100 万词,每次训练都对整个词表做 softmax,成本很高。

负采样的思路是:

text 复制代码
正样本:真实上下文词
负样本:随机采样几个不是上下文的词

模型只需要区分"这个词是不是中心词的真实上下文"。

例如中心词"机器",正样本"学习",负样本"香蕉""火车""椅子"。

训练目标让:

text 复制代码
机器 和 学习 的相似度变高
机器 和 随机负样本 的相似度变低

这大幅降低计算成本,也让词向量训练更高效。

现代大规模对比学习、embedding 检索模型里,也能看到类似"正样本拉近、负样本推远"的思想。


六、用余弦相似度看语义距离

Embedding 向量训练好后,常用余弦相似度衡量方向接近程度。

公式:

c o s ( a , b ) = a ⋅ b ∥ a ∥ ∥ b ∥ cos(a, b) = \frac{a \cdot b}{\|a\|\|b\|} cos(a,b)=∥a∥∥b∥a⋅b

代码:

python 复制代码
import numpy as np

def cosine_similarity(a, b):
    a = np.array(a)
    b = np.array(b)
    return float(a @ b / (np.linalg.norm(a) * np.linalg.norm(b)))

cat = [0.2, 0.1, 0.7]
dog = [0.25, 0.05, 0.65]
car = [-0.5, 0.8, 0.1]

print("cat-dog:", cosine_similarity(cat, dog))
print("cat-car:", cosine_similarity(cat, car))

余弦相似度更关注方向,而不是向量长度。

在检索系统里,常见做法是把 query 和 document 编码成向量,再用余弦相似度或内积找最近文档。


七、从静态词向量到上下文相关表示

Word2Vec 这类词向量通常是静态的:同一个词只有一个向量。

这会遇到多义词问题。

例如"苹果":

text 复制代码
我买了一个苹果。
苹果发布了新手机。

静态 embedding 里,"苹果"只有一个向量,很难同时表达水果和公司。

Transformer 里的表示是上下文相关的。

输入层 token embedding 仍然是查表得到的静态向量,但经过多层 self-attention 后,每个 token 的 hidden state 会融合上下文信息。

text 复制代码
输入层:苹果 -> 同一个 token embedding
经过 Transformer:
  水果语境里的苹果 -> 一种上下文表示
  公司语境里的苹果 -> 另一种上下文表示

这就是现代语言模型强于早期静态词向量的重要原因之一。


八、Transformer 里的 Token Embedding

在 Transformer 语言模型中,第一步通常是:

text 复制代码
token ids -> token embedding

形状:

text 复制代码
input_ids: [batch, seq_len]
token_embedding: [vocab_size, d_model]
output: [batch, seq_len, d_model]

PyTorch:

python 复制代码
import torch
import torch.nn as nn

batch, seq_len = 2, 4
vocab_size, d_model = 50000, 768

input_ids = torch.randint(0, vocab_size, (batch, seq_len))
tok_emb = nn.Embedding(vocab_size, d_model)

x = tok_emb(input_ids)
print(x.shape)

然后通常还要加入位置信息:

text 复制代码
x = token_embedding + position_embedding

或者在 attention 的 Q/K 上使用 RoPE。

Token embedding 解决"是什么 token",位置编码解决"在哪里"。


九、输出层和权重绑定

语言模型最后要把 hidden state 映射回词表 logits:

text 复制代码
hidden: [batch, seq_len, d_model]
logits: [batch, seq_len, vocab_size]

这通常通过 LM Head 完成:

python 复制代码
lm_head = nn.Linear(d_model, vocab_size, bias=False)
logits = lm_head(hidden)

有些模型会使用 weight tying,也就是输入 embedding 矩阵和输出投影矩阵共享权重。

直觉:输入时每个 token 有一个向量,输出时也需要判断 hidden state 和哪个 token 向量最匹配。共享权重可以减少参数,也可能改善表示一致性。

PyTorch 示意:

python 复制代码
tok_emb = nn.Embedding(vocab_size, d_model)
lm_head = nn.Linear(d_model, vocab_size, bias=False)

lm_head.weight = tok_emb.weight

权重绑定不是所有模型都必须用,但它是语言模型里常见技巧。


十、RAG 里的 Embedding 和模型内部 Embedding

现代应用里,说到 embedding,很多人想到的是 RAG 检索向量。

例如:

text 复制代码
query -> embedding vector
document chunk -> embedding vector
向量数据库检索相似 chunk

这和模型内部 token embedding 有区别。

类型 输入 输出 用途
Token Embedding token id 每个 token 一个向量 作为语言模型内部输入
语义 Embedding 句子/段落/文档 整段文本一个向量 检索、聚类、相似度

RAG embedding 通常来自专门训练的 Encoder 模型或 embedding API。它输出的是整段文本的语义向量,目标是让相关文本在向量空间接近。

模型内部 token embedding 则是大模型参数的一部分,主要服务于后续 Transformer 计算。

不要把两者混为一谈。


十一、Embedding 模型如何用于检索

一个最小语义检索流程:

python 复制代码
import numpy as np

def normalize(x):
    x = np.array(x, dtype=float)
    return x / np.linalg.norm(x)

query = normalize([0.2, 0.1, 0.7])
docs = np.array([
    normalize([0.21, 0.12, 0.69]),
    normalize([-0.4, 0.9, 0.1]),
    normalize([0.18, 0.08, 0.72]),
])

scores = docs @ query
ranking = np.argsort(-scores)
print(scores)
print(ranking)

真实系统会用向量数据库做近似最近邻搜索,例如 FAISS、Milvus、Qdrant、pgvector 等。

RAG 效果不仅取决于 embedding 模型,还取决于:

  • 文档切分 chunk 是否合理;
  • query 是否需要改写;
  • 向量维度和归一化;
  • top-k 取多少;
  • 是否使用 reranker;
  • 检索结果如何放入 prompt;
  • 是否保留引用和来源。

Embedding 是 RAG 的基础,但不是 RAG 的全部。


十二、Embedding 的常见问题

问题 1:语义相近但关键词不同

好的 embedding 应该能找到语义相近内容,而不只是关键词重合。

text 复制代码
query:如何重置密码?
doc:忘记登录口令后的找回流程

问题 2:关键词相同但语义不同

Embedding 也可能被表面相似迷惑。

text 复制代码
苹果 水果
aapl 苹果公司股票

上下文和领域训练很重要。

问题 3:长文档被压成一个向量会丢信息

一篇很长的文档包含多个主题,如果只编码成一个向量,细节可能被稀释。所以 RAG 常常需要 chunk。

问题 4:领域术语不匹配

通用 embedding 模型可能不懂医疗、法律、金融、代码库里的专业语义。领域任务可能需要专门模型或微调。

问题 5:向量相似不等于答案正确

检索相似文档只是第一步。最终回答还要看生成模型是否忠实使用证据。


十三、常见误区

误区 1:token id 大小有语义。

没有。id 只是查表索引,语义来自 embedding 向量和训练过程。

误区 2:Embedding 向量每一维都有明确人工含义。

通常没有。单个维度很难解释,语义更多体现在整体方向和距离上。

误区 3:Word2Vec 已经过时,所以不值得学。

Word2Vec 是理解分布式语义和上下文学习的经典入口,思想仍然影响现代 embedding。

误区 4:模型内部 embedding 就是 RAG embedding。

不是。前者是 token 输入表示,后者是整段文本语义检索表示。

误区 5:向量最相似的文档一定最有用。

相似不等于相关,更不等于能回答问题。检索常需要 rerank 和任务评估。

误区 6:Embedding 维度越高越好。

维度高可能表达力更强,也会增加存储、检索成本和过拟合风险。要看任务和模型。


十四、你应该记住的最小心智模型

Embedding 可以这样记:

text 复制代码
token id 本身没有语义
embedding table 把 id 查成向量
训练目标让有用的向量关系逐渐形成
Transformer 进一步把静态 token embedding 变成上下文相关 hidden state
RAG embedding 把整段文本变成向量用于检索

核心区别:

text 复制代码
模型内部 token embedding:服务模型计算
语义检索 embedding:服务相似度搜索

看到 embedding,不要只问"维度是多少",还要问:

text 复制代码
它是为哪个目标训练的?
输入粒度是 token 还是文本段?
相似度用于什么任务?
是否经过领域适配?

总结

Embedding 是把离散符号变成连续向量的关键技术。one-hot 表示稀疏且没有语义距离,embedding table 通过训练学习每个 token 的稠密向量。Word2Vec 证明了词义可以从上下文中学习,CBOW 和 Skip-gram 分别用上下文预测中心词或用中心词预测上下文。Transformer 在 token embedding 基础上加入位置和多层上下文建模,让同一个词在不同语境中形成不同表示。

现代应用中的 embedding 还包括语义检索向量,用于 RAG、搜索、聚类和推荐。它和模型内部 token embedding 相关但不同:一个服务语言模型输入,一个服务文本相似度检索。

第一遍记住一句话:Embedding 的本质是把离散 token 或文本映射到向量空间,让模型可以用距离和方向学习语义关系。

大模型视角

后续你看 tokenizer、Transformer、RAG、向量数据库和 embedding 模型时,都会反复遇到本篇概念。大模型内部靠 token embedding 开始计算,外部知识系统靠语义 embedding 找资料。理解这两类 embedding 的区别,是理解现代 LLM 应用架构的基础。

下一篇

RNN 与 LSTM:序列建模的前 Transformer 时代 ------ Embedding 把 token 变成向量,接下来要处理顺序。下一篇看 Transformer 出现前,RNN 和 LSTM 如何用隐藏状态建模序列。

相关推荐
明月_清风2 小时前
用自然语言控制 Blender:开源项目 Blender MCP 深度介绍
人工智能·后端
鲁邦通物联网2 小时前
机器人梯控如何区分电梯门全开与半开状态
人工智能·机器人·机器人梯控·agv梯控·机器人乘梯·机器人自主乘梯·agv机器人梯控
matlab代码2 小时前
基于matlab模板匹配的手写体数字识别【源码78期】
人工智能·计算机视觉
智购无人售货机厂家2 小时前
2026自动售货机品类拓展逻辑:从饮料零食到鲜食药品文创的工程实践~YH
服务器·人工智能·单片机·线性代数·矩阵
泡茶喝茶写代码2 小时前
量化数据开发实战系列(第 25 篇):基金基础接口实战:基金列表、ETF-LOF 分类、基金概况、净值数据
java·数据库·人工智能·python·mysql
张小姐的猫2 小时前
【AI大模型接入SDK】 —— 数据管理 & 与Session模块进行联动
数据结构·数据库·c++·人工智能·python·chatgpt
m4Rk_2 小时前
【论文阅读】Agent 记忆机制(67):MemPO——用记忆级信用分配训练 Agent 主动管理长程上下文
论文阅读·人工智能·学习·开源·github
Ai思想家2 小时前
企业AI网关的跨可用区容灾与多活设计
人工智能
Mr数据杨2 小时前
基于企业交易数据的OKVED行业分类实战解析
人工智能·数据分析·kaggle竞赛