iT邦幫忙

2026 iThome 鐵人賽

DAY 4
0
Build on Google AI

在贏家書寫歷史之前:我所看見的 AI,與一位工程師共舞著系列 第 4

Day 04 | 少年 Token(中):SentencePiece 說文解字

  • 分享至 

  • xImage
  •  

來做個小實驗吧!我們實際來試看看自己透過 BPE 建立一個分詞器(Tokenizer),接著用我們訓練好的分詞器進行分詞(Tokenize)看看。這次我使用的是 Google 所開發的 SentencePiece 開源工具,這是一個專為神經網路與語言模型設計的開源分詞系統,它主要具備兩個功能:

  1. 訓練器(Trainer):從大量的純文字文章中統計字頻,自動合成出一本專屬的子詞字典( .model.vocab )。
  2. 處理器(Processor):在推論時載入剛剛訓練好的模型,把人類輸入的句子精確拆解成 Token ID 陣列。

也就是說,從編寫字典到實際切分文字,整個流程都可以靠它一手包辦。當中支援的訓練方法也包含了昨天說的 BPE 與 Unigram 等等。


1. 訓練階段 - 來訓練自己的 BPE 分詞器吧!

要做分詞實驗,首先需要訓練語料。我們就截取「Google 維基百科繁體中文條目」(約 5,800 字)來當作我們的訓練語料庫,裡面各種中英夾雜,是個很好的訓練資料。我所設定的字典大小是 5000 個詞,所以當它收集到第 5000 個最熱門的詞後就會停止收集。

import sentencepiece as spm

spm.SentencePieceTrainer.train(
    input="data/corpus.txt",
    model_prefix="models/model",
    vocab_size=5000,
    model_type="bpe",
    character_coverage=1.0,
    byte_fallback=True,
    remove_extra_whitespaces=False,
)

執行後,會印出 SentencePiece 底層 C++ 的 log,越上面是越早產生的 Token,最一開始它會先把自然語言處理常見的 Token <unk><s></s> 以及 <0x00><0x01> ... <0xFE><0xFF> 放到分詞器模型裡,也就是昨天提到的「字典非常薄」的階段。

https://ithelp.ithome.com.tw/upload/images/20260917/20183607JvnTxRIJ2s.png

接著開始把各種最常見的字或詞合併,慢慢組出一本有 5000 個詞彙的字典,這就是我們的分詞器模型。可以看到它會把像是「佩吉」、「股票」、「搜尋引擎」等高頻相鄰字元逐步合併成新詞。其中的 5886 是原本 wiki 的字數,整個訓練過程只花了大約 18 毫秒就能生成完成。

https://ithelp.ithome.com.tw/upload/images/20260917/201836076zrGrqjZIs.png

(1) 訓練結果 - 開箱詞表(.vocab)

打開生成的詞表檔案,可以發現每一列後面都有一個數字,值的範圍是小於等於 0 的數字,這數字代表 BPE 依合併頻率給予的優先級分數(Rank),越小表示越後面進去,表示分數越低,也代表出現頻率較低,而行號才是真正的 ID。整份詞表呈現清楚的三層結構:

  1. 頂層<unk>, <s>, </s> 等控制標記。
<unk>	0
<s>	0
</s>	0
  1. 中層:256 個十六進位的 <0x00><0xFF>。這是 UTF-8 的純 Byte 保底,確保遇到任何字典沒收錄的字元時都不會崩潰,因為最壞狀況就是靠 UTF-8 把字元組回來。
...
<0x00>	0
<0x01>	0
<0x02>	0
...
<0xFD>	0
<0xFE>	0
<0xFF>	0
...
  1. 底層:BPE 演算法從語料庫中統計出的合併字詞。畢竟是 Google 的 Wiki,可以看到 Google 這個字很快就被拼起來變成一個 Token 了。接著各種詞彙,長度甚至可以到 6 個字,意思就是說,假設輸入「一張十萬美元」這句話,它就只會被算作 1 個 Token。
le	-0
og	-1
oog	-2
oogle	-3
Google	-4
20	-5
公司	-6

...

創始人	-135
在網路	-136
旗下的	-137
2011	-138
2015	-139
▁199	-140
作業系統	-141

...

一張十萬美元	-2159
上市不會影響	-2160
不作惡的哲學	-2161
並在內部部落	-2162
並得到了保羅	-2163
中國人工智慧	-2164

...

頓	-4735
願	-4736
馬	-4737
駕	-4738
麻	-4739
齡	-4740

