blob: b363e0244a107ef5909fad0593685e993d54d3be [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
import os
import logging
import argparse
import mxnet as mx
from common import modelzoo
import gluoncv
from gluoncv.model_zoo import get_model
from mxnet.contrib.amp import amp
import numpy as np
def download_model(model_name, logger=None):
dir_path = os.path.dirname(os.path.realpath(__file__))
model_path = os.path.join(dir_path, 'model')
if logger is not None:
logger.info('Downloading model {}... into path {}'.format(model_name, model_path))
return modelzoo.download_model(args.model, os.path.join(dir_path, 'model'))
def save_symbol(fname, sym, logger=None):
if logger is not None:
logger.info('Saving symbol into file at {}'.format(fname))
sym.save(fname, remove_amp_cast=False)
def save_params(fname, arg_params, aux_params, logger=None):
if logger is not None:
logger.info('Saving params into file at {}'.format(fname))
save_dict = {('arg:%s' % k): v.as_in_context(mx.cpu()) for k, v in arg_params.items()}
save_dict.update({('aux:%s' % k): v.as_in_context(mx.cpu()) for k, v in aux_params.items()})
mx.nd.save(fname, save_dict)
if __name__ == '__main__':
symbolic_models = ['imagenet1k-resnet-152',
'imagenet1k-resnet-18',
'imagenet1k-resnet-34',
'imagenet1k-resnet-50',
'imagenet1k-resnet-101',
'imagenet1k-resnext-50',
'imagenet1k-resnext-101',
'imagenet1k-resnext-101-64x4d',
'imagenet11k-place365ch-resnet-152',
'imagenet11k-place365ch-resnet-50']
# Faster RCNN and Mask RCNN commented because of model loading issues
# https://github.com/dmlc/gluon-cv/issues/1034
gluon_models = [#'faster_rcnn_fpn_resnet50_v1b_coco',
'mobilenetv2_0.75',
'cifar_resnet56_v1',
'mobilenet0.25',
'mobilenet1.0',
#'mask_rcnn_fpn_resnet50_v1b_coco',
'simple_pose_resnet152_v1b',
'ssd_512_resnet50_v1_voc',
#'faster_rcnn_resnet50_v1b_voc',
'cifar_resnet20_v1',
'yolo3_darknet53_voc',
'resnet101_v1c',
'simple_pose_resnet18_v1b',
#'mask_rcnn_resnet50_v1b_coco',
'ssd_512_mobilenet1.0_coco',
'vgg19_bn',
#'faster_rcnn_resnet50_v1b_coco',
'cifar_resnet110_v1',
'yolo3_mobilenet1.0_voc',
'cifar_resnext29_16x64d',
'resnet34_v1',
'densenet121',
#'mask_rcnn_fpn_resnet101_v1d_coco',
'vgg13_bn',
'vgg19',
'resnet152_v1d',
'resnet152_v1s',
'densenet201',
'alexnet',
'se_resnext50_32x4d',
'resnet50_v1d_0.86',
'resnet18_v1b_0.89',
'yolo3_darknet53_coco',
'resnet152_v1',
'resnext101_64x4d',
'vgg13',
'resnet101_v1d_0.76',
'simple_pose_resnet50_v1d',
'senet_154',
'resnet50_v1',
'se_resnext101_32x4d',
'fcn_resnet101_voc',
'resnet152_v2',
#'mask_rcnn_resnet101_v1d_coco',
'squeezenet1.1',
'mobilenet0.5',
'resnet34_v2',
'resnet18_v1',
'resnet152_v1b',
'resnet101_v2',
'cifar_resnet56_v2',
'ssd_512_resnet101_v2_voc',
'resnet50_v1d_0.37',
'mobilenetv2_0.5',
#'faster_rcnn_fpn_bn_resnet50_v1b_coco',
'resnet50_v1c',
'densenet161',
'simple_pose_resnet50_v1b',
'resnet18_v1b',
'darknet53',
'fcn_resnet50_ade',
'cifar_wideresnet28_10',
'simple_pose_resnet101_v1d',
'vgg16',
'ssd_512_resnet50_v1_coco',
'resnet101_v1d_0.73',
'squeezenet1.0',
'resnet50_v1b',
#'faster_rcnn_resnet101_v1d_coco',
'ssd_512_mobilenet1.0_voc',
'cifar_wideresnet40_8',
'cifar_wideresnet16_10',
'cifar_resnet110_v2',
'resnet101_v1s',
'mobilenetv2_0.25',
'resnet152_v1c',
'se_resnext101_64x4d',
#'faster_rcnn_fpn_resnet101_v1d_coco',
'resnet50_v1d',
'densenet169',
'resnet34_v1b',
'resnext50_32x4d',
'resnet101_v1',
'resnet101_v1b',
'resnet50_v1s',
'mobilenet0.75',
'cifar_resnet20_v2',
'resnet101_v1d',
'vgg11_bn',
'resnet18_v2',
'vgg11',
'simple_pose_resnet101_v1b',
'resnext101_32x4d',
'resnet50_v2',
'vgg16_bn',
'mobilenetv2_1.0',
'resnet50_v1d_0.48',
'resnet50_v1d_0.11',
'fcn_resnet101_ade',
'simple_pose_resnet152_v1d',
'yolo3_mobilenet1.0_coco',
'fcn_resnet101_coco']
# TODO(anisub): add support for other models from gluoncv
# Not supported today mostly because of broken net.forward calls
segmentation_models = ['deeplab_resnet50_ade',
'psp_resnet101_voc',
'deeplab_resnet152_voc',
'deeplab_resnet101_ade',
'deeplab_resnet152_coco',
'psp_resnet101_ade',
'deeplab_resnet101_coco',
'psp_resnet101_citys',
'psp_resnet50_ade',
'psp_resnet101_coco',
'deeplab_resnet101_voc']
calib_ssd_models = ["ssd_512_vgg16_atrous_voc",
"ssd_300_vgg16_atrous_voc",
"ssd_300_vgg16_atrous_coco"]
calib_inception_models = ["inceptionv3"]
gluon_models = gluon_models + segmentation_models + \
calib_ssd_models + calib_inception_models
models = symbolic_models + gluon_models
parser = argparse.ArgumentParser(description='Convert a provided FP32 model to a mixed precision model')
parser.add_argument('--model', type=str, choices=models)
parser.add_argument('--run-dummy-inference', action='store_true', default=False,
help='Will generate random input of shape (1, 3, 224, 224) '
'and run a dummy inference forward pass')
parser.add_argument('--use-gluon-model', action='store_true', default=False,
help='If enabled, will download pretrained model from Gluon-CV '
'and convert to mixed precision model ')
parser.add_argument('--cast-optional-params', action='store_true', default=False,
help='If enabled, will try to cast params to target dtype wherever possible')
args = parser.parse_args()
logging.basicConfig()
logger = logging.getLogger('logger')
logger.setLevel(logging.INFO)
if not args.use_gluon_model:
assert args.model in symbolic_models, "Please choose one of the available symbolic models: {} \
If you want to use gluon use the script with --use-gluon-model".format(symbolic_models)
prefix, epoch = download_model(model_name=args.model, logger=logger)
sym, arg_params, aux_params = mx.model.load_checkpoint(prefix, epoch)
result_sym, result_arg_params, result_aux_params = amp.convert_model(sym, arg_params, aux_params,
cast_optional_params=args.cast_optional_params)
sym_name = "%s-amp-symbol.json" % (prefix)
save_symbol(sym_name, result_sym, logger)
param_name = '%s-%04d.params' % (prefix + '-amp', epoch)
save_params(param_name, result_arg_params, result_aux_params, logger)
if args.run_dummy_inference:
logger.info("Running inference on the mixed precision model with dummy input, batch size: 1")
mod = mx.mod.Module(result_sym, data_names=['data'], label_names=['softmax_label'], context=mx.gpu(0))
mod.bind(data_shapes=[['data', (1, 3, 224, 224)]], label_shapes=[['softmax_label', (1,)]])
mod.set_params(arg_params, aux_params)
mod.forward(mx.io.DataBatch(data=[mx.nd.ones((1, 3, 224, 224))],
label=[mx.nd.ones((1,))]))
result = mod.get_outputs()[0].asnumpy()
logger.info("Inference run successfully")
else:
assert args.model in gluon_models, "Please choose one of the available gluon models: {} \
If you want to use symbolic model instead, remove --use-gluon-model when running the script".format(gluon_models)
shape = None
if args.model in segmentation_models:
shape = (1, 3, 480, 480)
elif args.model in calib_ssd_models:
shape = (1, 3, 512, 544)
elif args.model in calib_inception_models:
shape = (1, 3, 299, 299)
else:
shape = (1, 3, 224, 224)
net = gluoncv.model_zoo.get_model(args.model, pretrained=True)
net.hybridize()
result_before1 = net.forward(mx.nd.random.uniform(shape=shape))
net.export("{}".format(args.model))
net = amp.convert_hybrid_block(net, cast_optional_params=args.cast_optional_params)
net.export("{}-amp".format(args.model), remove_amp_cast=False)
if args.run_dummy_inference:
logger.info("Running inference on the mixed precision model with dummy inputs, batch size: 1")
result_after = net.forward(mx.nd.random.uniform(shape=shape, dtype=np.float32, ctx=mx.gpu(0)))
result_after = net.forward(mx.nd.random.uniform(shape=shape, dtype=np.float32, ctx=mx.gpu(0)))
logger.info("Inference run successfully")