进阶案例,载入预训练的resnet50,在flowers数据集上做迁移学习,并使用新特性加速训练
下载resnet50预训练模型:http://download.tensorflow.org/models/resnet_v1_50_2016_08_28.tar.gz
模型解压后为:/tmp/model/resnet_v1_50.ckpt
使用预训练的模型在flowers数据集上做迁移学习,但是并不是模型的每一层都需要载入预置模型中的参数。由于预置模型是在ImageNet上训练的得到,ImageNet的分类数量为1000,而flowers的分类数量为5,所以模型最后一层logits分类层是不需要载入参数的。
获取模型元信息,并获取网络最后一层名字空间的统配符,利用MoXing-TensorFlow的内置超参checkpoint_exclude_patterns
,使得载入预训练模时,忽略指定层的参数。除了忽略logits分类层,这里还需要忽略checkpoint中的global_step参数,因为需要从第0步开始训练。
exclude_list = ['global_step']
model_meta = mox.get_model_meta(flags.model_name)
exclude_list.append(model_meta.default_logits_pattern)
checkpoint_exclude_patterns = ','.join(exclude_list)
mox.set_flag('checkpoint_exclude_patterns', checkpoint_exclude_patterns)
在mox.run
中,执行参数checkpoint_path
为/tmp/model/resnet_v1_50.ckpt
mox.run(input_fn=input_fn,
model_fn=model_fn,
optimizer_fn=optimizer_fn,
run_mode=mox.ModeKeys.TRAIN,
log_dir=flags.train_url,
checkpoint_path='/tmp/model/resnet_v1_50.ckpt',
max_number_of_steps=sys.maxint)
在mox.get_model_fn
中,传入data_format='NCHW'
和batch_norm_fused=True
,在GPU上的训练将会更快
mox_model_fn = mox.get_model_fn(
name=flags.model_name,
run_mode=mode,
num_classes=data_meta.num_classes,
weight_decay=0.00004,
data_format='NCHW',
batch_norm_fused=True)
使用多进程读取数据集,在mox.ImageClassificationRawDataset
中加入参数reader_class=mox.AsyncRawGenerator
dataset = mox.ImageClassificationRawDataset(data_meta,
batch_size=flags.batch_size,
num_epochs=20,
augmentation_fn=data_augmentation_fn,
reader_class=mox.AsyncRawGenerator)
训练过程中每层的权重都存成FP32格式(Mater-Weights),每次训练时都会将FP32的权重降精度至FP16( a master copy),前向输出和后向梯度都使用FP16进行计算,更新时将FP16的梯度累加到FP32的Mater-Weight上。
相关论文:https://arxiv.org/abs/1710.03740
在前向计算之前,先将images
转换成fp16,再强制使用fp32来存储参数变量
images = tf.cast(images, tf.float16)
with mox.var_scope(force_dtype=tf.float32):
logits, _ = mox_model_fn(images)
此时logits也会成为fp16,但是在计算正确率的方法tf.nn.in_top_k
中只能使用float32的tensor,所以在这个API中,先将logits转换成fp32再做计算(但是loss计算一定要使用fp16的logits,这样才能使得反向传播时计算仍然是使用fp16的)
logits_fp32 = tf.cast(logits, tf.float32)
accuracy = tf.reduce_mean(tf.cast(tf.nn.in_top_k(logits_fp32, labels, 1), tf.float32))
通常在使用混合精度的场景下,需要对loss进行缩放来减少精度损失,设置MoXing-TensorFlow的内置超参loss_scale
mox.set_flag('loss_scale', 1024.0)
在Nvidia-Tesla-K80设备上混合精度没有明显的性能提升,但是在Nvidia-Tesla-V100上会有2-3倍的性能提升
关于TensorFlow-Serving的详细文档请参考:https://www.tensorflow.org/serving
MoXing-TensorFlow中可以导出一份用于TF-Serving的预测模型,可以被TF-Serving使用
在model_fn的返回值mox.ModelSpec
中指定参数export_spec
中传入一个mox.ExportSpec
的实例,其中inputs_dict
用于指定输入节点,outputs_dict用于指定输出节点,模型的版本号能够自适应自增。
def model_fn(inputs, mode, **kwargs):
...
export_spec = mox.ExportSpec(inputs_dict={'images': images},
outputs_dict={'logits': logits_fp32})
return mox.ModelSpec(loss=loss,
log_info={'loss': loss, 'accuracy': accuracy},
export_spec=export_spec)
在ModelArts中使用模型预测相关文档可以参考:此案例
完整代码请参考:mox_flowers_advanced.py
执行训练:
python mox_flowers_advanced.py \
--data_url=/tmp/tensorflow/flower_photos \
--train_url=/tmp/flowers \
--checkpoint_url=/tmp/model/resnet_v1_50.ckpt \
--num_gpus=4
使用 4 * Nvidia-Tesla-K80 运行时间大约为:334秒,在训练集上的训练精度约为:95%