如何理解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架構概述