字节对编码(Byte-Pair Encoding,BPE)最初被开发为一种文本压缩算法,后来被 OpenAI 用于 GPT 模型预训练时的分词。许多 Transformer 模型都使用了该方法,包括 GPT、GPT-2、RoBERTa、BART 和 DeBERTa。
相较于传统的词表构建方法:
- 更加紧凑
- 传统词表: 通常是基于词的,每个词对应一个唯一的索引。对于大规模文本,词表会非常庞大,导致模型参数过多,计算量增加。
- BPE 词表: 通过不断合并高频字节对,将词拆分为子词,从而构建一个更小的词表。这使得模型的参数量减少,计算效率提高。
- 2. 减少数据的稀疏性
- 传统词表: 对于低频词或未登录词,在词表中没有对应的索引,这会导致数据稀疏,影响模型的训练效果。
- BPE 词表: 通过将词拆分为子词,即使是低频词或未登录词,也可以通过子词的组合来表示,从而减轻数据稀疏的问题。
- 3. 处理未登录词
- 传统词表:对于未在词典中出现的词,通常会用一个特殊的符号(如
<UNK>
)代替。这种处理方式简单粗暴,但会损失大量信息,影响模型的性能。 - BPE 词表:当遇到未见词时,BPE会尝试将其分解为多个已知的子词。例如,”智能手机”可能被分解为”智能”和”手机”。
- 传统词表:对于未在词典中出现的词,通常会用一个特殊的符号(如
Paper: https://arxiv.org/pdf/1508.07909.pdf
1. 训练过程
BPE 首先统计语料库中每个单词出现的次数,假设我们的语料库使用了以下 5 个单词:
"hug", "pug", "pun", "bun", "hugs"
接下来,通过提取这些单词中使用的所有符号来构建词汇表:
["b", "g", "h", "n", "p", "s", "u"]
在获得初始词汇表后,我们通过学习合并规则来添加新词,直到达到所需的词汇表大小。合并规则是将现有词汇表中相邻的两个元素合并成一个新的元素。因此,一开始的合并会创建由 2 个字符组成的词元,随着训练的进行,逐渐形成更长的子词。
在分词器训练的任何步骤中,BPE 算法都会统计出现频率最高的连续两个词元。这个最频繁的词对将被合并,回到之前的例子,假设这些单词有以下的频率:
("hug", 10), ("pug", 5), ("pun", 12), ("bun", 4), ("hugs", 5)
意思是 “hug” 在语料库中出现了10次,”pug” 出现了5次,”pun” 出现了12次,”bun” 出现了4次,而 “hugs” 出现了5次。我们从将每个单词拆分成字符开始训练(这些字符组成了我们的初始词汇表),这样我们可以将每个单词视为一个词元列表:
("h" "u" "g", 10), ("p" "u" "g", 5), ("p" "u" "n", 12), ("b" "u" "n", 4), ("h" "u" "g" "s", 5)
然后我们查看成对的字符。字符对 (“h”, “u”) 出现在单词 “hug” 和 “hugs” 中,总共在语料库中出现了15次。然而,这并不是最频繁的字符对,最频繁的是 (“u”, “g”),它出现在 “hug”、”pug” 和 “hugs” 中,总共在语料库中出现了20次。
因此,分词器学习的第一个合并规则是 (“u”, “g”) -> “ug”,这意味着 “ug” 将被添加到词汇表中,并且这个字符对会在语料库中的所有单词中被合并。在这个阶段结束时,词汇表和语料库将变成这样:
词表: ["b", "g", "h", "n", "p", "s", "u", "ug"] 语料: ("h" "ug", 10), ("p" "ug", 5), ("p" "u" "n", 12), ("b" "u" "n", 4), ("h" "ug" "s", 5)
现在我们有一些字符对生成了超过 2 个字符的词元:例如,字符对 (“h”, “ug”) 出现在语料库中15次。然而,此时最频繁的字符对是 (“u”, “n”),它在语料库中出现了16次,因此分词器学习的第二个合并规则是 (“u”, “n”) -> “un”。将其添加到词汇表并合并所有现有的出现后,我们得到了:
词表: ["b", "g", "h", "n", "p", "s", "u", "ug", "un"] 语料: ("h" "ug", 10), ("p" "ug", 5), ("p" "un", 12), ("b" "un", 4), ("h" "ug" "s", 5)
现在最频繁的字符对是 (“h”, “ug”),因此我们学习到的合并规则是 (“h”, “ug”) -> “hug”,这为我们带来了第一个由三个字母组成的词元。合并之后,语料库变成了这样:
词表: ["b", "g", "h", "n", "p", "s", "u", "ug", "un", "hug"] 语料: ("hug", 10), ("p" "ug", 5), ("p" "un", 12), ("b" "un", 4), ("hug" "s", 5)
重复进行如上操作,直到达到所需的词汇表大小。
注意:实际在训练分词器之前,我们会在每个单词后面增加一个特殊的 token (例如:_ 或者 </w>)。
来源:https://huggingface.co/learn/nlp-course/en/chapter6/5?fw=pt
2. 正则化
BPE-dropout 是一种基于字节对编码(Byte Pair Encoding,BPE)的自然语言处理算法,主要用于文本的子词分割。它的核心思想是在传统的BPE算法基础上引入了一种随机丢弃合并操作的机制,以提高模型的鲁棒性和泛化能力。
BPE: 通过不断合并出现频率最高的子词对来构建词典,从而实现数据压缩和语言模型的改进。 dropout: 借鉴神经网络中的 dropout 技术,通过随机丢弃部分合并操作,使得模型在训练过程中能够接触到更多的子词组合,从而提高模型的鲁棒性和泛化能力。
在实际进行中,每一次迭代都会产生多个待合并的组合,每一个组合都有概率 p 被丢弃。最后,从剩余的所有待合并的组合中选择出现频率最高的完成合并。