论文:Neural Machine Translation of Rare Words with Subword Units
作者:Rico Sennrich, Barry Haddow, Alexandra Birch
时间:2016
一、完整代码
这里我们使用python仅对BPE做一个简单的实现
import re, collections def get_stats(vocab): pairs = collections.defaultdict(int) for word, freq in vocab.items(): symbols = word.split() for i in range(len(symbols) - 1): pairs[symbols[i], symbols[i + 1]] += freq return pairs def merge_vocab(pair, v_in): v_out = {} bigram = re.escape(' '.join(pair)) p = re.compile(r'(?<!\S)' + bigram + r'(?!\S)') for word in v_in: w_out = p.sub(''.join(pair), word) v_out[w_out] = v_in[word] return v_out if __name__ == '__main__': vocab = {'l o w </w>': 5, 'l o w e r </w>': 2, 'n e w e s t </w>': 6, 'w i d e s t </w>': 3} num_merges = 10 for i in range(num_merges): pairs = get_stats(vocab) best = max(pairs, key=pairs.get) vocab = merge_vocab(best, vocab) print(vocab)
二、论文解读
word-level
在NMT
任务上的不足:
- a back-off to a dictionary look-up:用字典中相似且存在于
vocabulary
的词计算; - copy:对于名字来说处理有效,但是词的形态可能会发生改变,而翻译又需要词型的信息;
这篇文章主要介绍了两个方法:
- 使用
subwords
而不是word
,可以有效的提高NMT
的能力; byte pair encoding
,利用压缩算法来构建词汇表;
2.1 模型架构
encoder:一个双向的GRU网络,隐藏层的结果合并作为最终的隐藏层;
decoder:RNN,利用前馈神经网络做对其模型输出结果;
2.2 BPE
字节对编码(BPE)(Gage,1994)是一种简单的数据压缩技术,它迭代地用一个未使用的字节替换序列中最频繁的字节对。我们将该算法用于分词。我们不合并频繁的字节对,而是合并字符或字符序列。
首先,我们用字符词汇表初始化字符词汇表,并将每个单词表示为一个字符序列,再加上一个特殊的词末字符“·”,这允许我们在翻译后恢复原始的序列。我们迭代地计算所有的字符对,并将每次出现的最频繁的字符对(“A”,“B”)替换为一个新的字符“AB”。每个合并操作都会产生一个新的字符,它表示一个字符n-gram。频繁的字符n-克(或整个单词)最终被合并成一个单一的字符,因此BPE不需要候选名单。最终的字符词汇表大小等于初始词汇表的大小,再加上合并操作的数量——后者是算法中唯一的超参数。
实现代码如下:
import re, collections def get_stats(vocab): pairs = collections.defaultdict(int) for word, freq in vocab.items(): symbols = word.split() for i in range(len(symbols) - 1): pairs[symbols[i], symbols[i + 1]] += freq return pairs def merge_vocab(pair, v_in): v_out = {} bigram = re.escape(' '.join(pair)) p = re.compile(r'(?<!\S)' + bigram + r'(?!\S)') for word in v_in: w_out = p.sub(''.join(pair), word) v_out[w_out] = v_in[word] return v_out if __name__ == '__main__': vocab = {'l o w </w>': 5, 'l o w e r </w>': 2, 'n e w e s t </w>': 6, 'w i d e s t </w>': 3} num_merges = 10 for i in range(num_merges): pairs = get_stats(vocab) best = max(pairs, key=pairs.get) vocab = merge_vocab(best, vocab) print(vocab)
学习两种独立的编码,一种用于源句子,一种用于目标句子;可以使文本和词汇大小方面更紧凑,更能保证每个子词单元都在各自语言的训练文本中看到;
学习两个词汇的联合编码,提高了源句子和目标句子分割之间的一致性;
三、过程实现
论文整体比较简单,框架已经过时,没有实现的必要;
四、整体总结
这篇文章主要介绍了两个方法:
- 使用
subwords
而不是word
,可以有效的提高NMT
的能力; byte pair encoding
,利用压缩算法来构建词汇表;