diff --git a/README.md b/README.md index 1ef15c33dc71be53cae17f55a6077b90a51485a1..a052a2c89e0b58bf1416d6599491dfd78ff7acac 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,8 @@ git clone https://github.com/PaddlePaddle/PALM.git ## 目录结构 -- backbone: 多任务学习的主干网络表示,支持bert, ernie, xlnet等,用户可自定义添加 -- config:存放各个任务的配置文件,用户添加任务时需在此建立该任务的配置文件 +- backbone: 多任务学习的主干网络表示,支持bert, ernie等,用户可自定义添加 +- config:存放各个任务实例的配置文件,用户添加任务时需在此建立该任务的配置文件 - data: 存放各个任务的数据集 - pretrain_model: 存放预训练模型、字典及其相关配置 - optimizer: 优化器,用户可在此自定义优化器 @@ -49,7 +49,7 @@ bash run.sh - do_train:*(bool)* 训练标志位 - do_predict:*(bool)* 预测标志位,目前仅支持对主任务进行预测 - checkpoint_path: *(str)* 模型保存、训练断点恢复和预测模型载入路径,从该路径载入模型时默认读取最后一个训练step的模型 -- backbone_model:*(str)* 使用的骨干网络,名称选取自`backbone`目录下的模块 +- backbone_model:*(str)* 使用的骨干网络,名称选取自`backbone`目录下的模块。注意,更换backbone时,若使用预训练模型,应同步更换预训练模型参数、配置和字典等相关字段 - vocab_path:*(str)* 字典文件,纯文本格式存储,其中每行为一个单词 - optimizer:*(str)* 优化器名称,名称选取自`optimizer`中的文件名 - learning_rate:*(str)* 训练阶段的学习率 @@ -74,7 +74,7 @@ bash run.sh ### 使用示例 若内置任务可满足用户需求,或用户已经完成自定义任务的添加,可通过如下方式直接启动多任务学习。 -例如,框架中内置了一个小数据集,包含MRQA阅读理解评测数据`mrqa`、MaskLM训练数据`mlm4mrqa`和问题与答案所在上下文的匹配数据集`am4mrqa`,而在框架中已经内置了机器阅读理解任务(`reading_comprehension`)、问答匹配任务(`answer_matching`)和掩码语言模型任务(`mask_language_model`),用户可通过如下流程完成多任务学习的启动。 +例如,框架中内置了一个小数据集,包含MRQA阅读理解评测数据`mrqa`、MaskLM训练数据`mlm4mrqa`和问题与答案所在上下文的匹配数据集`am4mrqa`,而在框架中已经内置了机器阅读理解任务(`reading_comprehension`)、掩码语言模型任务(`mask_language_model`)和问答匹配任务(`answer_matching`)。这里我们希望用掩码语言模型和问答匹配任务来提升机器阅读理解任务的效果,那么我们可通过如下流程完成多任务学习的启动。 首先在config文件夹中添加训练任务相关的配置文件: @@ -107,7 +107,10 @@ batch_size: 4 in_tokens: False ``` -而后可以在主配置文件`mtl_config.yaml`中完成多任务学习的配置,其中,使用`main_task`字段指定主任务,使用`auxilary_task`可指定辅助任务,多个辅助任务之间使用空格"` `"隔开 +而后可以在主配置文件`mtl_config.yaml`中完成多任务学习的配置,其中,使用`main_task`字段指定主任务,使用`auxilary_task`可指定辅助任务,多个辅助任务之间使用空格"` `"隔开。 + +epoch的设定仅针对设定为主任务有效,`mix ratio`的基准值1.0也是针对主任务的训练步数而言的。例如,对于`epoch=2`,若将`reading_comprehension`任务的`mix ratio`设定为1.0,`mask_language_model`的`mix ratio`设定为0.5,那么`reading_comprehension`任务将训练两个完整的`epoch`,而`mask_language_model`任务的训练步数等于`reading_comprehension`训练步数的一半。 + ```python main_task: "reading_comprehension" auxiliary_task: "mask_language_model answer_matching" @@ -127,8 +130,8 @@ epoch: 2 位于`./config`目录。存放各个任务实例的配置文件,使用`yaml`格式描述。配置文件中的必选字段包括 -- in_tokens:是否使用lod tensor的方式构造batch,当`in_tokens`为False时,使用padding方式构造batch。 - batch_size:每个训练或推理step所使用样本数。当`in_tokens`为True时,`batch_size`表示每个step所包含的tokens数量。 +- in_tokens:是否使用lod tensor的方式构造batch,当`in_tokens`为False时,使用padding方式构造batch。 训练阶段包含的必选字段包括 @@ -218,6 +221,13 @@ epoch: 2 3. 启动多任务学习:sh run.sh ``` +## 框架结构与运行原理 +框架结构如图所示 + +![框架图](https://tva1.sinaimg.cn/large/006y8mN6ly1g7goo0bjzwj31c20om13h.jpg) + +其中`mtl_config.yaml`用于配置多任务主控的参数设定,每个任务实例的配置由用户完成后放置于`config`文件夹中。当用户运行`run.sh`后,脚本启动多任务学习控制器,控制器开始解析`mtl_config.yaml`和各个任务实例的配置文件,进而创建backbone、为各个任务创建reader和任务层,最后控制器启动训练任务,实现多任务训练。 + ## License This tutorial is contributed by [PaddlePaddle](https://github.com/PaddlePaddle/Paddle) and licensed under the [Apache-2.0 license](https://github.com/PaddlePaddle/models/blob/develop/LICENSE). diff --git a/mtl_config.yaml b/mtl_config.yaml index e6bbcf66ff24803fc6e564171db4738b43240726..afa15f7255938c515e364aa298ae194219c0f81a 100644 --- a/mtl_config.yaml +++ b/mtl_config.yaml @@ -31,6 +31,5 @@ max_seq_len: 512 use_ema: True ema_decay: 0.9999 random_seed: 0 -use_fp16: False loss_scaling: 1.0 diff --git a/mtl_run.py b/mtl_run.py index eb23f7576daaebc1fa6defe41b180fa62c84e3d0..7f457b9d0eb37a755d0cb280d5df7e211f22f476 100644 --- a/mtl_run.py +++ b/mtl_run.py @@ -275,14 +275,14 @@ def train(multitask_config): exe, args.pretrain_model_path, main_program=startup_prog, - use_fp16=args.use_fp16) + use_fp16=False) if args.checkpoint_path: if os.path.exists(args.checkpoint_path): init_checkpoint( exe, args.checkpoint_path, main_program=startup_prog, - use_fp16=args.use_fp16) + use_fp16=False) else: os.makedirs(args.checkpoint_path) @@ -294,7 +294,7 @@ def train(multitask_config): exe, args.checkpoint_path, main_program=test_prog, - use_fp16=args.use_fp16) + use_fp16=False) if args.do_train: print('start training...') diff --git a/optimizer/bert_optimizer.py b/optimizer/bert_optimizer.py index 412604daa0037fa6428104e555761de602e2c40b..7300009b8a317c6473dc11b4f125cf7f1776134d 100644 --- a/optimizer/bert_optimizer.py +++ b/optimizer/bert_optimizer.py @@ -19,8 +19,6 @@ from __future__ import print_function import numpy as np import paddle.fluid as fluid -from utils.fp16 import create_master_params_grads, master_param_to_train_param - def linear_warmup_decay(learning_rate, warmup_steps, num_train_steps): """ Applies linear warmup of learning rate from 0 and decay to 0.""" @@ -73,8 +71,6 @@ def optimization(loss, programs, args): clip_norm_thres = 1.0 # When using mixed precision training, scale the gradient clip threshold # by loss_scaling - if args.use_fp16 and args.loss_scaling > 1.0: - clip_norm_thres *= args.loss_scaling fluid.clip.set_gradient_clip( clip=fluid.clip.GradientClipByGlobalNorm(clip_norm=clip_norm_thres)) @@ -89,44 +85,19 @@ def optimization(loss, programs, args): param_list = dict() - if args.use_fp16: - param_grads = optimizer.backward(loss) - master_param_grads = create_master_params_grads( - param_grads, train_program, startup_prog, args.loss_scaling) - - for param, _ in master_param_grads: - param_list[param.name] = param * 1.0 - param_list[param.name].stop_gradient = True - - optimizer.apply_gradients(master_param_grads) - - if args.weight_decay > 0: - for param, grad in master_param_grads: - if exclude_from_weight_decay(param.name.rstrip(".master")): - continue - with param.block.program._optimized_guard( - [param, grad]), fluid.framework.name_scope("weight_decay"): - updated_param = param - param_list[ - param.name] * weight_decay * scheduled_lr - fluid.layers.assign(output=param, input=updated_param) - - master_param_to_train_param(master_param_grads, param_grads, - train_program) - - else: - for param in train_program.global_block().all_parameters(): - param_list[param.name] = param * 1.0 - param_list[param.name].stop_gradient = True - - _, param_grads = optimizer.minimize(loss) - - if args.weight_decay > 0: - for param, grad in param_grads: - if exclude_from_weight_decay(param.name): - continue - with param.block.program._optimized_guard( - [param, grad]), fluid.framework.name_scope("weight_decay"): - updated_param = param - param_list[ - param.name] * args.weight_decay * scheduled_lr - fluid.layers.assign(output=param, input=updated_param) + for param in train_program.global_block().all_parameters(): + param_list[param.name] = param * 1.0 + param_list[param.name].stop_gradient = True + + _, param_grads = optimizer.minimize(loss) + + if args.weight_decay > 0: + for param, grad in param_grads: + if exclude_from_weight_decay(param.name): + continue + with param.block.program._optimized_guard( + [param, grad]), fluid.framework.name_scope("weight_decay"): + updated_param = param - param_list[ + param.name] * args.weight_decay * scheduled_lr + fluid.layers.assign(output=param, input=updated_param) diff --git a/paradigm/answer_matching.py b/paradigm/answer_matching.py index 3c2f79749c180b98c1ad7b53f7f93a9284ac98f6..d1bd2023882c7c99ac4a75e75ce788495dca2096 100644 --- a/paradigm/answer_matching.py +++ b/paradigm/answer_matching.py @@ -25,9 +25,6 @@ def compute_loss(output_tensors, args=None): logits=logits, label=labels, return_softmax=True) loss = fluid.layers.mean(x=ce_loss) - if args.use_fp16 and args.loss_scaling > 1.0: - loss *= args.loss_scaling - return loss diff --git a/paradigm/mask_language_model.py b/paradigm/mask_language_model.py index 2725c8dc90a11cf81e2cdbfbf8d0d4a020f0fadd..fa13d75b306f249021ced83f5546ba922001f29b 100644 --- a/paradigm/mask_language_model.py +++ b/paradigm/mask_language_model.py @@ -42,7 +42,7 @@ def create_model(reader_input, base_model=None, is_training=True, args=None): _hidden_act = config['hidden_act'] _word_emb_name = "word_embedding" - _dtype = "float16" if args.use_fp16 else "float32" + _dtype = "float32" _param_initializer = fluid.initializer.TruncatedNormal( scale=config['initializer_range']) diff --git a/paradigm/reading_comprehension.py b/paradigm/reading_comprehension.py index af73630ab3c2219c0ed1d946483cedc5b5a5d1d3..5f38842720d9f503412891067528cc0aefbf194f 100644 --- a/paradigm/reading_comprehension.py +++ b/paradigm/reading_comprehension.py @@ -35,8 +35,6 @@ def compute_loss(output_tensors, args=None): start_loss = _compute_single_loss(start_logits, start_positions) end_loss = _compute_single_loss(end_logits, end_positions) total_loss = (start_loss + end_loss) / 2.0 - if args.use_fp16 and args.loss_scaling > 1.0: - total_loss = total_loss * args.loss_scaling return total_loss diff --git a/reader/reading_comprehension_reader.py b/reader/reading_comprehension_reader.py index 8480b1c9ca663b926d5d1830376887d861741c92..c3eaa7243529dd03ca82f66c0b1d41239ebdcb78 100644 --- a/reader/reading_comprehension_reader.py +++ b/reader/reading_comprehension_reader.py @@ -484,7 +484,8 @@ class InputFeatures(object): def read_mrqa_examples(input_file, is_training, with_negative=False): """Read a MRQA json file into a list of MRQAExample.""" - print("loading mrqa raw data...") + phase = 'training' if is_training else 'testing' + print("loading mrqa {} data...".format(phase)) with open(input_file, "r") as reader: input_data = json.load(reader)["data"]