【大模型】Text在tokenization之后如何输入transformer?
transformer的输入处理
·
1. 添加特殊 Tokens
根据模型架构和任务需求,会在序列的开头、结尾或特定位置添加特殊 tokens:
[CLS]
(Classification Token):用于分类任务的聚合表示(如 BERT)[SEP]
(Separator Token):分隔句子对(如问答、自然语言推理)[BOS]
(Beginning of Sequence):序列开始标记[EOS]
(End of Sequence):序列结束标记[PAD]
:填充 token(稍后添加)
示例:
原始 tokens: ["我", "喜欢", "机器学习"]
添加特殊 tokens 后: ["[CLS]", "我", "喜欢", "机器学习", "[SEP]"]
2. 填充 (Padding) 或截断 (Truncation)
为了批量处理,需要将所有序列统一到相同长度:
- Padding:较短的序列用
[PAD]
token 填充到最大长度 - Truncation:较长的序列被截断到最大长度限制
# 示例:批量序列填充
序列1: [101, 2054, 2003, 1037, 666, 102] # 长度6
序列2: [101, 1045, 2293, 102] # 长度4
填充后 (max_length=8):
序列1: [101, 2054, 2003, 1037, 666, 102, 0, 0]
序列2: [101, 1045, 2293, 102, 0, 0, 0, 0]
3. 创建注意力掩码 (Attention Mask)
告诉模型哪些位置是真实 tokens,哪些是填充 tokens:
- 1 表示真实 token(需要被注意力机制关注)
- 0 表示填充 token(应该被忽略)
# 对应上面的填充示例
注意力掩码1: [1, 1, 1, 1, 1, 1, 0, 0]
注意力掩码2: [1, 1, 1, 1, 0, 0, 0, 0]
4. 创建 Token 类型 ID (Segment IDs)
对于处理句子对的任务(如问答、自然语言推理),需要区分两个句子:
- 0 表示属于第一个句子
- 1 表示属于第二个句子
# 句子对: [CLS] 句子A [SEP] 句子B [SEP]
input_ids: [101, 2054, 2003, 102, 1045, 2293, 102]
token_type_ids: [0, 0, 0, 0, 1, 1, 1]
5. 位置编码 (Positional Encoding)
由于 Transformer 的自注意力机制本身没有位置信息,需要注入位置信息:
- 绝对位置编码:为每个位置生成固定的编码向量
- 相对位置编码:编码 token 之间的相对距离关系
- 学习的位置嵌入:将位置索引也作为可学习的嵌入
# 位置索引: [0, 1, 2, 3, 4, 5] (对应序列长度)
位置编码 = 位置嵌入矩阵[位置索引]
6. 转换为模型输入张量
将所有组件组合成最终的输入字典或张量元组:
{
'input_ids': tensor([[101, 2054, 2003, 102, 0, 0]]), # Token IDs
'attention_mask': tensor([[1, 1, 1, 1, 0, 0]]), # 注意力掩码
'token_type_ids': tensor([[0, 0, 0, 0, 0, 0]]), # Token 类型 ID
'position_ids': tensor([[0, 1, 2, 3, 4, 5]]) # 位置 IDs(某些模型)
}
完整的数据预处理流程示例
# 假设使用 Hugging Face Transformers 库
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
# 原始文本
text = "Hello, how are you?"
# 1. Tokenization
tokens = tokenizer.tokenize(text) # ["hello", ",", "how", "are", "you", "?"]
# 2. 转换为 IDs 并添加特殊 tokens
input_ids = tokenizer.encode(text) # [101, 7592, 1010, 2129, 2024, 2017, 1029, 102]
# 3. 批量处理时:填充和创建掩码
batch_texts = ["Hello!", "How are you doing today?"]
inputs = tokenizer(
batch_texts,
padding=True, # 填充到批次中最长序列
truncation=True, # 截断到模型最大长度
return_tensors="pt" # 返回 PyTorch 张量
)
print(inputs)
# {
# 'input_ids': tensor([[101, 7592, 999, 102, 0, 0], [101, 2129, 2024, 2017, 2513, 102]]),
# 'attention_mask': tensor([[1, 1, 1, 1, 0, 0], [1, 1, 1, 1, 1, 1]]),
# 'token_type_ids': tensor([[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]])
# }
总结
Tokenizer 之后的操作形成了一个完整的数据预处理流水线:
文本 → Tokenization → 添加特殊Tokens → 填充/截断 → 创建注意力掩码 → 创建Segment IDs → 位置编码 → 输入张量
这些步骤确保了不同长度、不同任务的文本都能被规范化为模型可以处理的统一格式,是 Transformer 模型能够有效工作的关键前提。
更多推荐
所有评论(0)