文章目录
前言
Fairseq is a sequence modeling toolkit written in PyTorch that allows researchers and developers to train custom models for translation, summarization, language modeling and other text generation tasks.
Fairseq 是一个基于PyTorch编写的序列建模工具包 (由Facebook AI Research(FAIR)开发),它允许研究人员和开发人员训练用于翻译、摘要、语言建模和其他文本生成任务的自定义模型,以解决各种自然语言处理(NLP)任务。
安装:
- 通常情况下,Fairseq是一个较大的项目,因此它的安装可能会占用一些时间和磁盘空间,尤其是如果您的网络连接速度较慢时。
git clone https://github.com/pytorch/fairseq
cd fairseq
pip install --editable ./
- 如果只是想使用Fairseq而不需要进行开发或编辑Fairseq源代码,可以考虑直接安装Fairseq的发布版本
pip install fairseq
实际上本节内容知识主要目的是让使用者知道fairseq能干什么
一、Evaluating Pre-trained Models(评估预训练模型)
首先,需要下载示例的预训练模型(一个英语法语对的翻译任务)及它的词汇表(大概1.9g):
curl https://dl.fbaipublicfiles.com/fairseq/models/wmt14.v2.en-fr.fconv-py.tar.bz2 | tar xvjf -
但实际上我在使用过程中服务器下载速度极慢,改用了wget:
wget -c https://dl.fbaipublicfiles.com/fairseq/models/wmt14.v2.en-fr.fconv-py.tar.bz2
tar -xvjf wmt14.v2.en-fr.fconv-py.tar.bz2
会解压出下面五个文件:
此模型使用了字节对编码(Byte Pair Encoding,BPE)
词汇表,因此在进行翻译之前,我们需要将源文本(source text)
进行编码——使用 apply_bpe.py
脚本,并使用 wmt14.en-fr.fconv-cuda/bpecodes
文件进行编码。@@
(用来标记词汇切分的边界)被用作连续标记符,原始文本可以通过诸如
sed s/@@ //g
一个用于文本处理的命令。使用了 sed(流编辑器)工具,执行以下操作:其中 s 表示替换操作,@@ 是要查找的文本,// 之间是要用来替换的文本,g 表示全局替换(即一行中的所有匹配都将被替换)。即在文本中查找所有的 @@ 符号,并将其替换为空格)
或传递 --remove-bpe
标志给 fairseq-generate
(命令行工具) 来还原。
在进行BPE之前,输入文本需要使用来自 mosesdecoder
的 tokenizer.perl
进行标记化。
使用 fairseq-interactive
以交互方式生成翻译。在这里,我们使用了 5 的束搜索(beam size)
并使用了Moses标记器和给定的字节对编码词汇表对输入进行预处理。它将自动删除BPE连续标记符并对输出进行去标记化处理。
演示:
首先需要下载 subword-nmt 库:
pip install subword-nmt
使用清华源更快:
pip install subword-nmt -i https://pypi.tuna.tsinghua.edu.cn/simple
在命令行键入以下示例代码:
> MODEL_DIR=wmt14.en-fr.fconv-py
> fairseq-interactive \
--path $MODEL_DIR/model.pt $MODEL_DIR \
--beam 5 --source-lang en --target-lang fr \
--tokenizer moses \
--bpe subword_nmt --bpe-codes $MODEL_DIR/bpecodes
选用英文->法语的示例结果如下:
| loading model(s) from wmt14.en-fr.fconv-py/model.pt
| [en] dictionary: 44206 types
| [fr] dictionary: 44463 types
| Type the input sentence and press return:
Why is it rare to discover new marine mammal species?
S-0 Why is it rare to discover new marine mam@@ mal species ?
H-0 -0.0643349438905716 Pourquoi est-il rare de découvrir de nouvelles espèces de mammifères marins?
P-0 -0.0763 -0.1849 -0.0956 -0.0946 -0.0735 -0.1150 -0.1301 -0.0042 -0.0321 -0.0171 -0.0052 -0.0062 -0.0015
这个生成脚本产生三种类型的输出:
O:原始源句子的副本;
H:假设以及平均对数似然;
P:每个标记位置的位置分数,包括在文本中省略的句子末尾标记。
其他类型的输出行包括
D:解标记化的假设;T:参考目标;A:对齐信息;E:生成步骤的历史记录。
我的结果:
二、Training a New Model(训练一个新模型)
一个机器翻译任务的教程,其他任务可以参见[https://fairseq.readthedocs.io/en/latest/tasks.html#language-modeling]
2.1.Data Pre-processing(数据预处理)
Fairseq包含用于多个翻译数据集(如:IWSLT 2014(德语-英语)、WMT 2014(英语-法语)和WMT 2014(英语-德语))的示例预处理脚本。
需要注意的是如果使用的是第2种安装方法,还需要将fairseq仓库中的example下载
以IWSLT为例:
> cd examples/translation/
> bash prepare-iwslt14.sh
> cd ../..
> TEXT=examples/translation/iwslt14.tokenized.de-en
> fairseq-preprocess --source-lang de --target-lang en \
--trainpref $TEXT/train --validpref $TEXT/valid --testpref $TEXT/test \
--destdir data-bin/iwslt14.tokenized.de-en
2.2.Training(训练)
使用fairseq-train训练新模型:
> mkdir -p checkpoints/fconv
> CUDA_VISIBLE_DEVICES=0 fairseq-train data-bin/iwslt14.tokenized.de-en \
--optimizer nag --lr 0.25 --clip-norm 0.1 --dropout 0.2 --max-tokens 4000 \
--arch fconv_iwslt_de_en --save-dir checkpoints/fconv
默认情况下,fairseq-train
将使用机器上所有可用的 GPU。使用 CUDA_VISIBLE_DEVICES环境变量选择特定 GPU 和/或 更改将使用的 GPU 设备的数量。
另请注意,批次大小是根据每批次的最大令牌数 ( --max-tokens
)指定的,具体取决于系统上的可用 GPU 内存。
2.3.Generation(生成)
模型训练完毕后,可以使用 fairseq-generate
(针对二值化数据)或 fairseq-interactive
(针对原始文本)生成翻译。
命令如下(示例)(但是个人更建议使用脚本文件,更利用调参,记录等):
fairseq-generate data-bin/iwslt14.tokenized.de-en \
--path checkpoints/fconv/checkpoint_best.pt \
--batch-size 128 --beam 5
示例结果:
| [de] dictionary: 35475 types
| [en] dictionary: 24739 types
| data-bin/iwslt14.tokenized.de-en test 6750 examples
| model fconv
| loaded checkpoint trainings/fconv/checkpoint_best.pt
S-721 danke .
T-721 thank you .
...
我的结果:
使用--remove-bpe
可以去除延续标记
三、 Advanced Training Options(训练进阶)
3.1.Large mini-batch training with delayed updates(延迟更新的大批量训练)
可以通过 --update-freq
选项来累积来自多个小批量的梯度并延迟更新,从而创建更大的有效批量大小(batch size)。延迟更新还可以通过减少GPU之间的通信成本和节省由于GPU之间工作负载差异而导致的空闲时间来提高训练速度。更多详细信息,请参阅 文献
累积梯度的方法是将多个小批量的梯度累积在一起,然后在更新模型参数之前对它们进行平均或求和。这样做的好处是可以有效地增加每次参数更新的批量大小,从而提高了训练的效率。通过增加批量大小,可以在一定程度上提高模型的稳定性和泛化性能。
延迟更新是指在累积了一定数量的小批量后才进行一次参数更新。这个过程可以减少模型参数的更新频率,从而减少了GPU之间的通信成本,因为更新参数通常需要在GPU之间传输数据。此外,延迟更新还可以充分利用GPU的计算能力,因为它可以减少由于不同GPU之间工作负载不均匀而导致的空闲时间。
以下命令使得在单个GPU上进行训练,但有效批量大小相当于在8个GPU上进行训练:
CUDA_VISIBLE_DEVICES=0 fairseq-train --update-freq 8 (...)
3.2.Training with half precision floating point (FP16)(使用半精度浮点数(FP16)进行训练)
FP16训练需要使用Volta GPU以及CUDA 9.1或更高版本
- 单精度浮点数(32位): 符号位:1位 ; 指数位:8位; 尾数位:23位 精度:大约7位有效数字
范围:通常在约1.4 x 10-45 到3.4 x 1038之间 - 双精度浮点数(64位): 符号位:1位; 指数位:11位; 尾数位:52位 精度:大约15-16位有效数字
范围:通常在约5.0 x 10-324到1.8 x 10308之间 - 半精度浮点数(16位): 符号位:1位; 指数位:5位; 尾数位:10位 精度:约3位有效数字
范围:较小,但可表示的范围较有限
最近的GPU支持高效的半精度浮点数计算,例如使用Nvidia Tensor Cores。Fairseq支持使用 --fp16
标志进行FP16训练:
fairseq-train --fp16 (...)
3.3.Distributed training(分布式训练)
Fairseq中的分布式训练是建立在torch.distributed
之上的。启动作业的最简单方法是使用torch.distributed.launch
工具。
例如,要在两个包含8个GPU的节点上训练一个的大型英德Transformer模型(总共16个GPU),可以在每个节点上运行以下命令,并在第二个节点上将 node_rank=0
替换为 node_rank=1
,并确保更新 --master_addr
为第一个节点的IP地址:
python -m torch.distributed.launch --nproc_per_node=8 \
--nnodes=2 --node_rank=0 --master_addr="192.168.1.1" \
--master_port=12345 \
$(which fairseq-train) data-bin/wmt16_en_de_bpe32k \
--arch transformer_vaswani_wmt_en_de_big --share-all-embeddings \
--optimizer adam --adam-betas '(0.9, 0.98)' --clip-norm 0.0 \
--lr-scheduler inverse_sqrt --warmup-init-lr 1e-07 --warmup-updates 4000 \
--lr 0.0005 \
--dropout 0.3 --weight-decay 0.0 --criterion label_smoothed_cross_entropy --label-smoothing 0.1 \
--max-tokens 3584 \
--max-epoch 70 \
--fp16
在SLURM集群上,fairseq将自动检测节点和GPU的数量,但必须提供一个端口号:
salloc --gpus=16 --nodes 2 (...)
srun fairseq-train --distributed-port 12345 (...).
3.4.Sharding very large datasets(对非常大的数据集进行分片操作)
在非常大的数据集上进行训练可能具有挑战性,特别是如果机器中没有太多系统内存 (RAM)。fairseq 中的大多数任务都支持对“分片”数据集进行训练,其中原始数据集已被预处理为不重叠的块(或“分片”)。
例如,您可以拆分数据并创建“data-bin1”、“data-bin2”等,而不是将所有数据预处理到单个“data-bin”目录中。然后您可以像这样调整训练命令:
fairseq-train data-bin1:data-bin2:data-bin3 (...)
现在,训练将逐个迭代每个分片,每个分片对应一个epoch,从而减少系统内存使用量。
四、 Command-line Tools(命令行工具)
Fairseq 提供了多种用于训练和评估模型的命令行工具:
fairseq-preprocess
:数据预处理:构建词汇表并对训练数据进行二值化fairseq-train
:在一个或多个 GPU 上训练新模型fairseq-generate
:使用经过训练的模型翻译预处理数据fairseq-interactive
:使用经过训练的模型翻译原始文本fairseq-score
:根据参考翻译对生成的翻译进行BLEU 评分fairseq-eval-lm
:语言模型评估
此前已经接触了前四种;其余详情见官方文档