建议使用以下浏览器,以获得最佳体验。 IE 9.0+以上版本 Chrome 31+ 谷歌浏览器 Firefox 30+ 火狐浏览器
请选择 进入手机版 | 继续访问电脑版
设置昵称

在此一键设置昵称,即可参与社区互动!

确定
我再想想
选择版块
标签
您还可以添加5个标签
  • 没有搜索到和“关键字”相关的标签
  • 云产品
  • 解决方案
  • 技术领域
  • 通用技术
  • 平台功能
取消

qoooqqq

发帖: 6粉丝: 1

级别 : 高级会员

发消息 + 关注

更新于2020年09月30日 16:17:42 3232 5
直达本楼层的链接
楼主
显示全部楼层
[干货分享] 【昇腾模型训练挑战】Bert-Base模型昇腾910迁移过程

偶然的看到了这个活动 刚好又看见模型列表有个迁移起来挺简单的模型就参加了!修改的代码不多迁移起来也很简单


领域 模型名称 论文 参考数据集
Question   Answering BERT BERT: Pre-training of   Deep Bidirectional Transformers for Language Understanding SQuAD2.0

代码的迁移

首先先从Google Research下载用TF实现的源码(url

根据模型列表给出的SQuAD2.0数据集 今天就来修改run_squad.py相关的文件

文件头部加入NPU模块

from npu_bridge.estimator.npu.npu_config import NPURunConfig
from npu_bridge.estimator import npu_ops 
from npu_bridge.estimator.npu.npu_estimator import NPUEstimator,NPUEstimatorSpec

初始化TF的GPU调用

gpu_thread_count = 2
os.environ['TF_GPU_THREAD_MODE'] = 'gpu_private'
os.environ['TF_GPU_THREAD_COUNT'] = str(gpu_thread_count)
os.environ['TF_USE_CUDNN_BATCHNORM_SPATIAL_PERSISTENT'] = '1'
os.environ['TF_ENABLE_WINOGRAD_NONFUSED'] = '1'

mian的修改:

因为原版的是兼容TPU训练所以基本上看见TPU的函数全都要改掉或删掉

我就直接删掉了

if FLAGS.use_tpu and FLAGS.tpu_name:    
tpu_cluster_resolver = tf.contrib.cluster_resolver.TPUClusterResolver(    
FLAGS.tpu_name, zone=FLAGS.tpu_zone, project=FLAGS.gcp_project)

然后就是estimator的运行配置修改

run_config = tf.contrib.tpu.RunConfig(    
cluster=tpu_cluster_resolver,    
master=FLAGS.master,    
model_dir=FLAGS.output_dir,    
save_checkpoints_steps=FLAGS.save_checkpoints_steps,    
tpu_config=tf.contrib.tpu.TPUConfig(    
iterations_per_loop=FLAGS.iterations_per_loop,    
num_shards=FLAGS.num_tpu_cores,    
per_host_input_for_training=is_per_host))
#改为
  config = tf.ConfigProto(
            inter_op_parallelism_threads=0,
            intra_op_parallelism_threads=0,
            allow_soft_placement=True)
  config.gpu_options.allow_growth = True
  
  run_config = NPURunConfig(
                model_dir=FLAGS.output_dir,
                save_checkpoints_steps=FLAGS.save_checkpoints_steps,
                iterations_per_loop=FLAGS.iterations_per_loop,
                session_config=config,
                precision_mode="allow_mix_precision",#开启混合精度训练
                keep_checkpoint_max=15)
estimator = tf.contrib.tpu.TPUEstimator(    
use_tpu=FLAGS.use_tpu,    
model_fn=model_fn,    
config=run_config,    
train_batch_size=FLAGS.train_batch_size,    
predict_batch_size=FLAGS.predict_batch_size)    
#改为
estimator = NPUEstimator(
                model_fn=model_fn,
                config=run_config,
                model_dir=FLAGS.output_dir,
                params={"batch_size":FLAGS.train_batch_size,"predict_batch_size":FLAGS.predict_batch_size})

然后修改model_fn_builder模型初始化函数

还是一样为了省事 TPU的删掉

if use_tpu:    
def tpu_scaffold():    
tf.train.init_from_checkpoint(init_checkpoint, assignment_map)    
return tf.train.Scaffold()

然后TPUEstimatorSpec迁移

output_spec = tf.contrib.tpu.TPUEstimatorSpec(    
mode=mode,    
loss=total_loss,    
train_op=train_op,    
scaffold_fn=scaffold_fn)    
#改为 这里加了个loss打印 不影响训练无所谓加不加
logging_hook = tf.train.LoggingTensorHook({"loss": total_loss}, every_n_iter=FLAGS.iterations_per_loop)
      output_spec = NPUEstimatorSpec(
          mode=mode,
          loss=total_loss,
          training_hooks=[logging_hook],
          train_op=train_op,
          scaffold=scaffold_fn)

#预测:
output_spec = tf.contrib.tpu.TPUEstimatorSpec(    
mode=mode, predictions=predictions, scaffold_fn=scaffold_fn)    
#改为
output_spec = NPUEstimatorSpec(
          mode=mode, predictions=predictions, scaffold=scaffold_fn)

然后是input_fn_builder 数据输入函数的修改

数据输入大小必须要和batch_size大小一致

"一般情况下,直接迁移,无需改造。但如下情况需要进行适配修改: 如下情况需要进行适配修改: 由于当前仅支持固定shape下的训练,
也就是在进行图编译时shape的值必须是已知 的。当原始网络脚本中使用dataset.batch(batch_size)返回动态形状时,
由于数据流中 剩余的样本数可能小于batch大小,因此,在昇腾AI处理器上进行训练时,
请将 drop_remainder设置为True:  dataset = dataset.batch(batch_size, drop_remainder=True) 
这可能会丢弃文件中的后几个样本,以确保每个批量都具有静态形状 (batch_size)。但需要注意的是:推理时,当后一次迭代的推理数据量小于batch
size时,需要补齐空白数据到batch size,因为有些脚本后会加个断言,预测结果的 数量要和预测数据的数量一致,此种情况会导致训练失败。"
d = d.apply(    
tf.contrib.data.map_and_batch(    
lambda record: _decode_record(record, name_to_features),    
batch_size=batch_size,    
drop_remainder=drop_remainder))    
#改为
d = d.apply(
        tf.contrib.data.map_and_batch(
            lambda record: _decode_record(record, name_to_features),
            batch_size=batch_size,
            drop_remainder=True))#不一致直接丢掉

至此训练文件就修改完成了!

然后是模型定义文件modeling.py

头部引入NPU模块

from npu_bridge.estimator import npu_ops 
from npu_bridge.estimator.npu_unary_ops import npu_unary_ops

修改dropout函数:

output = tf.nn.dropout(input_tensor, 1.0 - dropout_prob)
#改为
output = npu_ops.dropout(input_tensor, 1.0 - dropout_prob)

修改gelu激活函数:

def gelu(x):    
"""Gaussian Error Linear Unit.    
  This is a smoother version of the RELU.    
  Original paper: https://arxiv.org/abs/1606.08415    
  Args:    
    x: float Tensor to perform activation.    
  Returns:    
    `x` with the GELU activation applied.    
  """    
cdf = 0.5 * (1.0 + tf.tanh(    
(np.sqrt(2 / np.pi) * (x + 0.044715 * tf.pow(x, 3)))))    
return x * cdf    

#改为
def gelu(x):
  return npu_unary_ops.gelu(x)

模型文件也改完了!

然后改优化器文件optimization.py 其实直接用原版也是可以的 但可能是混合精度训练的问题会导致最后的精度很大概率会在65-71之间徘徊达不到官方的76(但我最好的训练结果是在原版文件下训练的)!这里也可以使用NVIDIA的文件修改为NPU的(url

有很多启动参数可以直接删掉这里就不写出来了,重要的是LossScale的修改

头部引入NPU模块

from npu_bridge.estimator.npu.npu_optimizer import NPUDistributedOptimizer
from npu_bridge.estimator.npu import npu_loss_scale_optimizer as lso
from npu_bridge.estimator.npu import npu_loss_scale_manager as lsm_lib

LossScale:

if use_fp16:    
loss_scaler = tf.train.experimental.DynamicLossScale(initial_loss_scale=init_loss_scale, increment_period=1000, multiplier=2.0)    
optimizer = tf.train.experimental.enable_mixed_precision_graph_rewrite(optimizer, loss_scaler)    
loss_scale_value = tf.identity(loss_scaler(), name="loss_scale")    
if manual_fp16:    
loss_scale_manager = tf.contrib.mixed_precision.ExponentialUpdateLossScaleManager(init_loss_scale=init_loss_scale,    
incr_every_n_steps=1000,    
decr_every_n_nan_or_inf=2,    
decr_ratio=0.5)    
optimizer = tf.contrib.mixed_precision.LossScaleOptimizer(optimizer, loss_scale_manager)    
#这里偷懒直接就改成固定了
optimizer = NPUDistributedOptimizer(optimizer)
  opt_tmp = optimizer
  loss_scale_manager = lsm_lib.ExponentialUpdateLossScaleManager(init_loss_scale=2**32, incr_every_n_steps=1000, decr_every_n_nan_or_inf=2, decr_ratio=0.5)
  optimizer = lso.NPULossScaleOptimizer(opt_tmp, loss_scale_manager)

#你也可以根据网络模型移植训练指南.pdf
来改成自定义参数
if FLAGS.use_fp16 and (FLAGS.npu_bert_loss_scale not in [None, -1]):
	opt_tmp = opt
	if FLAGS.npu_bert_loss_scale == 0:
		loss_scale_manager = ExponentialUpdateLossScaleManager(init_loss_scale=2**32, incr_every_n_steps=1000, decr_every_n_nan_or_inf=2, decr_ratio=0.5)
	elif FLAGS.npu_bert_loss_scale >= 1:
		loss_scale_manager = FixedLossScaleManager(loss_scale=FLAGS.npu_bert_loss_scale)
	else: 
		raise ValueError("Invalid loss scale: %d" % FLAGS.npu_bert_loss_scale)
	if ops_adapter.size() > 1:
		opt = NPULossScaleOptimizer(opt_tmp, loss_scale_manager, is_distributed=True)
	else:
		opt = NPULossScaleOptimizer(opt_tmp, loss_scale_manager)

到这里全部代码就已经迁移完成了!可以看到迁移起来非常简单一共就没几行需要修改的


这里为了方便ModelArts的训练修改了启动参数可以直接参考我修改好的源码

举报
分享

分享文章到朋友圈

分享文章到微博

qoooqqq

发帖: 6粉丝: 1

级别 : 高级会员

发消息 + 关注

更新于2020年09月30日 16:23:04
直达本楼层的链接
沙发
显示全部楼层

训练过程

首先把修改后的代码上传至OBS然后在ModelArts新建算法

image.png


定义超参数

image.png

完成后即可开始创建训练作业image.png


超参数的设置很有讲究

image.png

根据google-research官方的推荐学习率为3e-4, 1e-4, 5e-5, 3e-5 批次为8, 16, 32, 64, 128 如果预测精度达不到预期可以根据这几个学习率进行多次尝试!

这里可以参考stanford小组作业的成果(web.stanford.edu/class/cs224n/posters/15845024.pdf)

image.png

batch_size : 32

learning_rate : 3e-5

epochs : 3

max_seq_length : 384

然后开始训练:

数据预处理输出tf_record 大概需要15分钟

image.png


显示训练参数并开始训练

image.png

根据设置iterations_per_loop的次数打印loss

image.png

达到save_checkpoints_steps的次数保存ckpt

image.png

直到最后训练完成后会进行一次预测并保存结果到文件

image.png

训练就完成了!

然后我们根据SQuAD给的dev集验证文件验证我们模型精度 

image.png

根据数据集验证脚本计算出来的best_f1_thresh值重新进行模型预测

python ./run_squad.py \
--do_train=False \
--do_predict=True \
--model_dir=./model \
--data_dir=./squad2 \
--output_dir=./output_dir \
--train_batch_size=32 \
--learning_rate=3e-5 \
--num_train_epochs=3 \
--max_seq_length=384 \
--version_2_with_negative=True \
--iterations_per_loop=1000 \
--predict_batch_size=8 \
--save_checkpoints_steps=1000 \
--init_checkpoint=bert_model.ckpt \
--null_score_diff_threshold=-6.09375


即可得到更好的精度

image.png


虽然不能上传到SQuAD官方排行榜进行test集的精度验证 但对比了下排行应该也差不多

image.png

评论
张辉 2020-9-28 18:51 评论

优秀。先不回帖打扰。。。

... 查看全部
rain酱 2020-9-29 09:29 评论

棒!!!!感谢对本次活动的参加和过程分享~

... 查看全部
点赞 评论 引用 举报

山人_mhc

发帖: 101粉丝: 19

级别 : 中级会员

发消息 + 关注

发表于2020年09月29日 09:49:32
直达本楼层的链接
板凳
显示全部楼层

优秀!!!

点赞 评论 引用 举报

小果果

发帖: 116粉丝: 1

级别 : 外部版主

发消息 + 关注

发表于2020年09月30日 20:26:39
直达本楼层的链接
地板
显示全部楼层

优秀!!!

点赞 评论 引用 举报

Tianyi_Li

发帖: 287粉丝: 88

级别 : 外部版主

发消息 + 关注

发表于2020年09月30日 21:14:30
直达本楼层的链接
5#
显示全部楼层

很有意思。

点赞 评论 引用 举报

火箭少女101

发帖: 1粉丝: 0

级别 : 新手上路

发消息 + 关注

发表于2020年11月05日 20:24:26
直达本楼层的链接
6#
显示全部楼层

厉害了,我也正在迁移,还没搞定

点赞 评论 引用 举报

游客

富文本
Markdown
您需要登录后才可以回帖 登录 | 立即注册