大模型进行训练前,需要对语料进行 tokenize 处理。

BPE (Byte-pair encoding) 字节对编码算法

Byte-pair encoding 字节对编码 是一种简单的数据压缩形式,下面直接引用 wikipedia 的原文。

原始算法主要是为了压缩。大语言模型使用的修改后的算法。与原始 BPE 相比,修改后的 BPE 并非旨在最大限度地压缩文本,而是将明文编码为“token”(即自然数)。

原始算法

假设要编码的数据是:

aaabdaaabac

字节对“aa”出现的频率最高,因此会用数据中未使用的字节替换,例如“Z”。现存在以下数据及替换表:

ZabdZabac
Z=aa

然后使用字节对“ab”重复该过程,将其替换为“Y”:

ZYdZYac
Y=ab
Z=aa

剩下的唯一字面字节对只出现一次,编码过程可能就此结束。或者,该过程可以继续进行递归字节对编码,将“ZY”替换为“X”:

XdXac
X=ZY
Y=ab
Z=aa

该数据无法通过字节对编码进一步压缩,因为没有出现多次的字节对。要解压缩数据,只需按相反的顺序执行替换即可。

用于大模型的修改算法

大模型使用的修改算法,将明文编码为“token”(自然数)。最终预料库中的唯一 token 将会在一个 token 词汇表中。

上面的例子 假设我们对前面的例子“aaabdaaabac”进行编码,指定词汇表大小为 6,那么它首先会被编码为“0,0,0,1,2,0,0,0,1,0,3” ,词汇表大小为“a = 0 , b=1, d=2, c=3”。然后,它会按照前面的步骤进行,得到“4,5,2,4,5,0,3” ,词汇表大小为“a=0, b=1, d=2, c=3, aa=4, ab=5”。

到目前为止,这与之前基本相同。但是,如果我们仅指定词汇表大小为 5,那么处理过程将在词汇表大小“a=0, b=1, d=2, c=3, aa=4”处停止,因此该示例将被编码为“4,0,1,2,4,0,1,0,3” 。相反,如果我们指定词汇表大小为 8,那么它将被编码为“7,6,0,3”,词汇表大小为“a=0, b=1, d =2, c=3, aa =4, ab=5, aaab=6, aaabd=7”。

rust 实现

rustbpe 用 rust 实现了上面的算法,然后通过 pyo3 打包为 native python 插件模块,让 python 可以调用。