FaceBook-NLP工具Fairseq

1. 简介

作为一个通用的序列建模工具,fairseq可以在多个自然语言处理任务上使用,如机器翻译、自动摘要、语音识别等文本生成任务,或者BERT、GPT等语言模型的训练;同时fairseq还实现了目前常用的多数模型,如RNN、CNN、Transformer、RoBERTa、XLM等。除了大量内置的任务和模型,fairseq还提供了极为简洁的接口,以便于使用者扩展已有模型、验证新的想法。

开源代码:
https://github.com/pytorch/fairseq/tree/v0.10.1

文档:
https://fairseq.readthedocs.io/en/latest/command_line_tools.html

2. 安装

FaceBook-NLP工具Fairseq_第1张图片
安装完成之后会在相应python的bin文件夹下面生成一些可直接执行的二进制文件,这些文件是我们用命令的形式使用fairseq的基础。
FaceBook-NLP工具Fairseq_第2张图片

3. 模型训练(fairseq-train)

例子:

fairseq-train data-bin --arch transformer_iwslt_de_en \
        --max-tokens 4096 --max-update 30000 \
        --optimizer adam --lr-scheduler inverse_sqrt --lr 0.0007 \
        --criterion label_smoothed_cross_entropy --label-smoothing 0.1 \
        --no-progress-bar --save-interval-updates 1000 

可以从文档里了解各个参数的含义以及该如何设置,我们只介绍几个常用的。

  • data-bin
    这里是填输入的二进制文件的路径,直接把data-bin覆盖掉
  • –arch (model architecture)
    后面跟着模型的名字,如果是fairseq里面本来就有的模型可以直接使用,如果是自己写的新模型,就得通过在fairseq/tasks中注册自己的task,fairseq/models中注册自己的model,fairseq/critirion中注册自己的critirion来完成基于fairseq框架的训练。
    fairseq在自己的models文件夹里面放了好几个已经写好的模型,可以直接用。
  • task
    训练任务的名字
  • –criterion
    损失函数

4. 一个机器翻译的任务

(1)准备数据

在机器翻译中,需要双语平行数据来进行模型的训练,在这里使用fairseq中提供的数据:

bash fairseq/examples/translation/prepare-iwslt14.sh

这个脚本会下载IWSLT 14 英语和德语的平行数据,并进行分词、BPE等操作,处理的结果为:

iwslt14.tokenized.de-en
├── code
├── test.de
├── test.en
├── tmp
├── train.de
├── train.en
├── valid.de
└── valid.en

(2)数据二进制化

之后,使用fairseq的预处理命令fairseq-preprocess将文本数据转换为二进制的文件:

fairseq-preprocess --source-lang de --target-lang en \
    --trainpref iwslt14.tokenized.de-en/train \
    --validpref iwslt14.tokenized.de-en/valid \
    --testpref iwslt14.tokenized.de-en/test

其中,trainpref、validpref和testpref代表两个语言对应文件的前缀(路径和文件名的前缀),source-lang和target-lang两个参数代表两个语言对应文件的后缀名(不代表具体语言,只是通过后缀区分两种语言的数据),fairseq通过这几个参数的组合,来寻找对应的文本数据。

例如我们的数据中只有训练数据和测试数据,且文件后缀为src和tgt,即train.src、train.tgt、test.src和test.tgt,那么通过指定–source-lang src --target-lang tgt --trainpref train --testpref test,也可以读取的对应的文件。

预处理命令首先会从训练文本数据中构建词表。在默认情况下,会将所有出现过的单词根据词频排序,并将这个排序后的单词列表作为最终的词表。同时,fairseq还提供了相关的参数来自定义词表:

–thresholdsrc/–thresholdtgt,分别对应源端(source)和目标端(target)的词表的最低词频,词频低于这个阈值的单词将不会出现在词表中,而是统一使用一个unknown标签来代替。

–srcdict/–tgtdict,其参数为一个文件名,即使用已有的词表,而不去根据文本数据中单词的词频构建词表。已有的词表文件中,每一行包含一个单词及其词频(这个词频只作为排序和阈值过滤的依据,不代表实际的词频)。

–nwordssrc/–nwordstgt,源端和目标端词表的大小,在对单词根据词频排序后,取前n个词来构建词表,剩余的单词使用一个统一的unknown标签代替。

–joined-dictionary,源端和目标端使用同一个词表,对于相似语言(如英语和西班牙语)来说,有很多的单词是相同的,使用同一个词表可以降低词表和参数的总规模。

构建的词表是一个单词和序号之间的一对一映射,这个序号是单词在词表中的下标位置。预处理命令在构建词表之后,会将文本数据转换为数值形式,也就是把文本中的每一个词,转换为对应的序号。之后,数值化的文本数据会被进一步编码,默认情况下使用Memory-Mapped IndexedDataset,这种数据编码方式不仅可以压缩文件大小,还可以根据索引进行随机读取,因此在训练的时候不需要加载全部数据,从而节约内存使用。

二进制化的数据文件会默认保存在data-bin目录下,包括生成的词表、训练数据、验证数据和测试数据。也可以通过–destdir参数,将生成的数据保存在其他目录。

(3)模型训练

在对数据进行预处理之后,就可以开始训练翻译模型了。模型训练使用的命令是fairseq-train,在参数中需要指定训练数据、模型、优化器等参数:

fairseq-train data-bin --arch transformer_iwslt_de_en \
        --max-tokens 4096 --max-update 30000 \
        --optimizer adam --lr-scheduler inverse_sqrt --lr 0.0007 \
        --criterion label_smoothed_cross_entropy --label-smoothing 0.1 \
        --no-progress-bar --save-interval-updates 1000 

