解决未登录词问题的一种方法。
在做nlp的时候,很多时候我们会对语料做一个预处理,生成语料的一个字典。为了不让字典太大,我们通常只会把出现频次大于某个阈值的词丢到字典里边,剩下所有的词都统一编码成#UNK
。这是很经典 很朴素的做法,这种方法不能解决未登录词的问题。未登录词是指 在验证集或测试集出现了训练集从来没见到过的单词。这种未登录词对分词,机器翻译性能影响很大。
于是有学者就提出,ε=(´ο`*)))唉,我们不能这么简单粗暴,我们还是应该看看怎么去解决这种未登录词或者说频率很低的词的问题。在机器翻译领域,常见的方法有:给低频次再设置一个back-off 表呀,当出现低频次的时候就去查表;或者就不做word-level的东西,转而做char-level的东西,也就是说 既然以词为对象进行建模会有未登录词的问题,那么我们以单个字母或单个汉字为对象建模不就可以解决了嘛?因为不管是什么词它肯定是由若干个字母组成的。
这两种方法都有其优势和劣势。第一种方法,简单直接,若干back-off做的很好的话,对低频词的翻译会有很大的提升;但是这种方法依赖于back-off表的质量,而且也没法处理非登录词问题。第二种方法,的确可以从源头解决未登录词的问题,但是这种模型粒度太细,一般出来的效果不是特别好。
于是2016年 rich 这几个人就提出了基于subword来生成词典的方法。
论文:https://arxiv.org/abs/1508.07909 Neural Machine Translation of Rare Words with Subword Units
他的核心思想是综合word-level和char-level的优势,从语料中学习到所有词里边 频次高的 字符串子串。然后把这些频次高的字符串子串收集起来形成一个字典。这个字典里边,既存在char-level级别的子串,也存在word-level级别的子串。然后把这个字典用于模型的训练。论文在寻找频次高的子串时,使用到了bytes-pair-encoding 算法,只不过是把子串进行encoding而已。这个算法也很简单:每次合并在语料中 同一个词里面、相邻的、出现频率最高的两个子串。decoding的时候,根据生成的voc 做相应的替换。
作者已经把论文的subword-nmt开源了,地址:https://github.com/rsennrich/subword-nmt ,但是比较不好的是github上的readme是老版本的,尚未更新。
使用pip3安装
pip3 install subword-nmt
先准备一个语料库。例如:
链接:https://pan.baidu.com/s/1BAWDeAw5QYXS7xCrLIBIAw
提取码:kfy9
subword-nmt learn-joint-bpe-and-vocab -i .\en.txt -o .\code.file --write-vocabulary voc.txt
说明:
-i
后面的参数是输入文件名-o
后面是输出的code文件文件名--write-vocabulary
后面是输出字典的文件名其他参数说明:
usage: subword-nmt learn-joint-bpe-and-vocab [-h] --input PATH [PATH ...]
--output PATH [--symbols SYMBOLS]
[--separator STR]
--write-vocabulary PATH
[PATH ...] [--min-frequency FREQ]
[--total-symbols] [--verbose]
learn BPE-based word segmentation
optional arguments:
-h, --help show this help message and exit
--input PATH [PATH ...], -i PATH [PATH ...]
Input texts (multiple allowed).
--output PATH, -o PATH
Output file for BPE codes.
--symbols SYMBOLS, -s SYMBOLS
Create this many new symbols (each representing a
character n-gram) (default: 10000))
--separator STR Separator between non-final subword units (default:
'@@'))
--write-vocabulary PATH [PATH ...]
Write to these vocabulary files after applying BPE.
One per input text. Used for filtering in apply_bpe.py
--min-frequency FREQ Stop if no symbol pair has frequency >= FREQ (default:
2))
--total-symbols, -t subtract number of characters from the symbols to be
generated (so that '--symbols' becomes an estimate for
the total number of symbols needed to encode text).
--verbose, -v verbose mode.
我们可以看一下生成的code.file和voc.txt
code.file:
#version: 0.2
t h
i n
th e
a n
r e
t i
e n
o n
an d
e r
···
就是做merge操作时的输出,先是单个单个字母的合并,例如第一行:t h 表示可以把字母t和字母h合并起来变成 th,然后把th添加到字典voc.txt里面去。
voc.txt部分内容:
···
ary 14
apart 14
conscientiously 14
flight 14
association 14
represent 14
th 14
activity 14
standard 14
call 14
jia 14
solid 14
seven 14
···
可以看到有th出现。
在使用learn-bpe功能得到code以及字典后,可以使用apple-bpe来对语料进行解码。
subword-nmt apply-bpe -i .\en.test.txt -c .\code.file -o result.txt
说明:
-i
后面是输入的待解码文件名-c
后面跟着learn-bpe步骤得到的code文件-o
结果输出文件我们可以查看结果:
beijing , 1 mar ( xinhua ) -- tian feng@@ shan , former heilongjiang governor who is 5@@ 9 years old , was appointed minister of land and resources today .
tian feng@@ shan , who was born in zhao@@ yuan county , heilongjiang province , took part in work since july 196@@ 1 and joined the cpc in march 1970 .
this should be a natural process set off by economic development ; the " third tier construction " of the 1960s involving fac@@ tory relocation was something entirely different .
we must also realize however that from the angle of changing the pattern of resource allocation , we have not yet made the big breakthrough in reform .
with regard to joining the world trade organization , one recent reaction has been blind optim@@ ism and the belief that china will profit whatever it does .
since these areas where objective conditions are not particularly good can achieve this , other areas where conditions are better can naturally do the same .
the objective trend of globalization is calling for international cooperation on a global scale , and a global cooperation has far exceeded the scope of the economy .
就会自动根据bpe生成的code文件对语料进行分割,依照voc.txt进行分割。
如果需要把bpe使用到神经网络中,很简单 使用subword-nmt apply-bpe
对输入语料进行解码得到decode.txt,然后在程序载入subword-nmt生成的字典voc.txt。然后按照机器翻译正常处理语料的套路来做即可:读入decode.txt的每个单词,查找它在voc.txt的字典中的编号。