发现一篇知乎写的比较好:https://zhuanlan.zhihu.com/p/194176917
Facebook-NLP工具包fairseq漫游指南(1)—命令行工具:https://bbs.hupu.com/37383258.html
fairseq命令:https://www.jianshu.com/p/09055a16fa98
fairseq的使用
下载fairseq到本地
项目地址:https://github.com/pytorch/fairseq
运行fairseq项目出现报错:
解决方案:
cd到fairseq的文件夹,执行
pip install --editable .
总结:
git clone https://github.com/pytorch/fairseq.git
cd fairseq && pip install --editable ./
git clone https://github.com/NVIDIA/apex
cd apex
pip install -v --no-cache-dir --global-option="--cpp_ext" --global-option="--cuda_ext" \
--global-option="--deprecated_fused_adam" --global-option="--xentropy" \
--global-option="--fast_multihead_attn" ./
fairseq preprocess | 数据预处理,建立字典和训练数据和二值化数据 |
fairseq train | 训练模型 |
fairseq gennerate | 使用训练的模型翻译预处理后的数据 |
fairseq generate-lines | 使用训练后的数据翻译一行文本 |
fairseq score | 翻译后的文本的BLEU得分 |
fairseq tofloat | 转化训练模型为CPU模型 |
fairseq optimize-fconv | 优化生成的全卷积模型 |
将文本数据转换为二进制的文件
预处理命令首先会从训练文本数据中构建词表,默认情况下将所有出现过的单词根据词频排序。
并将排序后的单词列表作为最终的词标。
--thresholdsrc/--thresholdtgt,分别对应源端和目标端的词标的最低词频,词频低于这个阈值的单词将不会出现在此表中,而是使用unknown标签代替。
--srcdict/--tgtdict,其参数为一个文件名,也就是说使用已有的词表,而不是根据单词的词频构建词表。已有的词标文件,每一行包含一个单词及其词频。
--nwordssrc/--nwordstgt,源端和目标端词表的大小,在对单词根据词频排序后,取前n个词来构建词表,剩余的单词使用unknow标签代替。
--joined-dictionary,源端和目标端使用同一个词表。
构建的词表是一个单词和序号之间的一对一映射,这个序号是单词在词表中的下标位置。
二进制化的文件会默认保存在data-bin目录下,包括生成的词表,训练数据、验证数据和测试数据,也可以通过destdir参数,将生成的数据保存在其他目录。
TEXT=examples/translation/py_hz
fairseq-preprocess --source-lang input --target-lang label --trainpref $TEXT/train --validpref $TEXT/valid --testpref $TEXT/test --destdir data-bin/py_hz_pre
|
--destdir |
预处理后的二进制文件会默认保存在data-bin目录下,可以通过destdir参数将生成的数据存放在其他位置 |
|
--thresholdsrc/--thresholdtgt |
分别对应源端(source)和目标端(target)的词表的最低词频,词频低于这个阈值的单词将不会出现在词表中,而是统一使用一个unknown标签来代替。 |
|
--srcdict/--tgtdict |
其参数为一个文件名,即使用已有的词表,而不去根据文本数据中单词的词频构建词表。已有的词表文件中,每一行包含一个单词及其词频(这个词频只作为排序和阈值过滤的依据,不代表实际的词频) |
|
--nwordssrc/--nwordstgt |
源端和目标端词表的大小,在对单词根据词频排序后,取前n个词来构建词表,剩余的单词使用一个统一的unknown标签代替 |
|
--joined-dictionary |
源端和目标端使用同一个词表,对于相似语言(如英语和西班牙语)来说,有很多的单词是相同的,使用同一个词表可以降低词表和参数的总规模。
|
|
构建的词表是一个单词和序号之间的一对一映射,这个序号是单词在词表中的下标位置。预处理命令在构建词表之后,会将文本数据转换为数值形式,也就是把文本中的每一个词,转换为对应的序号。之后,数值化的文本数据会被进一步编码,默认情况下使用Memory-Mapped IndexedDataset,这种数据编码方式不仅可以压缩文件大小,还可以根据索引进行随机读取,因此在训练的时候不需要加载全部数据,从而节约内存使用。
|
fairseq-train提供了大量的训练参数,从而进行定制化的训练过程。
fairseq-train data-bin/py_hz_pre --task translation --source-lang input --target-lang label --arch fconv --optimizer adam --adam-betas '(0.9,0.98)' --clip-norm 0.1 --lr 0.01 --lr-scheduler inverse_sqrt --warmup-updates 2000 --dropout 0.2 --weight-decay 0.0001 --max-tokens 8000 --save-dir checkpoints --eval-bleu
注意:默认情况下会使用GPU训练模型。
数据 |
--max-tokens |
按照词的数量来分batch,每个batch包含**个词 |
|
--max-sentences |
按照句子的数量来划分batch,每个batch包含多少个句子 |
模型部分 |
--arch |
所使用的模型结构 |
|
--encoder-layers 12 |
使用预设模型时,可以通过额外的命令行参数覆盖原有的参数,如transformer_wmt_en_de中预设的编码器层数是6,可以使用--encoder-layers 12 将编码器层数改为12 |
优化部分 |
--criterion |
指定使用的优化器,如adam、sgd等 |
--label-smoothing 0.1 | 将label_smoothed_cross_entropy损失默认为0的label-smoothing值改为0.1 | |
|
--lr-scheduler |
指定学习缩减的方式 |
|
--update-freq |
指定参数更新频率:通常每计算一次梯度,就会更新一次参数,但是某些时候希望多次梯度计算后更新参数。 例如:在单个GPU上指定“--update-freq 4”来训练,结果和4个GPU训练是基本等价的。 |
训练部分 |
Fairseq支持单GPU/多GPU/多机器等多种训练方式,在默认情况下,会根据当前机器的GPU数量来确定训练方式。在绝大多数情况下,这部分参数都不需要关心,而是通过系统环境变量的方式,export CUDA_VISIBLE_DEVICES=0,1,来指定单卡/多卡训练。 |
|
|
--fp 16 |
若使用的GPU支持半精度,可以通过--fp16来进行混合精度训练,可以极大提高模型训练的速度。通过torch.cuda.get_device_capablity(0)[0]可以确定GPU是否支持半精度(值小于7则不支持,大于7则支持。) |
日志和模型的保存 |
--no-progress-bar |
逐行打印日志,方便保存 |
|
--log-interval |
默认情况每训练100次会打印一次,可通过该参数进行修改。 |
|
--save-dir |
训练过程保存中间模型 |
|
--save-interval |
每N个epoch保存一次 |
|
--save-interval-updates |
每N步保存一次,通过step来保存模型 |
|
在使用多GPU训练时,指定的batch size(max tokens或max sentences)是单个GPU上的数量,以token计算为例,最终batch size的大小为max-tokens、GPU数量、update-freq的乘积。 |
|
|
|
|
fairseq-generate data-bin/py_hz_pre --path checkpoints/checkpoint_best.pt --remove-bpe --results-path data-bin
fairseq-generate data-bin/py_hz_pre --path checkpoints/checkpoint_best.pt --batch-size 128 --beam 5 > temp.txt
fairseq-generate |
--gen-subset |
默认解码测试部分, 指定解码其他部分,例如--gen-subset train 会翻译 |
|
--gen-subset train |
翻译整个训练数据 |
|
--quiet |
若不想看到翻译结果,只想看到翻译结果的BLEU分值,使用--quiet参数,只显示翻译进度和最后打分 |
|
--remove-bpe |
指定对翻译结果后处理 |
|
--results-path |
翻译结果的存放位置 |
--beam | 设置beam search中的beam size |
|
--lenpen | 设置beam search中的长度惩罚 | |
--unkpen | 设置beam search中的unk惩罚 | |
fairseq-interactive |
cat test.de |fairseq-interactive data-bin --path checkpoints/checkpoint_best.pt --remove-bpe逐行翻译test.de中的句子 |
|
faiseq-generate someargs >result.txt将输出保存到文件 grep ^H result.txt | sort -n -k 2 -t '-' | cut -f 3 |
S 源预
T 目标语
H 预测的句子,H前的数字是这个句子的预测概率的log再除以总长度
P 每个单词的预测概率的log,全部相加除句子总长度等于H
DATA=data-bin/iwslt14.tokenized.de-en
fairseq generate-lines -sourcedict $DATA/dict.de.th7 -targetdict $DATA/dict.en.th7 -path trainings/fconv/model_best_opt.th7 -beam 10 -nbest 2
整体流程
##优化模型
# Optional: optimize for generation speed
$ fairseq optimize-fconv -input_model trainings/fconv/model_best.th7 -output_model trainings/fconv/model_best_opt.th7
##翻译文本
# Translate some text
$ DATA=data-bin/iwslt14.tokenized.de-en
$ fairseq generate-lines -sourcedict $DATA/dict.de.th7 -targetdict $DATA/dict.en.th7 \
-path trainings/fconv/model_best_opt.th7 -beam 10 -nbest 2
转化模型以仅使用CPU操作
# Optional: optimize for generation speed
$ fairseq optimize-fconv -input_model trainings/fconv/model_best.th7 -output_model trainings/fconv/model_best_opt.th7
# Convert to float
$ fairseq tofloat -input_model trainings/fconv/model_best_opt.th7 \
-output_model trainings/fconv/model_best_opt-float.th7
# Translate some text
$ fairseq generate-lines -sourcedict $DATA/dict.de.th7 -targetdict $DATA/dict.en.th7 \
-path trainings/fconv/model_best_opt-float.th7 -beam 10 -nbest 2
预训练模型Pre-trained models
$ fairseq generate -sourcelang en -targetlang fr -datadir data-bin/wmt14.en-fr -dataset newstest2014 -path wmt14.en-fr.fconv-cuda/model.th7 -beam 5 -batchsize 128 | tee /tmp/gen.out
# Word-level BLEU scoring:
$ grep ^H /tmp/gen.out | cut -f3- | sed 's/@@ //g' > /tmp/gen.out.sys
$ grep ^T /tmp/gen.out | cut -f2- | sed 's/@@ //g' > /tmp/gen.out.ref
$ fairseq score -sys /tmp/gen.out.sys -ref /tmp/gen.out.ref