在自然语言处理(NLP)中,Tokenizer 和 Embedding 是两个非常基础但又容易混淆的概念。它们在 Transformer 和 BERT 等模型中扮演着至关重要的角色。本文将详细讲解它们的定义、作用、区别,以及它们在模型输入处理中的具体流程。
一、什么是 Tokenizer?(一把菜刀🔪)
1. 定义
Tokenizer 是将原始文本(字符串)转化为模型可以处理的“token”(词、子词、字符等单位)的过程。
2. 作用
-
将一段文本切分成一个个基本单位(token)。
-
将每个 token 映射为一个唯一的整数 ID(词表中的索引)。
3. 示例
输入文本:
"Hello, how are you?"
经过 Tokenizer(如 BERT 的 WordPiece)处理后可能变成:
["Hello", ",", "how", "are", "you", "?"]
然后映射为 ID(假设词表中):
[7592, 117, 1762, 1385, 2345, 119]
4. 常见的 Tokenizer 类型
-
Word-level(词级)
-
Character-level(字符级)
-
Subword-level(子词级):
-
BPE(Byte Pair Encoding)
-
WordPiece(BERT 使用)
-
SentencePiece(支持多语言)
-
二、什么是 Embedding?(一个词典📖)
1. 定义
Embedding 是将离散的 token ID 映射为连续的向量(向量空间中的表示)的过程。
2. 作用
-
将每个 token ID 转换为一个固定维度的向量(如 768 维)。
-
这些向量可以捕捉词语的语义信息(通过训练得到)。
3. 示例
假设词表大小是 30522,embedding 维度是 768,那么 Embedding 层是一个形状为 (30522, 768)
的矩阵。
输入一个 token ID 7592
,Embedding 层会输出一个 768 维的向量:
embedding_matrix[7592] -> [0.23, -0.45, ..., 0.12] # shape: (768,)
三、Tokenizer 与 Embedding 的区别与联系
项目 | Tokenizer | Embedding |
类型 | 文本处理 | 向量表示 |
输入 | 原始文本(字符串) | token ID |
输出 | token list / token ID 序列 | 向量(tensor) |
是否可训练 | 一般不训练,使用预训练的 | 一般是可训练的参数 |
所属模块 | 预处理 | 模型的一部分 |
示例 |
|
|
常见误区与澄清
- ❌ 误解1:Tokenizer直接输出向量
✅ 纠正:Tokenizer仅输出ID,Embedding层才负责转向量。 - ❌ 误解2:Embedding是Tokenizer的一部分
✅ 纠正:Tokenizer是独立预处理步骤,Embedding是模型的可训练层。 - ❌ 误解3:BERT的输入是Embedding后的结果
✅ 纠正:BERT的输入是文本(或Token ID),Embedding是模型内部处理步骤。
四、Transformer Encoder 的输入是什么?
Transformer 的 Encoder 输入是一个 token 的向量表示,即:
✅ 输入到 Encoder 的是:
-
经过 Tokenizer 处理后的 token ID
-
再经过 Embedding 层映射成的向量
-
并加上位置编码(Positional Encoding)
流程如下:
原始文本
↓
Tokenizer(分词 + 映射为 ID)
↓
Embedding Layer(映射为向量)
↓
Positional Encoding(加上位置信息)
↓
输入到 Transformer Encoder
五、BERT 的输入处理流程
BERT 是基于 Transformer 的 Encoder 构建的模型,因此输入流程与 Transformer 类似,但结构更复杂。
✅ 输入到 BERT 的是:
-
经过 Tokenizer 处理后的 token ID
-
再经过 Embedding 层映射成的向量
-
并加上 Segment Embedding 和 Positional Embedding
BERT 输入的三部分:
-
Token Embeddings:词本身的嵌入。
-
Segment Embeddings:用于区分句子对(如问题和回答)。
-
Positional Embeddings:表示位置信息。
这三部分相加后,输入到 BERT 的第一个 Encoder 层。
六、代码示例(使用 HuggingFace Transformers)
from transformers import BertTokenizer, BertModel
# 1. 加载 Tokenizer
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
# 2. 原始文本
text = "Hello, how are you?"
# 3. Tokenizer 处理(得到 token ID)
inputs = tokenizer(text, return_tensors='pt') # 输出 token_ids, attention_mask 等
# 4. 加载预训练的 BERT 模型
model = BertModel.from_pretrained('bert-base-uncased')
# 5. 输入到 BERT(自动完成 Tokenizer + Embedding + Encoder)
outputs = model(input_ids=inputs['input_ids'],
attention_mask=inputs['attention_mask'])
# 6. outputs.last_hidden_state 就是 Encoder 输出的 token 向量表示
七、总结
-
Tokenizer 是将文本切分并映射为 ID 的工具;
-
Embedding 是将 ID 映射为向量的模型参数;
-
输入到 Transformer Encoder 或 BERT 的是 Tokenizer + Embedding 的结果(即 token 的向量表示);
-
BERT 还进一步加入了 Segment Embedding 和 Positional Embedding。
常见误区与澄清
- ❌ 误解1:Tokenizer直接输出向量
✅ 纠正:Tokenizer仅输出ID,Embedding层才负责转向量。 - ❌ 误解2:Embedding是Tokenizer的一部分
✅ 纠正:Tokenizer是独立预处理步骤,Embedding是模型的可训练层。 - ❌ 误解3:BERT的输入是Embedding后的结果
✅ 纠正:BERT的输入是文本(或Token ID),Embedding是模型内部处理步骤