在自然語言處理里,tokenizer.json
文件一般是由 Hugging Face 的 Tokenizers 庫生成的,它是分詞器配置的核心文件。這里面的 vocab
和 merges
是子詞分詞算法(像 BPE 這種)的重要構成要素。下面為你詳細解釋它們的作用和工作原理:
1. vocab(詞匯表)
- 功能:
vocab
是一個從 token(子詞)到 ID 的映射表,其作用是把文本轉換為模型能夠處理的數字表示。 - 內容形式:
- 基礎字符:涵蓋了單個字符,例如
["a", "b", "c", ...]
。 - 常見子詞:包含常見的前綴、后綴或者詞片段,例如
["?the", "?quick", "?brown", ...]
(這里的?
代表空格)。 - 特殊 token:有用于填充的
[PAD]
、句子開始的[CLS]
、分隔的[SEP]
、未知詞的[UNK]
等。
- 基礎字符:涵蓋了單個字符,例如
- 示例:
{"vocab": {"?": 0,"a": 1,"b": 2,"c": 3,"?the": 4,"?quick": 5,"[PAD]": 100,"[CLS]": 101,"[SEP]": 102,"[UNK]": 103}
}
- 運作機制:
在分詞時,文本會先被分解成基礎字符,接著依據merges
規則合并成子詞,最后通過vocab
將這些子詞轉換為對應的 ID。
2. merges(合并規則)
- 功能:
merges
是一系列的合并規則,其目的是把基礎字符組合成子詞。這體現了 BPE(字節對編碼)算法的核心思想。 - 內容形式:
- 它是一個按照合并優先級排序的二元組列表,格式為
["ab", "?t", "he", ...]
。 - 排序越靠前的規則,應用的優先級越高。
- 它是一個按照合并優先級排序的二元組列表,格式為
- 示例:
{"merges": ["a b", // 先將 "a" 和 "b" 合并為 "ab""? t", // 再將 "?" 和 "t" 合并為 "?t""?t h", // 接著將 "?t" 和 "h" 合并為 "?th""?th e" // 最后將 "?th" 和 "e" 合并為 "?the"]
}
-
運作機制:
- 初始狀態:文本被拆分成單個字符,比如
"The dog"
會變成["?", "T", "h", "e", "?", "d", "o", "g"]
。 - 應用合并規則:按照
merges
中的順序依次進行合并。- 首先合并
"?"
和"T"
,得到["?T", "h", "e", "?", "d", "o", "g"]
。 - 然后合并
"h"
和"e"
,得到["?T", "he", "?", "d", "o", "g"]
。 - 繼續合并
"d"
和"o"
,得到["?T", "he", "?", "do", "g"]
。 - 最后合并
"do"
和"g"
,得到["?T", "he", "?", "dog"]
。
- 首先合并
- 映射到 ID:利用
vocab
將這些子詞轉換為 ID,例如[103, 4, 0, 500]
(假設"?T"
是未知詞,對應[UNK]
的 ID 為 103)。
這些id就是token id,可參考文章:大模型推理過程中的tokenazier,tokenid,詞向量之間的關系
- 初始狀態:文本被拆分成單個字符,比如
3. 二者的協同工作方式
- 訓練流程:
- 從所有出現的字符構成初始詞匯表。
- 統計訓練數據中字符對的出現頻率。
- 不斷合并最常出現的字符對,每合并一次就更新一次詞匯表。
- 重復上述合并過程,直到達到預設的詞匯表大小或者合并次數。
- 分詞流程:
- 把輸入文本拆分成字符序列。
- 按照
merges
規則進行合并,直到無法再合并或者達到最大子詞長度。 - 查找
vocab
,將子詞轉換為 ID。
4. 實際應用案例
假設 vocab
和 merges
已經訓練好,對句子 "Hello world!"
進行分詞:
- 初始字符:
["?", "H", "e", "l", "l", "o", "?", "w", "o", "r", "l", "d", "!"]
。 - 應用合并規則:
- 合并
"H"
和"e"
,得到["?", "He", "l", "l", "o", "?", "w", "o", "r", "l", "d", "!"]
。 - 合并
"l"
和"l"
,得到["?", "He", "ll", "o", "?", "w", "o", "r", "l", "d", "!"]
。 - 合并
"He"
和"ll"
,得到["?", "Hell", "o", "?", "w", "o", "r", "l", "d", "!"]
。 - 合并
"Hell"
和"o"
,得到["?", "Hello", "?", "w", "o", "r", "l", "d", "!"]
。 - 合并
"?"
和"Hello"
,得到["?Hello", "?", "w", "o", "r", "l", "d", "!"]
。 - 合并
"w"
和"o"
,得到["?Hello", "?", "wo", "r", "l", "d", "!"]
。 - 合并
"wo"
和"r"
,得到["?Hello", "?", "wor", "l", "d", "!"]
。 - 合并
"wor"
和"l"
,得到["?Hello", "?", "worl", "d", "!"]
。 - 合并
"worl"
和"d"
,得到["?Hello", "?", "world", "!"]
。 - 合并
"?"
和"world"
,得到["?Hello", "?world", "!"]
。
- 合并
- 轉換為 ID:假設
vocab
中有對應的項,那么結果就是[1000, 1001, 1002]
。
總結
- vocab:是子詞到 ID 的映射表,它能將文本轉換為模型可以處理的數字形式。
- merges:是子詞合并規則,它決定了如何從基礎字符構建出子詞。
- 相互關系:
merges
規則生成子詞,而vocab
負責存儲這些子詞并為它們分配 ID。
通過這種方式,子詞分詞器能夠在處理常見詞時保持完整性,同時將罕見詞拆分成有意義的片段,有效平衡了詞匯表的大小和表達能力。