OpenNMT 2.0.0rc1 使用手册
最近在用OpenNMT训练机器翻译模型。OpenNMT 全称 Open-Source Neural Machine Translation,是https://nlp.seas.harvard.edu/ 和SYSTRAN 共同开发的适用于机器翻译的集成库(现在由SYSTRAN和 Ubiqus 维护)。
OpenNMT有两个版本,分别为依赖PyTorch 和TensorFlow的。从使用人数上来说,PyTorch用的人多得多,更新的速度也快一点,所以就选了OpenNMT-py 的版本。据说Academia的趋势也是PyTorch增多,考虑复用的话PyTorch是你的好朋友 :p
不得不说,OpenNMT开发得确实快,版本更新也快,眼睁睁看着它两个月更新一个版本,也是挺6。但这也导致文档update的速度跟不上开发的速度 🐶
所以本文记录下从头训练一个NMT的pipeline,也记录一些useful 的七七八八。
Why OpenNMT 2.0.0rc
版本更新挺快,之前的version比较稳定的是1.2.0,但最近用起来还是有点不趁手。而且2.0.0提供了pretrained tokenizer,不用白不用。所以本文之后的安装和使用,都是建立在这个版本上。
Installation
Prerequisite
- Python >= 3.6
- Pytorch == 1.6.0
接下来两种安装方法,一种pip安装,一种from source。
From pip
1 | pip install OpenNMT-py==2.0.0rc1 |
如果用pip安装的时候提示MemoryError,则用:
1 | pip install OpenNMT-py==2.0.0rc1 --no-cache-dir |
From source
1 | git clone https://github.com/OpenNMT/OpenNMT-py.git |
如果想用pretrained model 或transformers,还要运行以下这句:
1 | pip install -r requirements.opt.txt |
注意:
clone 之前记得切换分支!master
分支是开发中的分支,如果碰上他们正在更新(是我的血泪史了QAQ),有的code 或api还没写完,很坑。
切换方式:master
-> Tags
-> 2.0.0rc1
.
PS. 就在写这篇博客的当下,他们又更新到 2.0.0rc2
了(看了一下更新时间,14 days ago) = = 虽然敏捷开发是没有错,但是也太快了,文档维护没跟上,有点坑。。。
Check installation
检测是否安装成功:
1 | onmt_train -h |
如果能输出help信息,说明安装成功。
Step 0. Training data preparation
Dataset preparation
如果选择install from source的方法,就可以看到在 OpenNMT-py/data/
的文件夹下已经下载好 英译德 的dataset:
- For training:
src-train.txt
tgt-train.txt
- For validation:
src-val.txt
tgt-val.txt
但这个dataset很小,训练效果不会好,所以这里下载更多的dataset。
(如果只打算跑通一个例子,可以直接跳到下一个小节,不用重新下载新的dataset)
Dataset Download
WMT DATASET
Link: https://www.statmt.org/wmt13/translation-task.html#download
WMT 数据集,每年都有。上面的link是WMT13年的link。要找哪一年的dataset,就把 wmt13
这个数字改成那一年。比如要找WMT19的dataset,下载地址就是 https://www.statmt.org/wmt19/translation-task.html#download。
因为每一年翻译任务的语言不一样,所以根据要训练的翻译模型自己找年份 :(
下载解压之后,一般有两个文件夹。根据dataset不同,名字可能不同,但能看出来一个是源语言(src
),一个是目标语言(tgt
)。文件的形式是一行一句话。
OPUS
Link: http://opus.nlpl.eu/
这个网站也包含WMT的入口,很杂很乱,但好在可以选source,target language, customize 的空间很大。
下载之后的形式和WMT 的dataset很像,也是一行一句话。
Tatoeba Kaggle
http://www.manythings.org/anki/
这个网站的好处是简洁,一看就知道在哪里下载。
缺点是数据集不大,且双语放在同一个文件中,格式为English + TAB + The Other Language + TAB + Attribution
。 如:
1 | This work isn't easy. この仕事は簡単じゃない。 CC-BY 2.0 (France) Attribution: tatoeba.org #3737550 (CK) & #7977622 (Ninja) |
所以下载下来需要预处理,将两种语言分开存在不同文件中,方便后续使用。
(Optional) Preprocess
一般上述网站提供的数据集已经进过一定程度的清洗,但还可以根据自己的需求继续做一些预处理。这里不做赘述,可根据需要处理。
注意:
OpenNMT 2.0.0rc1 提供去除长句、特殊词汇等功能,可以不用自己处理,美滋滋 :p
Step 1. Build Vocabulary
准备好数据集之后,先建立词汇表。
OpenNMT提供onmt_build_vocab
命令,输入onmt_build_vocab
可以看到所有的arguments。为了避免每次输入一堆argument的麻烦,OpenNMT 可以接收一整份configuration作为输入,这样就省去了很多麻烦。
Example configuration for Build Vocab
This is the example provided here. 这个例子里用作分词的语言模型是subword,需要提前训练, 保存在data/wmt/wmtende.model
。如果不想做这一步,可以直接看下一个例子。
1 | # wmt14_en_de.yaml |
以一个不用语言模型的分词作例子:
1 | # wmt14_en_de.yaml |
这个例子用到四个数据集,分别设置了不同的权重,src和tgt语言共享一个大小为32000的单词表,单词表存在src_vocab
和tgt_vocab
指定的路径下。
保存这个config文件,运行:(注意替换url-to-config-file
成存储的路径, 如 config/build_vocab.yaml
)
1 | onmt_build_vocab -config url-to-config-file -n_sample -1 |
这里n_sample 是用到的数据数量,-1指用全部。
Data Transformer
OpenNMT 2.0 以后提供常用的预处理方法和分词模型,如去除长句,bpe等。
用法
在每个dataset的transform中填写preset transformer,例如用sentencepiece
做分词;
1 | data: |
Preprocess - Filterlong
用filterlong
做预处理去掉过长句子,搭配以下comment一起使用:
1 | #### Filter |
不一一赘述了。
注意:sentencepiece如果
Tokenization
No special tokenization.
相当于直接用空格当作tokenization. 缺点是vocabulary会很大,很多同源词会被当作独立的单词。好处是简单,无需用到什么语言模型。
1 | data: |
Sentencepiece
Sentencepiece要预训练一个语言模型,然后用语言模型将source 和target文件进行分词,保存相应的vocabulary。
(a) 训练语言模型
1 | import sentencepiece as spm |
参数input
和model_prefix
要指定, vocab_size
可以自定义,这里设置为32000。
(b) Encode
1 | spp = spm.SentencePieceProcessor() |
model_file
指定到刚刚训练好的语言模型路径,line
是待encoding的句子/段落。
(c) Decode (After translation)
训练模型之前不需要做这一步,这一步是提供给训练模型之后的。
1 | spp = spm.SentencePieceProcessor() |
model_file
指定到刚刚训练好的语言模型路径,line
是待decoding的句子列表。
BPE
在tools/
下有bpe_pipeline.sh
可以直接用。
其他可用的data transformers 在这里,
Step 2. Train the model
把下面的configuration加在之前build vocabulary 的config 后面:
1 | # General opts |
注意:
gpu_ranks
: 指定前两个gpu core,这里根据需要设置要用的gpu序号和个数。- 这里的模型是 encoder,decoder都为6层transformer 的attention model,各种参数都可调
- 如果想从某个checkpoint开始train起,加上参数
train_from: path-to-pt-file
- 可以指定log路径:
log_file: path-you-want-to-save-log-file
- 用几个GPU进行训练,
world_size
就设置成几。 - 如果
share_vocab: false
, 则share_decoder_embeddings
也要为false。
Step 3. Translate
用法
1 | onmt_translate -src src-file -tgt tgt-file -model url-to-the-model -replace_unk -gpu 0 -verbose |
输出
1 | [2020-12-29 12:03:14,773 INFO] |
注意:
- 这里的
src-file
,tgt-file
,url-to-the-model
需指定 - 可以用多个gpu进行计算,用法
-gpu 0 1
- 如果不使用
-replace_unk
,预测出来的句子就都是 -verbose
打印出每个句子的具体翻译情况- 如果用了语言模型做分词,要先将source 和target 文件用相应的语言模型进行处理,再translate。
写在最后
文档不是很完善,但是看代码还是可以。版本迭代很快,well-maintained,看看代码还是能跟上的。总体来说是个提高效率的codebook吧。
BTW,内存管理有些问题,不确定问题出在OpenNMT还是pytorch上。