大模型进行训练前,需要对语料进行 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 可以调用。