用例子解释bpe(字节对编码)?

时间:2018-05-29 11:28:51

标签: nlp

有人可以帮助解释 bpe模型背后的基本概念吗?除https://newsapi.org之外,目前还没有那么多解释。

到目前为止我所知道的是,通过将稀有和未知单词编码为子单元序列,它可以在开放词汇表上进行NMT模型翻译。

但是我希望在不通过论文的情况下大致了解它是如何工作的。

3 个答案:

答案 0 :(得分:1)

BPE 是三种以自动方式处理未知单词问题的算法之一:字节对编码、一元语言建模、WordPiece,并且 BPE 标记化模式有两个部分:标记学习器和标记分割器。

<块引用>

标记学习器采用原始训练语料库(有时粗略地预先分成单词,例如通过空格)并归纳出词汇表,即一组标记。标记分割器将原始测试句子分割成词汇表中的标记。

该算法有一个参数 k,表示最终词汇表中的 k 个合并或 k 个新符号。

让我们使用这一行来训练 BPE:Pen Penapple Apple Pen 改编自 PPAP,并展示测试数据中的未知/稀有“词”penapplepenapplepen 如何自动缩减为已知的子词单元。

学习

enter image description here

首先,经过一些预处理(案例映射,基于正则表达式的预标记化,并添加词尾符号_),我们获得以下字符串C(作为我们的语料库)及其频率(频率:字符串):

2: p e n _    
1: p e n a p p l e _  
1: a p p l e _  

词汇V是[_, p, e, n, a, l]

现在让我们运行上面伪代码中的第一轮for循环:

p, e <- most frequent pair in {(p, e): 3, (e, n): 3, (n, _): 2, (a, p): 2, (p, p): 2, (p, l): 2, (l, e): 2, (e, _): 2, (n, a): 1}    
pe <- p + e   
[_, p, e, n, a, l, pe] <- [_, p, e, n, a, l] + pe    
C becomes this: 
    2: pe n _    
    1: pe n a p p l e _  
    1: a p p l e _ 

让我们按如下方式运行第二次合并:

p, e <- most frequent pair in {(pe, n): 3, (n, _): 2, (a, p): 2, (p, p): 2, (p, l): 2, (l, e): 2, (e, _): 2, (n, a): 1}    
pen <- pe + n   
[_, p, e, n, a, l, pe, pen] <- [_, p, e, n, a, l, pe] + pen    
C becomes this: 
    2: pen _    
    1: pen a p p l e _  
    1: a p p l e _ 

如果我们将 k 设为 N >= 9,这里是下一次合并:

Merge          Current V 
(pen, _)       [_, p, e, n, a, l, pe, pen, pen_]  
(a, p)         [_, p, e, n, a, l, pe, pen, pen_, ap]
(ap, p)        [_, p, e, n, a, l, pe, pen, pen_, ap, app]
(app, l)       [_, p, e, n, a, l, pe, pen, pen_, ap, app, appl]
(appl, e)      [_, p, e, n, a, l, pe, pen, pen_, ap, app, appl, apple]
(apple, _)     [_, p, e, n, a, l, pe, pen, pen_, ap, app, appl, apple, apple_]
(pen, apple_)  [_, p, e, n, a, l, pe, pen, pen_, ap, app, appl, apple, apple_, penapple_]

我们看到经过 9 次合并迭代后,C 中没有相邻对。

解析

<块引用>

令牌解析器只是在测试数据上运行我们从训练数据中学到的合并,贪婪地,按照我们学习它们的顺序。 (因此测试数据中的频率不起作用,只影响训练数据中的频率)。

在这一步中,我们使用以下语句测试解析器:Applepen PenapplePen。像往常一样,我们做我们在训练步骤中做的预处理,得到:

a p p l e p e n _   
p e n a p p l e p e n _ 

并遵循合并顺序:

(p, e), (pe, n), (pen, _), (a, p), (ap, p), (app, l), (appl, e), (apple, _), (pen, apple_)

首先,(p, e)。我们合并测试数据中的 p 和 e 得到:

a p p l e pe n _    
pe n a p p l e pe n _  

其次,(pe, n) 并得到:

a p p l e pen _    
pen a p p l e pen _ 

.....
在所有 9 轮合并之后我们得到(如果 k <= 9 我们只在这一步应用前 k 次合并;如果 k 是 2 参考 this answer):

apple pen_    
pen apple pen_

最后分词化的测试句是[apple, pen_, pen, apple, pen_],未知(在训练数据中没见过)词penapplepen也可以分开。

参考:

  1. Neural Machine Translation of Rare Words with Subword Units
  2. Speech and Language Processing
  3. PPAP (Pen Pineapple Apple Pen)

答案 1 :(得分:0)

随机找到了这个老问题,只是我最近尝试解释它:

https://narsil.github.io/2019/05/16/model-based-bpe-encodings.html

希望这会有所帮助。

答案 2 :(得分:0)

NLP中的字节对编码是一种中间解决方案,与基于单词的令牌相比,它可以减少词汇量,并在单个令牌中覆盖尽可能多的频繁出现的字符序列,而无需代表使用基于长字符的令牌。

最初,每个字符都由一个令牌引用,并且合并操作的数量是构建BPE词汇表的超参数。

让我们考虑一下这句话:

“他有一只猫”和“那只猫坐在垫子上”

我们可以按如下方式构建字符词汇表:

['a','c','d','e','g','h','i','m','n','o','s','t ']

现在我们可以列出这些对及其出现的位置:

he: 3 (he, the*2)
ha: 1 (had)
ad: 1 (had)
ca: 2 (cat*2)
at: 3 (cat*2, mat)
th: 2
is: 1
si: 1
it: 1
ti: 1
in: 1
ng: 1
on: 1
ma: 1

现在,由于“ he”和“ at”对在词汇表中出现频率最高,因此可以将其组合(合并操作)并添加到词汇表中。

更新的词汇表: ['a','c','d','e','g','h','i','m','n','o','s','t','他,'在']

现在,如果可以使用单个标记引用词汇中出现的较长单词,即使用单个标记而不是两个字符标记来引用“ he”或“ at”。

因此:句子:

  1. “他有一只猫”和2。“那只猫坐在垫子上”

可以如下标记:

  1. [{'he','h','a','d','a','c','at']
  2. ['t','he','c','at','i','s','s','i','t','t','i ','n','g','o','n','t','he','m','at']

此外,可以通过识别最频繁出现的对来重复进行此处理:

ha: 1 (had)
ad: 1 (had)
c'at': 2 (cat*2)
th: 2
is: 1
si: 1
it: 1
ti: 1
in: 1
ng: 1
on: 1
m'at': 1

由于c'at'一词的出现频率最高,因此可以将其组合成一个新的词汇,如下所示:

['a','c','d','e','g','h','i','m','n','o','s','t ','他','在','猫']

因此有了新的令牌化:

  1. [{'he','h','a','d','a','cat']
  2. ['t','he''cat','i','s','s','i','t','t','i','n ','g','o','n','t','he','m','at']

因此,随着合并操作数量的增加,词汇量会增加,但用于表示给定文本的标记数量会减少。