Byte Pair Encoding · BPE

把常一起出現的
黏起來

整個演算法只有一條規則,而且你三秒就懂。難的是它跑了幾萬次以後,長出來的東西出乎意料地像語言學。

n + e → ne 一起出現 15 次

找出最常相鄰的兩個 → 合成一個新符號 → 回頭再找一次 → 重複。

先講為什麼需要它。

要把文字餵給模型,得先切成一塊一塊。兩個最直覺的切法,兩邊都不能用。

切成字母
unbelievable
清單只要幾十個 — 但句子變超長,模型要記很遠以前的東西。
切成整個詞
unbelievable
短得漂亮 — 但清單永遠不夠用,遇到沒收錄的詞就只能吐出「不認識」。
BPE — 中間路線(示意)
unbelievable
常見的整塊留著,罕見的拆成碎片。永遠不會遇到不認識的字 — 最糟也能一個字母一個字母拼出來。

按下去,看它自己長出詞尾。

下面是九個英文詞和它們的出現次數。一開始全部拆成單一字母,· 代表詞的結尾。每按一次,就合併當下最常相鄰的那一對。

第 0 / 14 步
合併規則0
總共幾塊185
不同的塊11

「總共幾塊」= 把這九個詞按出現次數全部攤開來要用掉幾個 token。

它沒學過文法,卻切出了詞尾。

跑完 14 步,這些東西自己浮出來 — 沒有人告訴過它英語有詞綴。

low new wid / er· est·

詞幹和詞尾,分得乾乾淨淨。純粹是因為它們常常黏在一起,不是因為它懂構詞。

而這就是它露餡的地方。

那中文呢?

英文靠空格分詞,中文沒有。所以現在的做法更暴力:直接在 UTF-8 的位元組上跑 BPE,根本不管什麼是字。

語 = E8AA9E → ?

一個漢字是 3 個位元組。常見的字在訓練時被合併成 1 塊,罕見的字就得花上 2、3 塊拼出來。同樣一句話,中文用掉的 token 常常比英文多 — 這也是為什麼中文用 API 有時候比較貴。

一條「把常見的黏起來」的規則,
跑上幾萬次,就長成了一整套詞彙表。