词云嵌入(精简版)
#2025/12/28 #ai
可以把 “词元嵌入” (Token Embeddings) 看作是将非结构化数据(文本)转换为结构化数据(向量)的关键类型转换过程。
分词器(Tokenizer)把文本转成了 List<Int>(Token IDs)。但是,神经网络的内部计算(矩阵乘法)不能直接处理整数 ID,它需要浮点数向量。
下面讲两个核心概念:
静态查表和动态上下文处理。- 我们可以用“
数据库查找”和“运行时上下文注入”来类比。
- 我们可以用“
目录
- 1. 静态嵌入:巨大的 Key-Value 查找表 (The Lookup Table)
- 2. 动态嵌入:运行时上下文注入 (Contextualized Embeddings)
- 3. 代码实战:数据的形状 (Shape)
- 总结:程序员视角的“词元嵌入”
1. 静态嵌入:巨大的 Key-Value 查找表 (The Lookup Table)
语言模型如何存储词元?
- 数据结构视角:
- 想象
模型内部维护了一个巨大的只读哈希表(HashMap)或者查找表(Lookup Table)。- Key (索引):
- Token ID (例如
50257代表"The")。
- Token ID (例如
- Value (数据):
- 一个固定长度的浮点数数组(Vector),
- 比如
[0.12, -0.98, 0.55, ...]。
- 比如
- 一个固定长度的浮点数数组(Vector),
- Key (索引):
- 想象
- 流程:
- 当你把 Token ID 列表
- `` 传给模型时,模型的第一层不做任何计算,仅仅是查表。它根据 ID 找到对应的向量。
- 输入:
[Integer] - 输出:
[Vector<Float>]
- 输入:
- `` 传给模型时,模型的第一层不做任何计算,仅仅是查表。它根据 ID 找到对应的向量。
- 当你把 Token ID 列表
- 初始化与训练:
- 这张表(嵌入矩阵)在模型刚开始训练时,里面的浮点数是
随机初始化的(全是噪声)。- 为什么要这样呢?这个问题很有意思
- 通过
海量数据的训练,反向传播算法会修改这些数值,让语义相近的词(如 “cat” 和 “dog”)在数学空间上的向量距离更近。
- 这张表(嵌入矩阵)在模型刚开始训练时,里面的浮点数是
2. 动态嵌入:运行时上下文注入 (Contextualized Embeddings)
这是 LLM 与老一代技术(如 word2vec)最大的区别
- 问题:
- 在静态查表中,“Apple” 这个词对应的向量是固定的
- 但是
- 在“I ate an Apple”(水果)和“I bought Apple stock”(科技公司)这两句话里,“Apple”的意思完全不同。
- 如果只用查表,模型不仅无法区分多义词,也无法理解语境。
- 解决方案(上下文相关):
- 模型的第一层查表得到的只是“初始状态”。随后,这些向量会流经模型的
一层层神经网络(Transformer 层)。- 处理逻辑:
- 模型会查看“Apple”周围的词(Context)。
- 如果周围有“eat”,模型就会修改“Apple”的向量,使其更像“水果”;
- 如果周围有“stock”,就修改它使其更像“公司”。
- 模型会查看“Apple”周围的词(Context)。
- 结果: 最终输出的向量是与上下文相关的(Contextualized)。它是
动态计算出来的,而不是静态查出来的。
- 处理逻辑:
- 模型的第一层查表得到的只是“初始状态”。随后,这些向量会流经模型的
3. 代码实战:数据的形状 (Shape)
书中通过一段 DeBERTa 模型的代码展示了数据在内存中的样子。作为程序员,理解数据的 Shape(维度) 至关重要。
# 1. 输入文本
tokens = tokenizer('Hello world', return_tensors='pt')
# 此时 tokens['input_ids'] 是一个整数张量: [] (假设值)
# 2. 模型处理
output = model(tokens)
# 3. 查看输出维度
print(output.shape)
# 输出: torch.Size()
如何理解这个 ``?,
- 1 (Batch Size):
- 你一次处理了 1 个句子。
- 4 (Sequence Length):
- 这个句子被分成了
4 个 Token(比如[CLS],Hello,world,[SEP])。
- 这个句子被分成了
- 384 (Hidden Size / Vector Dimension):
- 这就是嵌入的核心。 每一个 Token 不再是一个整数,而被“展开”成了一个包含 384 个浮点数的向量。
总结:程序员视角的“词元嵌入”
- 接口层: 它是
Integer到Float[]的适配器。 - 存储层: 模型权重里包含一个巨大的
Matrix[Vocab_Size, Vector_Dim],专门用来做 ID 到向量的映射。 - 逻辑层:
- LLM 的本质就是把这些静态的向量,经过复杂的计算(混合上下文信息),转换成含有丰富语义的动态向量,供下游任务(如分类、生成图片、命名实体识别)使用。
简单来说,嵌入(Embedding)就是把 符号(Symbol)变成了可计算的数学对象(Vector)。