文章目录
- 前言
- 环境
- 流程介绍
- 数据部分
- 分词部分
- 预处理部分
- 训练部分
- 遇到的问题
- 问题1
- 可能遇到的问题
- 问题1
- 问题2
前言
- 本文是使用
fairseq
做Bart
预训练任务的踩坑记录 huggingface
没有提供 Bart 预训练的代码
facebookresearch/fairseq: Facebook AI Research Sequence-to-Sequence Toolkit written in Python. (github.com)
环境
- fairseq=0.10.0
- torch=1.10.0+cu111
- GPU=NVIDIA GeForce RTX 3090
- CUDA=11.1
安装时先进行了
pip install --editable ./
之后报错
`Getting requirements to build editable ... error
error: subprocess-exited-with-error
× Getting requirements to build editable did not run successfully.
packages/torch/lib/../../nvidia/cublas/lib/libcublas.so.11: symbol cublasLtHSHMatmulAlgoInit version libcublasLt.so.11 not defined in file libcublasLt.so.11 with link time reference
解决(有issue,有回答: https://github.com/facebookresearch/fairseq/issues/4843
pip install --no-build-isolation --editable ./
-
但是装完之后是最新的
fairseq=0.12.0
,会有args
冲突的错误argparse.ArgumentError: argument --max-source-positions: conflicting option string: --max-source-positions
有人提issue,但是没有回答:https://github.com/facebookresearch/fairseq/issues/4416
-
这个错误应该是版本问题,于是换成
fairseq=0.10.0
, torch与cuda 11.1
对应安装
个人认为不需要执行 pip install --editable ./
,直接 pip 安装想要的fairseq
版本即可
流程介绍
- 数据部分:获得数据,将数据写进文件中,每一行代表一个样本
- 分词部分:使用 BPE(Byte Pair Encoding) 分词,将数据 tokenize
- 预处理部分:使用
fairseq-preprocess
对分词后的数据进行处理,并binarize数据 - 训练部分:使用
fairseq-train
进行训练
数据部分
我使用的是qulac
中query对应的top10k docs数据,数据包含大量文本形式的文档。
- 将数据划分为训练集,验证集,测试集,分别存于
train.input, valid.input, test.input
,其中每一行代表一个训练样本- 我将文档按
.
进行拆分,每个长度大于50的句子才会被考虑 - 这里我要进行的是
denoising
任务,因此不需要label
,如果任务是有target
的,还要存储train.output
等文件(文件名称和后缀可以自行设置)
- 我将文档按
- 我以
8:2
的比例设置了训练集和验证集,没有设置测试集
分词部分
因为模型不能处理原始文本,因此我们要将文本转换为 token id
的序列,使用命令如下
TASK=denoise_data/source_split
LANG=input
for SPLIT in train valid
do
python -m examples.roberta.multiprocessing_bpe_encoder \
--encoder-json ./BPE/encoder.json \
--vocab-bpe ./BPE/vocab.bpe \
--inputs "$TASK/$SPLIT.$LANG" \
--outputs "$TASK/$SPLIT.bpe.$LANG" \
--workers 60 \
--keep-empty;
done
-
这里需要先下载对应的
encoder.json, vocab.bpe. dict.txt
,Bart
与gpt2使用的是相同的wget -N 'https://dl.fbaipublicfiles.com/fairseq/gpt2_bpe/encoder.json' wget -N 'https://dl.fbaipublicfiles.com/fairseq/gpt2_bpe/vocab.bpe' wget -N 'https://dl.fbaipublicfiles.com/fairseq/gpt2_bpe/dict.txt'
-
这里的
output
是输出文件名,不是label
分词前的数据
分词后的数据(和分词前的数据不是对应的,只是展示结果)
预处理部分
预处理分词好的数据,并且对数据进行二值化,将得到的二值化数据写到 --destdir
文件夹中,可以用于模型训练
TASK=denoise_data/source_split
fairseq-preprocess \
--only-source \
--trainpref "${TASK}/train.bpe.input" \
--validpref "${TASK}/valid.bpe.input" \
--destdir "${TASK}/bpe_data" \
--workers 60 \
--srcdict /home/nsy/ict/Models/bart_base_fairseq/bart.base/dict.txt \
--tgtdict /home/nsy/ict/Models/bart_base_fairseq/bart.base/dict.txt;
训练部分
加载刚刚预处理完的数据,并进行训练,具体参数可以自行调整
MASKLEN="span-poisson"
MRATIO=0.4
DATASET=./denoise_data/source_split/bpe_data/
CUDA_VISIBLE_DEVICES=0 fairseq-train $DATASET \
--save-dir models/nsy_saved \
--no-epoch-checkpoints \
--tokens-per-sample 128 \
--arch bart_base \
--task denoising \
# other_parameters
遇到的问题
上面的流程部分是解决完 bug 之后的正确命令
问题1
报错out of memory
显存不够,需要 40G 显存,显然这对 Bart_base
来说是不会出现的错误,一定是自己的处理有问题,不是模型有问题
我使用小部分数据测试,因此这样加载一次很快,有利于发现问题。
-
train里面3000多条,可以跑通,且加载速度很快。这样模型的参数明显很小,比大数据集时小了很多倍。注意到
embedding
的维度很有问题,猜测:preprocess时产生的字典有问题,导致带字典维度的矩阵特别大 -
小数据集(3000多行文本)时
embedding
层的参数(embed_tokens): Embedding(13049, 768, padding_idx=1)
-
大数据集(千万行文本)时
embedding
层的参数(embed_tokens):Embedding(14929897, 768, padding_idx=1)
这会导致模型参数量巨大
发现参数量确实太大了,应该有问题,于是查看字典大小,与embedding
第一维大小基本一致
因为之前尝试过使用 Bart 的字典来进行preprocess
,但是发现百分之90多都被替换成 ,因此在小数据集上测试Bart的字典为什么会产生如此多的 。查看 Bart 的字典
发现直接preprocess没有分词,应该先对文本做分词,产生 token_id 之后再进行 preprocess
首先进行BPE分词
TASK=try_data
LANG=input
for SPLIT in train valid
do
python -m examples.roberta.multiprocessing_bpe_encoder \
--encoder-json ./BPE/encoder.json \
--vocab-bpe ./BPE/vocab.bpe \
--inputs "$TASK/$SPLIT.$LANG" \
--outputs "$TASK/$SPLIT.bpe.$LANG" \
--workers 60 \
--keep-empty;
done
之后进行preprocess,这样就发现一切都合理了,也没有被替换成 的 token 了
TASK=try_data
fairseq-preprocess \
--only-source \
--trainpref "${TASK}/train.bpe.input" \
--validpref "${TASK}/valid.bpe.input" \
--destdir "${TASK}/bpe_data" \
--workers 60 \
--srcdict /home/nsy/ict/Models/bart_base_fairseq/bart.base/dict.txt \
--tgtdict /home/nsy/ict/Models/bart_base_fairseq/bart.base/dict.txt;
2023-02-18 22:45:29 | INFO | fairseq_cli.preprocess | Namespace(align_suffix=None, alignfile=None, all_gather_list_size=16384, bf16=False, bpe=None, checkpoint_shard_count=1, checkpoint_suffix='', cpu=False, criterion='cross_entropy', dataset_impl='mmap', destdir='try_data/bpe_data', empty_cache_freq=0, fp16=False, fp16_init_scale=128, fp16_no_flatten_grads=False, fp16_scale_tolerance=0.0, fp16_scale_window=None, joined_dictionary=False, log_format=None, log_interval=100, lr_scheduler='fixed', memory_efficient_bf16=False, memory_efficient_fp16=False, min_loss_scale=0.0001, model_parallel_size=1, no_progress_bar=False, nwordssrc=-1, nwordstgt=-1, only_source=True, optimizer=None, padding_factor=8, profile=False, quantization_config_path=None, scoring='bleu', seed=1, source_lang=None, srcdict='/home/nsy/ict/Models/bart_base_fairseq/bart.base/dict.txt', target_lang=None, task='translation', tensorboard_logdir=None, testpref=None, tgtdict='/home/nsy/ict/Models/bart_base_fairseq/bart.base/dict.txt', threshold_loss_scale=None, thresholdsrc=0, thresholdtgt=0, tokenizer=None, tpu=False, trainpref='try_data/train.bpe.input', user_dir=None, validpref='try_data/valid.bpe.input', workers=60)
2023-02-18 22:45:29 | INFO | fairseq_cli.preprocess | [None] Dictionary: 51200 types
2023-02-18 22:45:30 | INFO | fairseq_cli.preprocess | [None] try_data/train.bpe.input: 3383 sents, 89468 tokens, 0.0% replaced by <unk>
2023-02-18 22:45:30 | INFO | fairseq_cli.preprocess | [None] Dictionary: 51200 types
2023-02-18 22:45:31 | INFO | fairseq_cli.preprocess | [None] try_data/valid.bpe.input: 4085 sents, 99282 tokens, 0.0% replaced by <unk>
2023-02-18 22:45:31 | INFO | fairseq_cli.preprocess | Wrote preprocessed data to try_data/bpe_data
可能遇到的问题
这里可能遇到的问题
是我最初遇到的,后来我重新clone
了fairseq
的仓库,安装了不同版本的fairseq
之后没有遇到的,因此这里的问题大概率是版本问题
问题1
遇到报错 Fairseq: No module named ‘fairseq.data.data_utils_fast’。在克隆后的项目主目录运行
python setup.py build_ext --inplace
- Fairseq: No module named ‘fairseq.data.data_utils_fast’ - 简书 (jianshu.com)
问题2
遇到报错 module numpy
has no attribute float
-
因为np.float从1.24起被删除。所用的代码是依赖于旧版本的Numpy。可以更新sklearn到一个不使用np.float的新版本(如果它存在)或者将你的Numpy版本降级到1.23.5.
pip install -U numpy==1.23.5
Note: sklearn是scikit-learn的缩写,安装时要用 pip install scikit-learn