【人工智能】如何理解transformer中的token?
如何理解transformer中的token?
- **一、Token在Transformer中的作用**
- **二、文本分词的常见方法**
- **1. 基于词典的分词(Dictionary-based Tokenization)**
- **2. 子词分词(Subword Tokenization)**
- **(1) WordPiece算法**
- **(2) BPE(Byte-Pair Encoding)**
- **(3) SentencePiece**
- **3. 字符级分词(Character-level Tokenization)**
- **三、分词步骤与算法选择**
- **具体步骤(以BPE为例)**
- **算法对比**
- **四、实际工具与代码示例**
- **1. Hugging Face Tokenizer**
- **2. 自定义BPE分词**
- **五、关键注意事项**
- **六、总结**
- 相关参考
一、Token在Transformer中的作用
Token 是Transformer模型的基本输入单位,可以理解为模型处理的“原子单元”。它的作用类似于人类语言中的“词”或“字符”,但具体定义取决于分词方法。
核心意义:
- 离散化连续文本:将无限可能的字符串映射到有限数量的Token集合(词汇表)。
- 保留语义信息:通过合理划分,使Token能携带单词、短语或字符级别的含义。
- 统一模型输入:所有文本需转换为相同长度的Token序列,便于模型处理。
二、文本分词的常见方法
1. 基于词典的分词(Dictionary-based Tokenization)
• 原理:使用预定义的词典(如WordNet、停用词表)匹配最长或最短单词。
• 步骤:
- 预处理:去除标点、数字、转换为小写。
- 查词典:按最长匹配或最短匹配切分单词。
- 未登录词处理:将未在词典中的词视为一个Token。
• 示例:
文本:"I love NLP!"
→ Tokens:["I", "love", "NLP", "!"]
• 优点:简单高效,适用于已知领域文本。
• 缺点:无法处理未登录词(如新造词“ChatGPT”)。
2. 子词分词(Subword Tokenization)
通过统计合并高频字符序列,生成子词单元(Subword Units),解决未登录词问题。常用方法包括:
(1) WordPiece算法
• 原理:
- 统计频率:统计所有可能的子词片段(如
"unhappy"
拆分为"un"
,"ha"
,"ppy"
)。 - 合并策略:合并出现频率最高的子词对,直到无法进一步合并。
• 示例:
文本:"unhappy"
→ 初始子词:["u", "n", "h", "a", "p", "p", "y"]
合并后:["un", "happy"]
(假设"un"
和"happy"
高频出现)。
• 应用:BERT、GPT等模型采用WordPiece。
(2) BPE(Byte-Pair Encoding)
• 原理:
- 初始切分:将文本按字符拆分(如
"apple"
→["a", "p", "p", "l", "e"]
)。 - 统计合并:每次合并出现频率最高的相邻字符对。
• 示例:
文本:"apple apple"
→ 初始字符对:"ap"
,"pp"
,"pl"
,"le"
等。
合并后:["a", "p", "p", "le"]
→["a", "pp", "le"]
。
• 应用:GPT-2、GPT-3等模型采用BPE。
(3) SentencePiece
• 原理:
- 无词典训练:直接从原始文本中学习子词边界,无需预定义词典。
- 统一编码:对多语言文本生成统一词汇表。
• 示例:
文本:"I love NLP! 你好世界!"
→ Tokens:["I", "love", "NLP", "!", "你", "好", "世界", "!"]
。
• 应用:XLM-R、mBERT等多语言模型。
3. 字符级分词(Character-level Tokenization)
• 原理:将每个字符视为一个Token(如中文的每个汉字)。
• 示例:
文本:"我爱NLP!"
→ Tokens:["我", "爱", "N", "L", "P", "!"]
• 优点:无需词典,处理罕见词能力强。
• 缺点:词汇表大小过大(如中文字符集达10万+),模型参数需求高。
三、分词步骤与算法选择
具体步骤(以BPE为例)
- 预处理:
• 删除标点符号、数字、转换为统一小写(可选)。
• 示例:"Hello, World! 2023"
→"hello world"
。 - 初始切分:按字符拆分文本。
• 示例:"hello world"
→["h", "e", "l", "l", "o", " ", "w", "o", "r", "l", "d"]
。 - 统计字符对频率:
• 构建所有可能的相邻字符对及其出现次数。
• 示例:"he"
,"el"
,"ll"
,"lo"
,"o "
," w"
, etc. - 合并高频字符对:
• 按频率从高到低排序,依次合并字符对,直到达到预设的词汇表大小。
• 示例:假设"ll"
频率最高,合并为"ll"
→ 新Token列表:["h", "e", "ll", "o", " ", "w", "o", "r", "l", "d"]
。 - 生成词汇表:
• 记录所有合并后的子词和单字符Token。 - 文本编码:
• 将原始文本映射为词汇表中的索引。
• 示例:"hello world"
→[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
。
算法对比
方法 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
WordPiece | 平衡词汇表大小与未登录词处理 | 依赖预定义词典或初始分词策略 | 中英文、已知领域文本 |
BPE | 无需词典,适合大数据集 | 合并过程复杂,内存消耗大 | 大规模语料(如GPT系列) |
SentencePiece | 跨语言支持,无词典依赖 | 训练时间较长 | 多语言、混合语种文本 |
字符级分词 | 完全处理未登录词 | 词汇表爆炸,模型参数量大 | 小语种、罕见词频繁场景 |
四、实际工具与代码示例
1. Hugging Face Tokenizer
from transformers import BertTokenizer
# 加载预训练模型的Tokenizer(基于WordPiece)
tokenizer = BertTokenizer.from_pretrained("bert-base-uncased")
# 分词示例
text = "I love NLP! This is an example."
tokens = tokenizer(text, truncation=True, padding="max_length", max_length=10)
print(tokens["input_ids"]) # 输出Token索引
print(tokens["tokens"]) # 输出Token字符串
输出:
input_ids: [101, 1976, 2363, 2003, 1994, 15851, 1999, 2002, 30522, 2000]
tokens: ['[CLS]', 'I', 'love', 'NLP', '!', 'This', 'is', 'an', 'example', '[SEP]']
2. 自定义BPE分词
使用tokenizers
库实现BPE:
from tokenizers import Tokenizer
# 初始化BPE Tokenizer
tokenizer = Tokenizer()
# 添加训练数据(假设语料库为.txt文件)
tokenizer.train(files=["corpus.txt"], model="bpe")
# 分词
text = "hello world!"
tokens = tokenizer.encode(text)
print(tokens) # 输出整数索引
print(tokenizer.decode(tokens)) # 输出恢复的文本
五、关键注意事项
- 特殊字符处理:
• 在预处理阶段删除或保留标点符号(如[CLS]
、[SEP]
在BERT中的作用)。 - 大小写敏感:
• 英文通常统一为小写,中文保留原样。 - 未登录词处理:
• 对未在词汇表中的词,BPE会自动拆分为子词(如"ChatGPT"
→["Chat", "G", "PT"]
)。 - 跨语言支持:
• 使用SentencePiece或XLM-R Tokenizer处理多语言文本。
六、总结
• Token是Transformer模型的“原子单位”,其划分方式直接影响模型性能。
• 分词算法选择:
• 中英文 → WordPiece/BPE。
• 多语言 → SentencePiece。
• 小语种 → 字符级分词。
• 工具推荐:
• Hugging Face Tokenizer(预训练模型适配)。
• tokenizers
库(自定义BPE/SentencePiece)。
通过合理选择分词方法,可以显著提升模型对文本的理解能力,尤其是在处理未登录词和跨语言场景时。
相关参考
【大语言模型知识】Transformer架构概述