def export_segmentation_model(model_name, backbone, dataset, model_path, save_root='./'): print('INFO') print('-' * 80) print('| Model Name: %s' % model_name) print('| Backbone: %s' % backbone) print('| Dataset: %s' % dataset) print('| Model Path: %s' % model_path) print('| Save Root: %s' % save_root) print() print('Exporting...') print('-' * 80) model = gcv.model_zoo.segbase.get_segmentation_model(model=model_name, dataset=dataset, backbone=backbone, aux=True) # crop_size=480) model.load_parameters(model_path) _, file_name = os.path.split(model_path) file_name, _ = os.path.splitext(file_name) os.makedirs(save_root, exist_ok=True) save_path = os.path.join(save_root, file_name) gutils.export_block(save_path, model, preprocess=False, layout='CHW') print('| Save Model in %s' % save_path)
def export_detection_model(model_name, model_path, model_classes, save_root='./'): print('INFO') print('-' * 80) print('| Model Name: %s' % model_name) print('| Model Path: %s' % model_path) print('| Model Classes: %s' % str(model_classes)) print('| Save Root: %s' % save_root) print() print('Exporting...') print('-' * 80) model = gcv.model_zoo.get_model(model_name, pretrained_base=True) if model_name.startswith('ssd'): model.reset_class(model_classes) model.load_parameters(model_path) _, file_name = os.path.split(model_path) file_name, _ = os.path.splitext(file_name) os.makedirs(save_root, exist_ok=True) save_path = os.path.join(save_root, file_name) gutils.export_block(save_path, model, preprocess=False, layout='CHW') print('| Save Model in %s' % save_path)
def saveTraining(self, network_name, epoch=0): # Export weights to .params file export_block(os.path.join(self.output_folder, network_name), self.net, epoch=epoch, preprocess=True, layout='HWC', ctx=self.ctx[0])
def get_weights(model_name): """ 下载预训练参数并保存到weights目录下,以gluoncv开头 :param model_name: :return: None """ finetune_net = get_model(model_name, pretrained=True) export_block('weights/gluoncv-'+ model_name, finetune_net, preprocess=None, layout='CHW')
def save_checkpoint(epoch, top1, best_acc): if opt.save_frequency and (epoch + 1) % opt.save_frequency == 0: fname = os.path.join( opt.prefix, '%s_%d_acc_%.4f.params' % (opt.model, epoch, top1)) #net.save_parameters(fname) logger.info('[Epoch %d] Saving checkpoint to %s with Accuracy: %.4f', epoch, fname, top1) #net.export("mobilenetv2-0.5") export_block('mobilenetv2-0.5-new', net, preprocess=True, ctx=mx.gpu(0)) if top1 > best_acc[0]: best_acc[0] = top1 fname = os.path.join(opt.prefix, '%s_best.params' % (opt.model)) # net.save_parameters(fname) # net.export("mobilenetv2-0.5") logger.info('[Epoch %d] Saving checkpoint to %s with Accuracy: %.4f', epoch, fname, top1)
def export_model_from_gluoncv(model_name, save_dir, data_shape=None): """ Export a pretrained model from gluoncv. Args: model_name: A pretrained model name. save_dir: Path of a directory to save the model. data_shape: data_shape of input tensor. Format: (height, width, channel). Returns: None """ from gluoncv import model_zoo from gluoncv.utils import export_block net = model_zoo.get_model(model_name, pretrained=True) prefix = os.path.join(save_dir, model_name) export_block(prefix, net, data_shape=data_shape, \ preprocess=False, layout='CHW')
def zoo_import(name, head=''): """Download from Gluoncv Zoo""" net = gz.get_model(name, pretrained=True) export_block(head + name, net, preprocess=True)
def train(net, train_data, val_data, eval_metric, ctx, args): """Training pipeline""" net.collect_params().reset_ctx(ctx) if args.no_wd: for k, v in net.collect_params('.*beta|.*gamma|.*bias').items(): v.wd_mult = 0.0 if args.label_smooth: net._target_generator._label_smooth = True if args.lr_decay_period > 0: lr_decay_epoch = list( range(args.lr_decay_period, args.epochs, args.lr_decay_period)) else: lr_decay_epoch = [int(i) for i in args.lr_decay_epoch.split(',')] lr_decay_epoch = [e - args.warmup_epochs for e in lr_decay_epoch] num_batches = args.num_samples // args.batch_size lr_scheduler = LRSequential([ LRScheduler('linear', base_lr=0, target_lr=args.lr, nepochs=args.warmup_epochs, iters_per_epoch=num_batches), LRScheduler(args.lr_mode, base_lr=args.lr, nepochs=args.epochs - args.warmup_epochs, iters_per_epoch=num_batches, step_epoch=lr_decay_epoch, step_factor=args.lr_decay, power=2), ]) trainer = gluon.Trainer(net.collect_params(), 'sgd', { 'wd': args.wd, 'momentum': args.momentum, 'lr_scheduler': lr_scheduler }, kvstore='local') # targets sigmoid_ce = gluon.loss.SigmoidBinaryCrossEntropyLoss(from_sigmoid=False) l1_loss = gluon.loss.L1Loss() # metrics obj_metrics = mx.metric.Loss('ObjLoss') center_metrics = mx.metric.Loss('BoxCenterLoss') scale_metrics = mx.metric.Loss('BoxScaleLoss') cls_metrics = mx.metric.Loss('ClassLoss') print('Start training from [Epoch {}]'.format(args.start_epoch)) best_map = [0] for epoch in range(args.start_epoch, args.epochs): if args.mixup: # TODO(zhreshold): more elegant way to control mixup during runtime try: train_data._dataset.set_mixup(np.random.beta, 1.5, 1.5) except AttributeError: train_data._dataset._data.set_mixup(np.random.beta, 1.5, 1.5) if epoch >= args.epochs - args.no_mixup_epochs: try: train_data._dataset.set_mixup(None) except AttributeError: train_data._dataset._data.set_mixup(None) tic = time.time() btic = time.time() mx.nd.waitall() net.hybridize() for i, batch in enumerate(train_data): batch_size = batch[0].shape[0] data = gluon.utils.split_and_load(batch[0], ctx_list=ctx, batch_axis=0) # objectness, center_targets, scale_targets, weights, class_targets fixed_targets = [ gluon.utils.split_and_load(batch[it], ctx_list=ctx, batch_axis=0) for it in range(1, 6) ] gt_boxes = gluon.utils.split_and_load(batch[6], ctx_list=ctx, batch_axis=0) sum_losses = [] obj_losses = [] center_losses = [] scale_losses = [] cls_losses = [] with autograd.record(): for ix, x in enumerate(data): obj_loss, center_loss, scale_loss, cls_loss = net( x, gt_boxes[ix], *[ft[ix] for ft in fixed_targets]) sum_losses.append(obj_loss + center_loss + scale_loss + cls_loss) obj_losses.append(obj_loss) center_losses.append(center_loss) scale_losses.append(scale_loss) cls_losses.append(cls_loss) autograd.backward(sum_losses) trainer.step(batch_size) obj_metrics.update(0, obj_losses) center_metrics.update(0, center_losses) scale_metrics.update(0, scale_losses) cls_metrics.update(0, cls_losses) if args.log_interval and not (i + 1) % args.log_interval: name1, loss1 = obj_metrics.get() name2, loss2 = center_metrics.get() name3, loss3 = scale_metrics.get() name4, loss4 = cls_metrics.get() print( '[Epoch {}][Batch {}], LR: {:.2E}, Speed: {:.3f} samples/sec, {}={:.3f}, {}={:.3f}, {}={:.3f}, {}={:.3f}' .format(epoch, i, trainer.learning_rate, batch_size / (time.time() - btic), name1, loss1, name2, loss2, name3, loss3, name4, loss4)) btic = time.time() name1, loss1 = obj_metrics.get() name2, loss2 = center_metrics.get() name3, loss3 = scale_metrics.get() name4, loss4 = cls_metrics.get() print( '[Epoch {}] Training cost: {:.3f}, {}={:.3f}, {}={:.3f}, {}={:.3f}, {}={:.3f}' .format(epoch, (time.time() - tic), name1, loss1, name2, loss2, name3, loss3, name4, loss4)) #if not (epoch + 1) % args.val_interval: # consider reduce the frequency of validation to save time #map_name, mean_ap = validate(net, val_data, ctx, eval_metric) #val_msg = '\n'.join(['{}={}'.format(k, v) for k, v in zip(map_name, mean_ap)]) #print('[Epoch {}] Validation: \n{}'.format(epoch, val_msg)) #current_map = float(mean_ap[-1]) #else: # current_map = 0. current_map = 0. save_params(net, best_map, current_map, epoch, args.save_interval, args.save_prefix) export_block(os.path.join(args.model_dir, 'yolo3_darknet53_coco'), net) print('Yeahhhhhh')
It is awesome if you are enjoy using GluonCV in Python for training and testing. At some point, you might ask: "Is it possible to deploy the existing models to somewhere out of Python environments?" The answer is "Absolutely!", and it's super easy actually. This article will show you how to export networks/models to be used somewhere other than Python. """ import gluoncv as gcv from gluoncv.utils import export_block ################################################################################ # First of all, we need a network to play with, a pre-trained one is perfect net = gcv.model_zoo.get_model('resnet18_v1', pretrained=True) export_block('resnet18_v1', net, preprocess=True, layout='HWC') print('Done.') ################################################################################ # .. hint:: # # Use ``preprocess=True`` will add a default preprocess layer above the network, # which will subtract mean [123.675, 116.28, 103.53], divide # std [58.395, 57.12, 57.375], and convert original image (B, H, W, C and range [0, 255]) to # tensor (B, C, H, W) as network input. This is the default preprocess behavior of all GluonCV # pre-trained models. With this preprocess head, you can use raw RGB image in C++ without # explicitly applying these operations. ################################################################################ # The above code generates two files: xxxx.json and xxxx.params import glob
def main(): opt = parse_args() filehandler = logging.FileHandler(opt.logging_file) streamhandler = logging.StreamHandler() logger = logging.getLogger('') logger.setLevel(logging.INFO) logger.addHandler(filehandler) logger.addHandler(streamhandler) logger.info(opt) batch_size = opt.batch_size classes = opt.classes num_training_samples = opt.num_training_samples ## 1281167 num_gpus = opt.num_gpus batch_size *= max(1, num_gpus) context = [mx.gpu(i) for i in range(num_gpus)] if num_gpus > 0 else [mx.cpu()] num_workers = opt.num_workers lr_decay = opt.lr_decay lr_decay_period = opt.lr_decay_period if opt.lr_decay_period > 0: lr_decay_epoch = list( range(lr_decay_period, opt.num_epochs, lr_decay_period)) else: lr_decay_epoch = [int(i) for i in opt.lr_decay_epoch.split(',')] lr_decay_epoch = [e - opt.warmup_epochs for e in lr_decay_epoch] num_batches = num_training_samples // batch_size lr_scheduler = LRSequential([ LRScheduler('linear', base_lr=0, target_lr=opt.lr, nepochs=opt.warmup_epochs, iters_per_epoch=num_batches), # warm up lr LRScheduler(opt.lr_mode, base_lr=opt.lr, target_lr=0, nepochs=opt.num_epochs - opt.warmup_epochs, iters_per_epoch=num_batches, step_epoch=lr_decay_epoch, step_factor=lr_decay, power=2) ]) model_name = opt.model # kwargs = {'ctx': context, 'pretrained': opt.use_pretrained, 'classes': classes} kwargs = {'ctx': context, 'pretrained': False, 'classes': 2} if opt.use_gn: from gluoncv.nn import GroupNorm kwargs['norm_layer'] = GroupNorm if model_name.startswith('vgg'): kwargs['batch_norm'] = opt.batch_norm elif model_name.startswith('resnext'): kwargs['use_se'] = opt.use_se if opt.last_gamma: kwargs['last_gamma'] = True #optimizer = 'nag' optimizer = 'sgd' optimizer_params = { 'wd': opt.wd, 'momentum': opt.momentum, 'lr_scheduler': lr_scheduler } if opt.dtype != 'float32': optimizer_params['multi_precision'] = True net = get_model(model_name, **kwargs) net.cast(opt.dtype) if opt.resume_params is not '': net.load_parameters(opt.resume_params, ctx=context) #if opt.resume_params is '': # net.initialize(mx.init.MSRAPrelu(), ctx = context) pretrained_net = get_model(model_name, pretrained=True, classes=1000, ctx=context) #pretrained_net = model_zoo.vision.resnet50_v2(pretrained=True, ctx=context) pretrained_net.cast(opt.dtype) net.features = pretrained_net.features net.output.initialize(init.Xavier(), ctx=context) # output中的模型参数将在迭代中使用10倍大的学习率 net.output.collect_params().setattr('lr_mult', 10) #net.features.collect_params().setattr('grad_req', 'null') # it don't update feature network weight # teacher model for distillation training if opt.teacher is not None and opt.hard_weight < 1.0: teacher_name = opt.teacher teacher = get_model(teacher_name, pretrained=True, classes=classes, ctx=context) teacher.cast(opt.dtype) distillation = True else: distillation = False # Two functions for reading data from record file or raw images def get_data_rec(rec_train, rec_train_idx, rec_val, rec_val_idx, batch_size, num_workers): rec_train = os.path.expanduser(rec_train) rec_train_idx = os.path.expanduser(rec_train_idx) rec_val = os.path.expanduser(rec_val) rec_val_idx = os.path.expanduser(rec_val_idx) jitter_param = 0.4 lighting_param = 0.1 input_size = opt.input_size crop_ratio = opt.crop_ratio if opt.crop_ratio > 0 else 0.875 resize = int(math.ceil(input_size / crop_ratio)) mean_rgb = [123.68, 116.779, 103.939] std_rgb = [58.393, 57.12, 57.375] def batch_fn(batch, ctx): data = gluon.utils.split_and_load(batch.data[0], ctx_list=ctx, batch_axis=0) label = gluon.utils.split_and_load(batch.label[0], ctx_list=ctx, batch_axis=0) return data, label train_data = mx.io.ImageRecordIter( path_imgrec=rec_train, path_imgidx=rec_train_idx, preprocess_threads=num_workers, shuffle=True, batch_size=batch_size, data_shape=(3, input_size, input_size), mean_r=mean_rgb[0], mean_g=mean_rgb[1], mean_b=mean_rgb[2], std_r=std_rgb[0], std_g=std_rgb[1], std_b=std_rgb[2], rand_mirror=True, random_resized_crop=True, max_aspect_ratio=4. / 3., min_aspect_ratio=3. / 4., max_random_area=1, min_random_area=0.08, brightness=jitter_param, saturation=jitter_param, contrast=jitter_param, pca_noise=lighting_param, ) val_data = mx.io.ImageRecordIter( path_imgrec=rec_val, path_imgidx=rec_val_idx, preprocess_threads=num_workers, shuffle=False, batch_size=batch_size, resize=resize, data_shape=(3, input_size, input_size), mean_r=mean_rgb[0], mean_g=mean_rgb[1], mean_b=mean_rgb[2], std_r=std_rgb[0], std_g=std_rgb[1], std_b=std_rgb[2], ) return train_data, val_data, batch_fn def get_data_loader(data_dir, batch_size, num_workers): normalize = transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) jitter_param = 0.4 lighting_param = 0.1 input_size = opt.input_size crop_ratio = opt.crop_ratio if opt.crop_ratio > 0 else 0.875 resize = int(math.ceil(input_size / crop_ratio)) def batch_fn(batch, ctx): data = gluon.utils.split_and_load(batch[0], ctx_list=ctx, batch_axis=0) label = gluon.utils.split_and_load(batch[1], ctx_list=ctx, batch_axis=0) return data, label transform_train = transforms.Compose([ transforms.RandomResizedCrop(input_size), transforms.RandomFlipLeftRight(), transforms.RandomColorJitter(brightness=jitter_param, contrast=jitter_param, saturation=jitter_param), transforms.RandomLighting(lighting_param), transforms.ToTensor(), normalize ]) transform_test = transforms.Compose([ transforms.Resize(resize, keep_ratio=True), transforms.CenterCrop(input_size), transforms.ToTensor(), normalize ]) train_data = gluon.data.DataLoader(imagenet.classification.ImageNet( data_dir, train=True).transform_first(transform_train), batch_size=batch_size, shuffle=True, last_batch='discard', num_workers=num_workers) val_data = gluon.data.DataLoader(imagenet.classification.ImageNet( data_dir, train=False).transform_first(transform_test), batch_size=batch_size, shuffle=False, num_workers=num_workers) return train_data, val_data, batch_fn if opt.use_rec: train_data, val_data, batch_fn = get_data_rec(opt.rec_train, opt.rec_train_idx, opt.rec_val, opt.rec_val_idx, batch_size, num_workers) else: train_data, val_data, batch_fn = get_data_loader( opt.data_dir, batch_size, num_workers) if opt.mixup: train_metric = mx.metric.RMSE() else: train_metric = mx.metric.Accuracy() acc_top1 = mx.metric.Accuracy() save_frequency = opt.save_frequency if opt.save_dir and save_frequency: save_dir = opt.save_dir makedirs(save_dir) else: save_dir = '' save_frequency = 0 def mixup_transform(label, classes, lam=1, eta=0.0): if isinstance(label, nd.NDArray): label = [label] res = [] for l in label: y1 = l.one_hot(classes, on_value=1 - eta + eta / classes, off_value=eta / classes) y2 = l[::-1].one_hot(classes, on_value=1 - eta + eta / classes, off_value=eta / classes) res.append(lam * y1 + (1 - lam) * y2) return res def smooth(label, classes, eta=0.1): if isinstance(label, nd.NDArray): label = [label] smoothed = [] for l in label: res = l.one_hot(classes, on_value=1 - eta + eta / classes, off_value=eta / classes) smoothed.append(res) return smoothed def test(ctx, val_data): if opt.use_rec: val_data.reset() acc_top1.reset() for i, batch in enumerate(val_data): data, label = batch_fn(batch, ctx) outputs = [net(X.astype(opt.dtype, copy=False)) for X in data] acc_top1.update(label, outputs) _, top1 = acc_top1.get() return 1 - top1 def train(ctx): if isinstance(ctx, mx.Context): ctx = [ctx] #if opt.resume_params is '': # net.initialize(mx.init.MSRAPrelu(), ctx=ctx) if opt.no_wd: for k, v in net.collect_params('.*beta|.*gamma|.*bias').items(): v.wd_mult = 0.0 trainer = gluon.Trainer(net.collect_params(), optimizer, optimizer_params) if opt.resume_states is not '': trainer.load_states(opt.resume_states) if opt.label_smoothing or opt.mixup: sparse_label_loss = False else: sparse_label_loss = True if distillation: L = gcv.loss.DistillationSoftmaxCrossEntropyLoss( temperature=opt.temperature, hard_weight=opt.hard_weight, sparse_label=sparse_label_loss) else: L = gluon.loss.SoftmaxCrossEntropyLoss( sparse_label=sparse_label_loss) best_val_score = 1 for epoch in range(opt.resume_epoch, opt.num_epochs): tic = time.time() if opt.use_rec: train_data.reset() train_metric.reset() btic = time.time() for i, batch in enumerate(train_data): data, label = batch_fn(batch, ctx) if opt.mixup: lam = np.random.beta(opt.mixup_alpha, opt.mixup_alpha) if epoch >= opt.num_epochs - opt.mixup_off_epoch: lam = 1 data = [lam * X + (1 - lam) * X[::-1] for X in data] if opt.label_smoothing: eta = 0.1 else: eta = 0.0 label = mixup_transform(label, classes, lam, eta) elif opt.label_smoothing: hard_label = label label = smooth(label, classes) if distillation: teacher_prob = [nd.softmax(teacher(X.astype(opt.dtype, copy=False)) / opt.temperature) \ for X in data] with ag.record(): outputs = [ net(X.astype(opt.dtype, copy=False)) for X in data ] if distillation: loss = [ L(yhat.astype('float32', copy=False), y.astype('float32', copy=False), p.astype('float32', copy=False)) for yhat, y, p in zip(outputs, label, teacher_prob) ] else: loss = [ L(yhat, y.astype(opt.dtype, copy=False)) for yhat, y in zip(outputs, label) ] for l in loss: l.backward() trainer.step(batch_size) if opt.mixup: output_softmax = [nd.SoftmaxActivation(out.astype('float32', copy=False)) \ for out in outputs] train_metric.update(label, output_softmax) else: if opt.label_smoothing: train_metric.update(hard_label, outputs) else: train_metric.update(label, outputs) if opt.log_interval and not (i + 1) % opt.log_interval: train_metric_name, train_metric_score = train_metric.get() logger.info( 'Epoch[%d] Batch [%d]\tSpeed: %f samples/sec\t%s=%f\tlr=%f' % (epoch, i, batch_size * opt.log_interval / (time.time() - btic), train_metric_name, train_metric_score, trainer.learning_rate)) btic = time.time() train_metric_name, train_metric_score = train_metric.get() throughput = int(batch_size * i / (time.time() - tic)) err_top1_val = test(ctx, val_data) logger.info('[Epoch %d] training: %s=%f' % (epoch, train_metric_name, train_metric_score)) logger.info('[Epoch %d] speed: %d samples/sec\ttime cost: %f' % (epoch, throughput, time.time() - tic)) logger.info('[Epoch %d] validation: err-top1=%f top1=%f' % (epoch, err_top1_val, 1 - err_top1_val)) if err_top1_val < best_val_score: best_val_score = err_top1_val net.save_parameters( '%s/%.4f-myperson-%s-%d-best.params' % (save_dir, 1 - best_val_score, model_name, epoch)) trainer.save_states( '%s/%.4f-myperson-%s-%d-best.states' % (save_dir, 1 - best_val_score, model_name, epoch)) if save_frequency and save_dir and (epoch + 1) % save_frequency == 0: net.save_parameters('%s/myperson-%s-%d.params' % (save_dir, model_name, epoch)) trainer.save_states('%s/myperson-%s-%d.states' % (save_dir, model_name, epoch)) if save_frequency and save_dir: net.save_parameters('%s/myperson-%s-%d.params' % (save_dir, model_name, opt.num_epochs - 1)) trainer.save_states('%s/myperson-%s-%d.states' % (save_dir, model_name, opt.num_epochs - 1)) if opt.imagenet_mode == 0: if opt.mode == 'hybrid': net.hybridize(static_alloc=True, static_shape=True) if distillation: teacher.hybridize(static_alloc=True, static_shape=True) train(context) elif opt.imagenet_mode == 1: err_top1_val = test(context, val_data) print('validation: err-top1=%f top1=%f' % (err_top1_val, 1 - err_top1_val)) else: if os.path.exists(opt.save_mxnet_dir) == False: os.makedirs(opt.save_mxnet_dir) param_save_path = '%s/gluoncv-%s' % (opt.save_mxnet_dir, model_name) export_block(param_save_path, net, preprocess=None, layout='CHW')
import argparse import os from gluoncv.model_zoo import get_model from gluoncv.utils import export_block parser = argparse.ArgumentParser( description='Download GluonCV pre-trained model without pre-processing') parser.add_argument('--model', type=str, required=True, help='name of the model to use') parser.add_argument('--save-file', type=str, default='', help='path to save the hybrid model') opt = parser.parse_args() model_name = opt.model model_save_path = opt.save_file file_path = os.path.join(model_save_path, model_name) net = get_model(model_name, pretrained=True) export_block(file_path, net, preprocess=False, layout='CHW')
net.initialize() async_net.initialize() # training data train_dataset, val_dataset, eval_metric = get_dataset(args.dataset, args) # print(train_dataset[100][0]) for i in range(len(train_dataset)): # print(len(list(tmp))) if train_dataset[i][1].shape[0] == 0: print("no val " + str(i)) for i in range(len(val_dataset)): # print(len(list(tmp))) if val_dataset[i][1].shape[0] == 0: print("no val " + str(i)) train_data, val_data = get_dataloader(async_net, train_dataset, val_dataset, args.data_shape, args.batch_size, args.num_workers, args) # e = enumerate(train_data) # training from gluoncv.utils import export_block export_block('./yolov3.json', net, preprocess=True, layout='HWC') print('Done.') # train(net, train_data, val_data, eval_metric, ctx, args)
import gluoncv as gcv from gluoncv.utils import export_block net = gcv.model_zoo.get_model('yolo3_darknet53_coco', pretrained=True) export_block('yolo3_darknet53_coco', net)