Subword策略,很有用的论文。BERT也使用到了,有对应的
tokenization.py
Neural Machine Translation of Rare Words with Subword Units
背景
摘要
NMT处理的词汇表是定长的,但是实际翻译却是OOV(out of vocabulary)的。以前是把 新词汇加到词典里去。本文是提出一种subword单元的策略,会把稀有和未知词汇以subword units序列来进行编码,更简单更有效。
会介绍不同分词技术的适用性,包括简单的字符n元模型和基于字节对编码压缩算法的分词技术。也会以经验说明subword模型比传统back-off词典的方法好。
简介
NMT模型的词汇一般是30000-5000,但是翻译却是open-vocabulary的问题。很多语言富有信息创造力,比如凝聚组合等等,翻译系统就需要一种低于word-level的机制。
Word-level NMT的缺点
对于word-level的NMT模型,翻译out-of-vocabulary的单词会回退到dictionary里面去查找。有下面几个缺点
- 种技术在实际上使这种假设并不成立。比如源单词和目标单词并不是一对一的,你怎么找呢
- 不能够翻译或者产生未见单词
- 把unknown单词直接copy到目标句子中,对于人名有时候可以。但是有时候却需要改变形态或者直译。
Subword-level NMT
我们的目标是建立open-vocabulary的翻译模型,不用针对稀有词汇去查字典。事实证明,subword模型效果比传统大词汇表方法更好、更精确。Subword神经网络模型可以从subword表达中学习到组合和直译等能力,也可以有效的产生不在训练数据集中的词汇。本文主要有下面两个贡献
- open-vocabulary的问题可以通过对稀有词汇使用subword units单元来编码解决
- 采用Byte pair encoding (BPE) 算法来进行分割。BPE通过一个固定大小的词汇表来表示开放词汇,这个词汇表里面的是变长的字符串序列。这是一种对于神经网络模型非常合适的词分割策略。
神经机器翻译
NMT是使用的Bahdanau的Attention模型。Encoder是双向RNN,输入\(X=(x_1, x_2, \cdots, x_m)\),会把两个方向的隐状态串联起来得到annotation向量\(\mathbf x\)。实际上是一个矩阵,对于单个\(x_j\)来说,对应的注释向量是\(\mathbf{x}_j\)。
Decoder是一个单向的RNN,预测\(Y=(y_1, y_2, \cdots, y_n)\)。 预测\(y_i\) 时,需要:
- 当前的隐状态\(s_i\)
- 上一时刻的输出\(y_{i-1}\)作为当前的输入
- 语义向量\(\mathbf c_i\) 。语义向量是由所有的注释向量\(x_j\) 加权求和得到的。权就是对齐概率\(\alpha_{ij}\)。 即\(\mathbf c_i = \sum_{j=1} ^ m \alpha_{ij} \mathbf x_j\)
详情请看谷歌论文里面的介绍或者Bahdanau的论文。
Subword 翻译
下面词汇的翻译是透明的(transparent,明显的)
- 命名实体。如果两个语言的字母表相同,可以直接copy到目标句子中去,也可以抄写音译直译等。
- 同源词和外来词。有着共同的起源,但是不同的语言表达形式不同,所以character-level翻译规则就可以了。
- 形态复杂的词语。包含多个语素的单词,可以通过单独翻译语素来翻译。
总之,通过subword单元表示稀有词汇对于NMT来说可以学到transparent翻译,并且可以翻译和产生未见词汇。
相关工作
对于SMT(Statistical Machine Translation)来说,翻译未见单词一直是研究的主题。
很多未见单词都是人名,如果两种语言的字母表一样,那么可以直接复制过去。如果不一样,那么就得音译过去。基于字符(character-based)的翻译是比较成功的。
形态上很复杂的单词往往需要分割,这里有很多的分割算法。基于短语的SMT的分割算法是比较保守的。而我们需要积极的细分,让网络可以处理open-vocabulary,而不是去求助于背字典。 怎么选择subword units要看具体的任务。
提出了很多这样的技术:生成基于字符或者基于语素的定长的连续的词向量。于此同时,word-based的方法并没有重大发现。现在的注意力机制还是基于word-level的。我们希望,注意力机制能从我们变长表达中收益:网络可以把注意力放在不同的subword units中。 这可以突破定长表达的信息传达瓶颈。
NMT减少词汇表可以大大节省时间和增加空间效率。我们也想要对一个句子更紧凑的表达。因为文本长度增加了,会减少效率,也会增加模型传递信息的距离。(hidden size?)
权衡词汇表大小和文本长度,可以用未分割单词列表,subword 单元表达的稀有词汇。作为一个代替,Byte pair encoding就是这样的一种分割算法,可以学到一个词汇表,同时对文本有很好的压缩率。
Byte Pair Encoding
Byte pair encoding是一种简单的数据压缩技术,它把句子中经常出现的字节pairs用一个没有出现的字节去替代。我们使用这种算法去分割单词,但我们合并字符或者字符序列。
算法步骤
算法步骤如下:
- 初始化符号词表。用所有的字符加入到符号词表中。对所有单词的末尾加入特殊标记,如
-
。翻译后恢复原始的标记。 - 迭代对所有符号进行计数,找出次数最多的(A, B),用AB代替。
- 每次合并,会产生一个新的符号,代表着n-gram字符
- 常见的n-grams字符(或者whole words),最终会被合并到一个符号
- 最终符号词表大小=初始大小+合并操作次数。操作次数是算法唯一的超参数。
不用考虑不在训练集里面的pair,为每个word根据出现频率设置权重。
和传统的压缩算法(哈夫曼编码)相比,我们的以subword 单元堆积的符号序列依然是可以解释的,网络也可以翻译和产生新的词汇(训练集没有见过的)。
下面是代码
1 | def process_raw_words(words, endtag='-'): |
单独BPE
为目标语言和原语言分别使用BPE去计算词典。从文本和词汇表大小来说更加紧凑,能保证每个subword单元在各自的训练数据上都有。同样的名字在不同的语言中可能切割的不一样,神经网络很难去学习subword units之间的映射。
Joint BPE
为目标语言和原语言一起使用BPE,即联合两种语言的词典去做BPE。提高了源语言和目标语言的分割一致性。训练中一般concat两种语言。
评估
有两个重要问题
- subword units表达稀有词汇,是否真的对翻译有效果?
- 根据词汇表大小,文本长度,翻译质量,怎样分割才是最好的?
我们的使用WMT2015的数据,使用BLEU来评判结果。英语-德语:
- 420万句子对
- 1亿个token
英语-俄罗斯语:
- 260万句子对
- 5000万个token
minibatch-size是80,每个epoch都会reshuffle训练数据。训练了7天,每12个小时存一次模型,取最后4个模型再单独训练。分别选择clip 梯度是5.0和1.0,1.0效果好一些。最终是融合了8个模型。
Beam search的大小是12,使用双语词典进行快速对齐,类似于对稀有词汇查找词典,也会用词典去加速训练。
Subword统计
我们的目标是通过一个紧凑的固定大小的subword词典去代表一个open-vocabulary,并且能够有效的训练和解码。
一个简单的基准就是把单词分割成字符n-grams 。n的选择很重要,可以在序列长度(tokens)和词汇表大小(size)之间做一个权衡。序列的长度会增加许多,一个比较好得减少长度的方法就是使用k个最常见的未被分割的词列表。只有unigram(n=1,一元模型)表达才能真正实现open-vocabulary,但是实际上效果却并不好。Bigram效果好,但是不能产生测试集中的tokens。
BPE符合open-vocabulary的目标,并且合并操作可以应用于测试集,去发现未知符号的分割。与字符集模型的主要区别在于,BPE更紧凑的表示较短序列,注意力模型可以应对变长的单元。
分割方法 | tokens | types | unk | merge次数 |
---|---|---|---|---|
BPE | 112 m | 63000 | 0 | 59500 |
BPE(joint) | 111 m | 82000 | 32 | 89500 |
实际上,NMT词汇表中,并不会包含不常见的subword单元,因为里面有很多噪声。
name | seg | shotlist | s-v | t-v | S-BLEU | BLEU | CHAR-F3 | CHAR-F3 | F1 | F1 | F1 |
---|---|---|---|---|---|---|---|---|---|---|---|
BPE-60k | BPE | 无 | 60000 | 60000 | 21.5 | 24.5 | 52.0 | 53.9 | 58.4 | 40.9 | 29.3 |
BPE-J60k | BPE(joint) | 无 | 90000 | 90000 | 22.8 | 24.7 | 51.7 | 54.1 | 58.5 | 41.8 | 33.6 |
翻译评估
所有的subword系统都不会去查字典。使用UNK表示模型词典以外的单词,OOV表示训练集里面没有的单词。