仔細看會發現 ▁199 前面有個小方塊符號,這其實是 SentencePiece 用來跳脫空白鍵的設計,讓它可以把空格當普通字元合併,以方便之後還原回去。

當中 UTF-8 可能就是另外一個故事了,UTF-8 這種編碼方式是現今最常見的編碼方式,他幾乎涵蓋了所有的字。至於他的運作原理,網路上已經有很多大神講的非常好了,如果大家敲碗的話,有機會我再整理看看「我所看見的 Unicode」吧 XDD。現在只需要知道,既然他用 Byte 來當最小的 token,UTF-8 就是用 1 到 4 個 Byte 的組合來進行編碼的。所以一段看不懂的句子,不論是哪一種語言或是 Emoji,最壞情況都能被拆解成 1 到 4 個 Byte。所以分詞器的 Token 至少都包含了所有 Byte,就可以透過 UTF-8 來解碼,最壞情況就是用 4 個 Token 來表示一個字,幾乎不會有這個分詞器沒辦法處理的句子。

(2) 下限報錯(設 500 報錯)

我嘗試將模型大小設成 500,結果系統直接噴 Vocabulary size is smaller than required_chars. 500 vs 1071。原因在於這篇維基語料中出現了 812 個「相異」字元,加上開啟 byte_fallback=True 所強制加入的 256 個 UTF-8 byte 保底與特殊控制符號,基礎字元就佔了 1,071 個位置。字典容量若小於 1,071,連基礎字元都裝不下,因此報錯。

(3) 上限報錯(設 50000 報錯)

接著我嘗試將模型大小設成 50,000,結果系統提示最大只能設到 8,007。這是因為 BPE 每合併一次,文本序列長度就減少 1。在這篇 5,800 多字的文章中,加上標點符號隔離與長度限制,所有可能產生的不重複子字串在去重後總共只會有 8,007 種。語料庫規模有限時就根本無法從中生出更多詞彙。


2. 推論階段:三種命中場景實測(Inference)

我們在推論時刻意輸入以下三種句子,來刻意命中或沒命中我們分詞庫的詞,結果如下:

  • 幾乎未命中:輸入語料中完全沒出現過的「𠮷野家喫茶店 🤖✨」,可以看到原本字串長度是 9。除了「家」因為碰巧在維基語料庫中出現過而保留為獨立 Token 外,其餘生僻字元與 Emoji 分詞器在語料庫裡完全沒看過,所以全部退化成 3 到 4 個 Byte 碎片的 Token,但在 decode 時依然能依據 UTF-8 的位元規則還原原話。
  • 部分命中:部分常見字詞被合併,冷門的字維持單字,這裡可以看到像「微軟」、「機器」、「人」這種詞就會被當作一個 Token,所以總 Token 數是比字串長度小的。
  • 大量命中:輸入 Google 語料中的高頻語句(如「Google搜尋引擎由佩吉在史丹佛大學創立,口號是不作惡」),核心名詞被當作 1 個 Token,總 Token 數是比輸入字串短很多,展現顯著的壓縮效果。

https://ithelp.ithome.com.tw/upload/images/20260917/20183607iNeBZB0pHh.png

這裡也可以想像為什麼 一般使用 LLM 時,中文字時常比英文貴? 主要原因並不是因為中文 UTF-8 編碼要用比較多 byte 表示,而是因為當初 LLM 模型開發商在訓練分詞器時使用的語料中,英文的佔比遠高於中文。就如這兩天所說的,BPE 看的就是詞的「出現頻率」,所以中文在訓練語料中出現頻率相對少很多的話,被收錄進分詞器裡的中文詞彙就會比較少。雖然現代主流大模型為了照顧多語言,已經把字典擴充到十幾萬詞,讓常見中文單字大多擁有獨立的 Token,但多字成詞的比例依然遠低於英文,因此傳達相同資訊量時,中文往往需要耗費更多 Token,其他非英語的語言也常面臨類似的問題。


看完推論結果後,心中自然浮出一個問題:當一段長文字送進分詞器時,底層怎麼決定在哪裡切一刀當作一個 Token 的,哪裡該合併?這個演算法大家心中可能已經有個答案了,我們就留到明天繼續探討吧!明天見~


參考資料


上一篇
Day 03 | 少年 Token(上):BPE 分詞演算法的奇幻起點
下一篇
Day 05 | 少年 Token(下):從 Token 到 Embedding
系列文
在贏家書寫歷史之前:我所看見的 AI,與一位工程師共舞著10
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言