ToD-BERT the Paper
数据集
不同的数据集可以帮助模型达到不同的熟练效果
- MetaLWOZ 预测数据
- …
ToD-BERT怎么训练的?
- mlm
- contrastive function 两者都有误差,因此才可以被训练。 空间结构能够捕获差异,发现细微结构。
在服务器上运行ToD-BERT训练
- 进入服务器,激活环境
source activate todbert_env
- 进入/media/HD1/dche/ToD-BERT文件夹
cd /media/HD1/dche/ToD-BERT
- 查看GPU资源占用情况
nvidia-smi
,然后选择目前占用情况较低的一张GPU进行训练即可 - 运行训练shell脚本文件
CUDA_VISIBLE_DEVICES=0 ./run_tod_lm_pretraining.sh 0 bert bert-base-uncased save/pretrain/ToD-BERT-MLM --only_last_turn --data_path ./../dialog_datasets
。根据第三步选择的几号卡,就把对应的0改成几,此处默认单卡训练。如果一切正常的话,再读入数据集数据后,就会开始训练了,有进度条出现就Ok了。常见的没跑起来的情况是CUDA out of memory。
ToD-BERT本地调用
- 将ToD-BERT模型下载至本地
- 包含ToD-BERT所需的python包,并定义模型路径
import torch from transformers import * BERT = <path_to_the_downloaded_tod-bert> # 注意此处的路径要使用从根目录开始的绝对路径,而非从用户~目录开始的相对路径。 model_class, tokenizer_class, config_class = BertModel, BertTokenizer, BertConfig tokenizer = tokenizer_class.from_pretrained(BERT) tod_bert = model_class.from_pretrained(BERT)
- 使用ToD-BERT文档中的示例
# Encode text input_text = "[CLS] [SYS] Hello, what can I help with you today? [USR] Find me a cheap restaurant nearby the north town." input_tokens = tokenizer.tokenize(input_text) story = torch.Tensor(tokenizer.convert_tokens_to_ids(input_tokens)).long() if len(story.size()) == 1: story = story.unsqueeze(0) # batch size dimension if torch.cuda.is_available(): tod_bert = tod_bert.cuda() story = story.cuda() with torch.no_grad(): input_context = {"input_ids": story, "attention_mask": (story > 0).long()} hiddens = tod_bert(**input_context)[0]
计算ToD-BERT推理时间延迟
如何正确地计算
深度学习中如何正确地measure inference time
问题:
- 在进行多batch训练或推理的时候,batch1被送进GPU后,CPU由于异步执行,不再等待batch1在GPU内执行完毕,而是直接对batch2进行预处理,此时若使用python的time库,停止计算时间的代码将在GPU执行完毕前被执行,导致时长计算错误。
- GPU在不工作时将关掉许多硬件模块,在调用GPU时需要重新初始化(GPU预热),占用大量时间,导致时间测算错误。
解决方法:
- 在真正需要的example前运行几个example,使得GPU不再处于省电模式。
- 使用
tr.cuda.event
,在GPU上测量时间 - 使用函数
torch.cuda.synchronize()
,使得CPU和GPU工作在同步执行模式。
在服务器上进行inference并计算inference时间
-
在
run_tod_lm_pretraining.sh
文件中修改batch size = 1
:gpu=$1 model_type=$2 bert_dir=$3 output_dir=$4 add1=$5 add2=$6 add3=$7 add4=$8 add5=$9 # ./run_tod_lm_pretraining.sh 0 bert bert-base-uncased save/pretrain/ToD-BERT-MLM --only_last_turn # ./run_tod_lm_pretraining.sh 0 bert bert-base-uncased save/pretrain/ToD-BERT-JNT --only_last_turn --add_rs_loss CUDA_VISIBLE_DEVICES=3 python my_tod_pretraining.py \ --task=usdl \ --model_type=${model_type} \ --model_name_or_path=${bert_dir} \ --output_dir=${output_dir} \ --do_train \ --do_eval \ --mlm \ --do_lower_case \ --evaluate_during_training \ --save_steps=2500 --logging_steps=1000 \ --per_gpu_train_batch_size=1 --per_gpu_eval_batch_size=1 \ ${add1} ${add2} ${add3} ${add4} ${add5}
-
使用上文办法,在
my_tod_pretraining.py
中引入计时相关语句:## with only MLM loss else: starter, ender = torch.cuda.Event(enable_timing=True), torch.cuda.Event(enable_timing=True) inputs = batch["context"].clone() if args.mlm: inputs, labels = mask_tokens(inputs, tokenizer, args) inputs = inputs.to(args.device) labels = labels.to(args.device) starter.record() outputs = model(inputs, masked_lm_labels=labels, attention_mask=inputs>0) ender.record() # WAIT FOR GPU SYNC torch.cuda.synchronize() curr_time = starter.elapsed_time(ender) print(curr_time)
-
由于训练时间较长,使用
tmux
命令:tmux new -s inference_time_measure
,进入tmux回话后还需要重新激活虚拟环境。\(base) dialogue@amax-13:/media/HD1/dche/ToD-BERT$ CUDA_VISIBLE_DEVICES=0 ./run_tod_lm_pretraining.sh 0 bert bert-base-uncased save/prtrain/ToD-BERT-MLM --only_last_turn --data_path ./../dialog_datasets Traceback (most recent call last): File "/media/HD1/dche/ToD-BERT/my_tod_pretraining.py", line 16, in <module> import numpy as np ModuleNotFoundError: No module named 'numpy' (base) dialogue@amax-13:/media/HD1/dche/ToD-BERT$ conda info --env # conda environments: # base * /media/HD1/dche/miniconda3 sum_env /media/HD1/dche/miniconda3/envs/sum_env tod_bert /media/HD1/dche/miniconda3/envs/tod_bert /media/HD1/miniconda3 (base) dialogue@amax-13:/media/HD1/dche/ToD-BERT$ conda activate tod_bert (tod_bert) dialogue@amax-13:/media/HD1/dche/ToD-BERT$ CUDA_VISIBLE_DEVICES=0 ./run_tod_lm_pretraining.sh 0 bert bert-base-uncased save/pretrain/ToD-BERT-MLM --only_last_turn --data_path ./../dialog_datasets
-
进行训练,观察输出结果
CUDA_VISIBLE_DEVICES=0 ./run_tod_lm_pretraining.sh 0 bert bert-base-uncased save/pretrain/ToD-BERT-MLM --only_last_turn --data_path ./../dialog_datasets
-
训练过程中可以使用
crtl+b d
从会话中分离(tod_bert) dialogue@amax-13:/media/HD1/dche/ToD-BERT$ tmux new -s inference_time_measure [detached (from session inference_time_measure)] (tod_bert) dialogue@amax-13:/media/HD1/dche/ToD-BERT$
-
可以查看当前的tmux会话并连接
(tod_bert) dialogue@amax-13:/media/HD1/dche/ToD-BERT$ tmux ls inference_time_measure: 1 windows (created Sun Nov 21 23:26:48 2021) [134x33] zym1: 1 windows (created Sun Nov 21 18:34:03 2021) [148x45] zym2: 1 windows (created Sun Nov 21 18:34:44 2021) [113x12] (tod_bert) dialogue@amax-13:/media/HD1/dche/ToD-BERT$ tmux attach -t inference_time_measure
-
为了便于记录inference time,可以将bash命令中的输出全部写入txt文件,
script -a 1.txt
,则之后shell中所有文字都将被记录在1.txt
中。