fairseq-train提供了大量的训练参数,从而进行定制化的训练过程,其中主要的参数可以分为数据(data)、模型(model)、优化(optimizing)、训练(分布式和多GPU等)、日志(log)和模型保存(checkpointing)等。

  • 数据部分
    数据部分的常用参数主要有训练数据的位置(路径),训练时的batch size等。其中,batch size可以通过两种方法指定,–max-tokens是按照词的数量来分的batch,比如“–max-tokens 4096”指每个batch中包含4096个词;另外还可以通过句子来指定,如“–max-sentences 128”指每个batch中包含128个句子。

  • 模型部分
    模型部分的参数主要有–arch,用指定所使用的网络模型结构,有大量预设的可以选择。其命名一般为“model_setting”,如“transformer_iwslt_de_en”就是使用Transformer模型和预设的iwslt_de_en超参数。在大数据上进行训练的时候,可以选择“transformer_wmt_en_de”、“transformer_wmt_en_de_big”等设置。除了Transformer之外,还有LSTM、FConv等模型及对应的预设超参数可以选择。
    在使用预设模型的同时,还可以通过额外的命令行参数来覆盖已有的参数,如“transformer_wmt_en_de”中预设的编码器层数是6,可以通过“–encoder-layers 12”将编码器改为12层。

  • 优化部分
    通过–criterion可以指定使用的损失函数,如cross_entropy等。和arch参数一样,也可以通过命令行参数来覆盖特定损失的默认参数,比如通过–label-smoothing 0.1,可以将label_smoothed_cross_entropy损失中默认为0的label-smoothing值改为0.1。
    通过–optimizer可以指定所使用的优化器,如adam、sgd等;通过–lr-scheduler可以指定学习率缩减的方式。
    通常来说,参数优化紧跟梯度计算,即每计算一次梯度,就会进行一次参数更新。在某些时候,我们希望在多次梯度计算之后进行一次更新,来模拟多GPU训练,可以通过–update-freq来指定,比如在单个GPU上指定“–update-freq 4”来训练,结果和4个GPU训练是基本等价的。

  • 训练部分
    Fairseq支持单GPU/多GPU/多机器等多种训练方式,在默认情况下,会根据当前机器的GPU数量来确定训练方式。在绝大多数情况下,这部分参数都不需要关心,而是通过系统环境变量的方式,export CUDA_VISIBLE_DEVICES=0,1,来指定单卡/多卡训练。
    如果所使用的GPU支持半精度,那么可以通过参数–fp16来进行混合精度训练,可以极大提高模型训练的速度。通过torch.cuda.get_device_capability(0)[0]可以确定GPU是否支持半精度,如果该值小于7则不支持,大于等于7则支持。

  • 日志和模型保存
    在默认情况下,fairseq使用tqdm和进度条来展示训练过程,但是这种方法不适合长时间在后台进行模型训练。通过–no-progress-bar参数可以改为逐行打印日志,方便保存。默认情况下,每训练100步之后会打印一次,通过–log-interval参数可以进行修改。
    Fairseq在训练过程中会保存中间模型,保存的位置可以通过–save-dir指定,其默认为checkpoints。中间模型保存的频率有两种指定方式,–save-interval指定了每N个epoch(遍历训练数据N次)保存一次;–save-interval-updates指定了每N步保存一次,这种通过step来保存模型的方法目前更为常用。

Note:在使用多GPU训练时,指定的batch size(max tokens或max sentences)是单个GPU上的数量,以token计算为例,最终batch size的大小为max-tokens、GPU数量、update-freq的乘积。

(4)解码

在经过了充分训练之后,就可以使用模型来进行翻译了。Fairseq提供了两种解码的方式:批生成解码(fairseq-generate)和交互式解码(fairseq-interactive)。

  • fairseq-generate
    fairseq-generate用来解码之前经过预处理(fairseq-preprocess)的数据:
fairseq-generate data-bin --path checkpoints/checkpoint_best.pt --remove-bpe

默认情况下,这个命令会从预处理的数据中,解码测试数据(test set)。通过–gen-subset可以指定解码其他部分,如“–gen-subset train”就会翻译整个训练数据。

如果不想得到翻译结果,只想看到翻译结果的BLEU分值,可以通过–quiet参数,只显示翻译进度和最后打分。

通过–beam、–lenpen和–unkpen,可以分别设置beam search中的beam size,长度惩罚和unk惩罚。

参数–remove-bpe可以指定对翻译结果的后处理,由于在准备数据的时候,使用了BPE切分,该参数会把BPE切分的词合并为完整的单词。如果不加该参数,则输出的翻译结果和BLEU打分都是按照未合并BPE进行的。如果准备数据时BPE切分使用的是sentencepiece(https://github.com/google/sentencepiece),那么参数的值还可以设为“–remove-bpe sentencepiece”,以合并sentencepiece的切分。

  • fairseq-interactive
    fairseq-interactive可以进行交互式逐句解码,其参数和fairseq-generate基本一致。以下命令用来逐行翻译test.de文件中的句子:
cat test.de | fairseq-interactive data-bin --path checkpoints/checkpoint_best.pt --remove-bpe
  • 保存翻译结果
    在默认情况下,两种解码方式会将翻译结果直接显示出来,如果想保存翻译结果,可以通过–results-path参数来指定保存结果的位置,或者可以通过重定向的方法将输出保存到文件:
fairseq-generate someargs > result.txt

这两种方法得到的翻译结果文件,包含了解码日志(log)、原文、译文、打分等信息,并且顺序与原文不一致,通过以下命令可以得到排序后的译文:

grep ^H result.txt | sort -n -k 2 -t '-' | cut -f 3

参考:FaceBook-NLP工具Fairseq漫游指南(1)—命令行工具

你可能感兴趣的:(NLP,自然语言处理,机器翻译,深度学习)