示例#1
0
def init_pose_model(config, checkpoint=None, device='cuda:0'):
    """Initialize a pose model from config file.

    Args:
        config (str or :obj:`mmcv.Config`): Config file path or the config
            object.
        checkpoint (str, optional): Checkpoint path. If left as None, the model
            will not load any weights.

    Returns:
        nn.Module: The constructed detector.
    """
    if isinstance(config, str):
        config = mmcv.Config.fromfile(config)
    elif not isinstance(config, mmcv.Config):
        raise TypeError('config must be a filename or Config object, '
                        f'but got {type(config)}')
    config.model.pretrained = None
    model = build_posenet(config.model)
    if checkpoint is not None:
        # load model checkpoint
        load_checkpoint(model, checkpoint, map_location=device)
    # save the config in the model for convenience
    model.cfg = config
    model.to(device)
    model.eval()
    return model
示例#2
0
def main():
    args = parse_args()

    cfg = mmcv.Config.fromfile(args.config)
    # set cudnn_benchmark
    if cfg.get('cudnn_benchmark', False):
        torch.backends.cudnn.benchmark = True
    cfg.model.pretrained = None
    cfg.data.test.test_mode = True

    args.work_dir = osp.join('./work_dirs',
                             osp.splitext(osp.basename(args.config))[0])
    mmcv.mkdir_or_exist(osp.abspath(args.work_dir))

    # init distributed env first, since logger depends on the dist info.
    if args.launcher == 'none':
        distributed = False
    else:
        distributed = True
        init_dist(args.launcher, **cfg.dist_params)

    # build the dataloader
    # TODO: support multiple images per gpu (only minor changes are needed)
    dataset = build_dataset(cfg.data.test, dict(test_mode=True))
    data_loader = build_dataloader(dataset,
                                   samples_per_gpu=1,
                                   workers_per_gpu=cfg.data.workers_per_gpu,
                                   dist=distributed,
                                   shuffle=False)

    # build the model and load checkpoint
    model = build_posenet(cfg.model)
    fp16_cfg = cfg.get('fp16', None)
    if fp16_cfg is not None:
        wrap_fp16_model(model)
    _ = load_checkpoint(model, args.checkpoint, map_location='cpu')

    # for backward compatibility

    if not distributed:
        model = MMDataParallel(model, device_ids=[0])
        outputs = single_gpu_test(model, data_loader)
    else:
        model = MMDistributedDataParallel(
            model.cuda(),
            device_ids=[torch.cuda.current_device()],
            broadcast_buffers=False)
        outputs = multi_gpu_test(model, data_loader, args.tmpdir,
                                 args.gpu_collect)

    rank, _ = get_dist_info()
    eval_config = cfg.get('eval_config', {})
    eval_config = merge_configs(eval_config, dict(metrics=args.eval))

    if rank == 0:
        if args.out:
            print(f'\nwriting results to {args.out}')
            mmcv.dump(outputs, args.out)

        dataset.evaluate(outputs, args.work_dir, **eval_config)
示例#3
0
def test_config_build_detector():
    """Test that all detection models defined in the configs can be
    initialized."""
    from mmcv import Config
    from mmpose.models import build_posenet

    config_dpath = _get_config_directory()
    print(f'Found config_dpath = {config_dpath}')

    import glob
    config_fpaths = list(glob.glob(join(config_dpath, '**', '*.py')))
    config_fpaths = [p for p in config_fpaths if p.find('_base_') == -1]
    config_names = [relpath(p, config_dpath) for p in config_fpaths]

    print(f'Using {len(config_names)} config files')

    for config_fname in config_names:
        config_fpath = join(config_dpath, config_fname)
        config_mod = Config.fromfile(config_fpath)

        print(f'Building detector, config_fpath = {config_fpath}')

        # Remove pretrained keys to allow for testing in an offline environment
        if 'pretrained' in config_mod.model:
            config_mod.model['pretrained'] = None

        detector = build_posenet(config_mod.model)
        assert detector is not None

        optimizer = build_optimizer(detector, config_mod.optimizer)
        assert isinstance(optimizer, torch.optim.Optimizer)
示例#4
0
def main():

    args = parse_args()

    if len(args.shape) == 1:
        input_shape = (3, args.shape[0], args.shape[0])
    elif len(args.shape) == 2:
        input_shape = (3, ) + tuple(args.shape)
    else:
        raise ValueError('invalid input shape')

    cfg = Config.fromfile(args.config)
    model = build_posenet(cfg.model)
    model = model.cuda()
    model.eval()

    if hasattr(model, 'forward_dummy'):
        model.forward = model.forward_dummy
    else:
        raise NotImplementedError(
            'FLOPs counter is currently not currently supported with {}'.
            format(model.__class__.__name__))

    flops, params = get_model_complexity_info(model, input_shape)
    split_line = '=' * 30
    print(f'{split_line}\nInput shape: {input_shape}\n'
          f'Flops: {flops}\nParams: {params}\n{split_line}')
    print('!!!Please be cautious if you use the results in papers. '
          'You may need to check if all ops are supported and verify that the '
          'flops computation is correct.')
def test_interhand3d_forward():
    # model settings
    model_cfg = dict(type='Interhand3D',
                     pretrained='torchvision://resnet50',
                     backbone=dict(type='ResNet', depth=50),
                     keypoint_head=dict(
                         type='Interhand3DHead',
                         keypoint_head_cfg=dict(
                             in_channels=2048,
                             out_channels=21 * 64,
                             depth_size=64,
                             num_deconv_layers=3,
                             num_deconv_filters=(256, 256, 256),
                             num_deconv_kernels=(4, 4, 4),
                         ),
                         root_head_cfg=dict(
                             in_channels=2048,
                             heatmap_size=64,
                             hidden_dims=(512, ),
                         ),
                         hand_type_head_cfg=dict(
                             in_channels=2048,
                             num_labels=2,
                             hidden_dims=(512, ),
                         ),
                         loss_keypoint=dict(type='JointsMSELoss',
                                            use_target_weight=True),
                         loss_root_depth=dict(type='L1Loss'),
                         loss_hand_type=dict(type='BCELoss',
                                             use_target_weight=True),
                     ),
                     train_cfg={},
                     test_cfg=dict(flip_test=True, shift_heatmap=True))

    detector = build_posenet(model_cfg)
    detector.init_weights()

    input_shape = (2, 3, 256, 256)
    mm_inputs = _demo_mm_inputs(input_shape)

    imgs = mm_inputs.pop('imgs')
    target = mm_inputs.pop('target')
    target_weight = mm_inputs.pop('target_weight')
    img_metas = mm_inputs.pop('img_metas')

    # Test forward train
    losses = detector.forward(imgs,
                              target,
                              target_weight,
                              img_metas,
                              return_loss=True)
    assert isinstance(losses, dict)

    # Test forward test
    with torch.no_grad():
        _ = detector.forward(imgs, img_metas=img_metas, return_loss=False)
        _ = detector.forward_dummy(imgs)
示例#6
0
def main():
    args = parse_args()

    cfg = Config.fromfile(args.config)
    # set cudnn_benchmark
    if cfg.get('cudnn_benchmark', False):
        torch.backends.cudnn.benchmark = True

    # build the dataloader
    dataset = build_dataset(cfg.data.val)
    data_loader = build_dataloader(
        dataset,
        samples_per_gpu=1,
        workers_per_gpu=cfg.data.workers_per_gpu,
        dist=False,
        shuffle=False)

    # build the model and load checkpoint
    model = build_posenet(cfg.model)
    fp16_cfg = cfg.get('fp16', None)
    if fp16_cfg is not None:
        wrap_fp16_model(model)
    if args.fuse_conv_bn:
        model = fuse_conv_bn(model)
    model = MMDataParallel(model, device_ids=[0])

    # the first several iterations may be very slow so skip them
    num_warmup = 5
    pure_inf_time = 0

    # benchmark with total batch and take the average
    for i, data in enumerate(data_loader):

        torch.cuda.synchronize()
        start_time = time.perf_counter()
        with torch.no_grad():
            model(return_loss=False, **data)

        torch.cuda.synchronize()
        elapsed = time.perf_counter() - start_time

        if i >= num_warmup:
            pure_inf_time += elapsed
            if (i + 1) % args.log_interval == 0:
                its = (i + 1 - num_warmup) / pure_inf_time
                print(f'Done item [{i + 1:<3}],  {its:.2f} items / s')
    print(f'Overall average: {its:.2f} items / s')
    print(f'Total time: {pure_inf_time:.2f} s')
示例#7
0
def load_model(cfg, ckp_link):
    """
    Loads a model from given mmcv.Config file and the related weights from the checkpoint link.

    Arguments:
        cfg         mmcv.Config for the model
        ckp_link    link to download the model's weights from

    Returns:
        model       nn.Module
    """
    model = build_posenet(cfg.model)
    load_checkpoint(model, ckp_link, map_location='cpu')
    model = MMDataParallel(model, device_ids=[0]) # device id, just set first cuda GPU

    return model
示例#8
0
def load_model(cfg, ckp_link):
    """
    Loads a model from given mmcv.Config file and the related weights from the checkpoint link.

    Arguments:
        cfg         mmcv.Config for the model
        ckp_link    link to download the model's weights from

    Returns:
        model       nn.Module
    """
    model = build_posenet(cfg.model)
    load_checkpoint(model, ckp_link, map_location='cpu')
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    model.to(device)

    return model
def test_pose_lifter_forward():
    # Test forward train
    model_cfg = dict(type='PoseLifter',
                     pretrained=None,
                     backbone=dict(type='TCN', in_channels=2 * 17),
                     keypoint_head=dict(
                         type='TemporalRegressionHead',
                         in_channels=1024,
                         num_joints=16,
                         max_norm=1.0,
                         loss_keypoint=dict(type='MPJPELoss'),
                         test_cfg=dict(restore_global_position=True)),
                     train_cfg=dict(),
                     test_cfg=dict())

    cfg = mmcv.Config({'model': model_cfg})
    detector = build_posenet(cfg.model)

    detector.init_weights()

    inputs = _create_inputs(joint_num_in=17,
                            joint_channel_in=2,
                            joint_num_out=16,
                            joint_channel_out=3,
                            seq_len=27,
                            batch_size=8)

    losses = detector.forward(inputs['input'],
                              inputs['target'],
                              inputs['target_weight'],
                              inputs['metas'],
                              return_loss=True)

    assert isinstance(losses, dict)

    # Test forward test
    with torch.no_grad():
        _ = detector.forward(inputs['input'],
                             inputs['target'],
                             inputs['target_weight'],
                             inputs['metas'],
                             return_loss=False)
        _ = detector.forward_dummy(inputs['input'])
def main():

    args = parse_args()

    if len(args.shape) == 1:
        input_shape = (1, 3, args.shape[0], args.shape[0])
    elif len(args.shape) == 2:
        input_shape = (
            1,
            3,
        ) + tuple(args.shape)
    else:
        raise ValueError('invalid input shape')

    cfg = Config.fromfile(args.config)
    model = build_posenet(cfg.model)
    model.eval()

    if args.with_head and hasattr(model, 'forward_with_head'):
        model.forward = model.forward_with_head
    elif not args.with_head and hasattr(model, 'forward_without_head'):
        model.forward = model.forward_without_head
    else:
        raise NotImplementedError(
            'FLOPs counter is currently not currently supported with {}'.
            format(model.__class__.__name__))

    df = model_stats(model, input_shape)
    print(df)
    if args.out_file:
        df.to_html(args.out_file + '.html')
        df.to_csv(args.out_file + '.csv')

    # flops, params = get_model_complexity_info(model, input_shape)
    # split_line = '=' * 30
    # print('{0}\nInput shape: {1}\nFlops: {2}\nParams: {3}\n{0}'.format(
    #     split_line, input_shape, flops, params))
    print('!!!Please be cautious if you use the results in papers. '
          'You may need to check if all ops are supported and verify that the '
          'flops computation is correct.')
示例#11
0
文件: train.py 项目: zhangyu92/mmpose
def main():
    args = parse_args()
    cfg = Config.fromfile(args.config)
    if args.options is not None:
        cfg.merge_from_dict(args.options)
    # set cudnn_benchmark
    if cfg.get('cudnn_benchmark', False):
        torch.backends.cudnn.benchmark = True
    # work_dir is determined in this priority: CLI > segment in file > filename
    if args.work_dir is not None:
        # update configs according to CLI args if args.work_dir is not None
        cfg.work_dir = args.work_dir
    elif cfg.get('work_dir', None) is None:
        # use config filename as default work_dir if cfg.work_dir is None
        cfg.work_dir = osp.join('./work_dirs',
                                osp.splitext(osp.basename(args.config))[0])
    if args.resume_from is not None:
        cfg.resume_from = args.resume_from
    if args.gpu_ids is not None:
        cfg.gpu_ids = args.gpu_ids
    else:
        cfg.gpu_ids = range(1) if args.gpus is None else range(args.gpus)

    if args.autoscale_lr:
        # apply the linear scaling rule (https://arxiv.org/abs/1706.02677)
        cfg.optimizer['lr'] = cfg.optimizer['lr'] * len(cfg.gpu_ids) / 8

    # init distributed env first, since logger depends on the dist info.
    if args.launcher == 'none':
        distributed = False
    else:
        distributed = True
        init_dist(args.launcher, **cfg.dist_params)

    # create work_dir
    mmcv.mkdir_or_exist(osp.abspath(cfg.work_dir))
    # init the logger before other steps
    timestamp = time.strftime('%Y%m%d_%H%M%S', time.localtime())
    log_file = osp.join(cfg.work_dir, f'{timestamp}.log')
    logger = get_root_logger(log_file=log_file, log_level=cfg.log_level)

    # init the meta dict to record some important information such as
    # environment info and seed, which will be logged
    meta = dict()
    # log env info
    env_info_dict = collect_env()
    env_info = '\n'.join([(f'{k}: {v}') for k, v in env_info_dict.items()])
    dash_line = '-' * 60 + '\n'
    logger.info('Environment info:\n' + dash_line + env_info + '\n' +
                dash_line)
    meta['env_info'] = env_info

    # log some basic info
    logger.info(f'Distributed training: {distributed}')
    logger.info(f'Config:\n{cfg.pretty_text}')

    # set random seeds
    if args.seed is not None:
        logger.info(f'Set random seed to {args.seed}, '
                    f'deterministic: {args.deterministic}')
        set_random_seed(args.seed, deterministic=args.deterministic)
    cfg.seed = args.seed
    meta['seed'] = args.seed

    model = build_posenet(cfg.model)
    datasets = [build_dataset(cfg.data.train)]

    if len(cfg.workflow) == 2:
        val_dataset = copy.deepcopy(cfg.data.val)
        val_dataset.pipeline = cfg.data.train.pipeline
        datasets.append(build_dataset(val_dataset))

    if cfg.checkpoint_config is not None:
        # save mmpose version, config file content
        # checkpoints as meta data
        cfg.checkpoint_config.meta = dict(
            mmpose_version=__version__ + get_git_hash(digits=7),
            config=cfg.pretty_text,
        )
    train_model(
        model,
        datasets,
        cfg,
        distributed=distributed,
        validate=(not args.no_validate),
        timestamp=timestamp,
        meta=meta)
示例#12
0
def test_pose_lifter_forward():
    # Test forward train for supervised learning with pose model only
    model_cfg = dict(type='PoseLifter',
                     pretrained=None,
                     backbone=dict(type='TCN', in_channels=2 * 17),
                     keypoint_head=dict(
                         type='TemporalRegressionHead',
                         in_channels=1024,
                         num_joints=16,
                         max_norm=1.0,
                         loss_keypoint=dict(type='MPJPELoss'),
                         test_cfg=dict(restore_global_position=True)),
                     train_cfg=dict(),
                     test_cfg=dict())

    cfg = mmcv.Config({'model': model_cfg})
    detector = build_posenet(cfg.model)

    detector.init_weights()

    inputs = _create_inputs(joint_num_in=17,
                            joint_channel_in=2,
                            joint_num_out=16,
                            joint_channel_out=3,
                            seq_len=27,
                            batch_size=8)

    losses = detector.forward(inputs['input'],
                              inputs['target'],
                              inputs['target_weight'],
                              inputs['metas'],
                              return_loss=True)

    assert isinstance(losses, dict)

    # Test forward test for supervised learning with pose model only
    with torch.no_grad():
        _ = detector.forward(inputs['input'],
                             inputs['target'],
                             inputs['target_weight'],
                             inputs['metas'],
                             return_loss=False)
        _ = detector.forward_dummy(inputs['input'])

    # Test forward train for semi-supervised learning
    model_cfg = dict(
        type='PoseLifter',
        pretrained=None,
        backbone=dict(type='TCN', in_channels=2 * 17),
        keypoint_head=dict(type='TemporalRegressionHead',
                           in_channels=1024,
                           num_joints=17,
                           loss_keypoint=dict(type='MPJPELoss'),
                           test_cfg=dict(restore_global_position=True)),
        traj_backbone=dict(type='TCN', in_channels=2 * 17),
        traj_head=dict(type='TemporalRegressionHead',
                       in_channels=1024,
                       num_joints=1,
                       loss_keypoint=dict(type='MPJPELoss'),
                       is_trajectory=True),
        loss_semi=dict(type='SemiSupervisionLoss',
                       joint_parents=[
                           0, 0, 1, 2, 0, 4, 5, 0, 7, 8, 9, 8, 11, 12, 8, 14,
                           15
                       ]),
        train_cfg=dict(),
        test_cfg=dict())

    cfg = mmcv.Config({'model': model_cfg})
    detector = build_posenet(cfg.model)

    detector.init_weights()

    inputs = _create_inputs(joint_num_in=17,
                            joint_channel_in=2,
                            joint_num_out=17,
                            joint_channel_out=3,
                            seq_len=27,
                            batch_size=8,
                            semi=True)

    losses = detector.forward(**inputs, return_loss=True)

    assert isinstance(losses, dict)
    assert 'proj_loss' in losses

    # Test forward test for semi-supervised learning
    with torch.no_grad():
        _ = detector.forward(**inputs, return_loss=False)
        _ = detector.forward_dummy(inputs['input'])

    # Test forward train for supervised learning with pose model and trajectory
    # model sharing one backbone
    model_cfg = dict(type='PoseLifter',
                     pretrained=None,
                     backbone=dict(type='TCN', in_channels=2 * 17),
                     keypoint_head=dict(
                         type='TemporalRegressionHead',
                         in_channels=1024,
                         num_joints=17,
                         loss_keypoint=dict(type='MPJPELoss'),
                         test_cfg=dict(restore_global_position=True)),
                     traj_head=dict(type='TemporalRegressionHead',
                                    in_channels=1024,
                                    num_joints=1,
                                    loss_keypoint=dict(type='MPJPELoss'),
                                    is_trajectory=True),
                     train_cfg=dict(),
                     test_cfg=dict())

    cfg = mmcv.Config({'model': model_cfg})
    detector = build_posenet(cfg.model)

    detector.init_weights()

    inputs = _create_inputs(joint_num_in=17,
                            joint_channel_in=2,
                            joint_num_out=17,
                            joint_channel_out=3,
                            seq_len=27,
                            batch_size=8,
                            semi=True)

    losses = detector.forward(**inputs, return_loss=True)

    assert isinstance(losses, dict)
    assert 'traj_loss' in losses

    # Test forward test for semi-supervised learning with pose model and
    # trajectory model sharing one backbone
    with torch.no_grad():
        _ = detector.forward(**inputs, return_loss=False)
        _ = detector.forward_dummy(inputs['input'])
示例#13
0
                        type=int,
                        nargs='+',
                        default=[1, 3, 256, 192],
                        help='input size')
    args = parser.parse_args()
    return args


if __name__ == '__main__':
    args = parse_args()

    assert args.opset_version == 11, 'MMPose only supports opset 11 now'

    cfg = mmcv.Config.fromfile(args.config)
    # build the model
    model = build_posenet(cfg.model)
    model = _convert_batchnorm(model)

    # onnx.export does not support kwargs
    if hasattr(model, 'forward_dummy'):
        model.forward = model.forward_dummy
    else:
        raise NotImplementedError(
            'Please implement the forward method for exporting.')

    checkpoint = load_checkpoint(model, args.checkpoint, map_location='cpu')

    # conver model to onnx file
    pytorch2onnx(model,
                 args.shape,
                 opset_version=args.opset_version,
示例#14
0
def main():
    args = parse_args()

    cfg = Config.fromfile(args.config)

    if args.cfg_options is not None:
        cfg.merge_from_dict(args.cfg_options)

    # set cudnn_benchmark
    if cfg.get('cudnn_benchmark', False):
        torch.backends.cudnn.benchmark = True
    cfg.model.pretrained = None
    cfg.data.test.test_mode = True

    args.work_dir = osp.join('./work_dirs',
                             osp.splitext(osp.basename(args.config))[0])
    mmcv.mkdir_or_exist(osp.abspath(args.work_dir))

    # init distributed env first, since logger depends on the dist info.
    if args.launcher == 'none':
        distributed = False
    else:
        distributed = True
        init_dist(args.launcher, **cfg.dist_params)

    # build the dataloader
    dataset = build_dataset(cfg.data.test, dict(test_mode=True))
    dataloader_setting = dict(samples_per_gpu=1,
                              workers_per_gpu=cfg.data.get(
                                  'workers_per_gpu', 1),
                              dist=distributed,
                              shuffle=False,
                              drop_last=False)
    dataloader_setting = dict(dataloader_setting,
                              **cfg.data.get('test_dataloader', {}))
    data_loader = build_dataloader(dataset, **dataloader_setting)

    # print(data_loader)

    # build the model and load checkpoint
    model = build_posenet(cfg.model)
    fp16_cfg = cfg.get('fp16', None)
    if fp16_cfg is not None:
        wrap_fp16_model(model)
    load_checkpoint(model, args.checkpoint, map_location='cpu')

    if args.fuse_conv_bn:
        model = fuse_conv_bn(model)

    if not distributed:
        model = MMDataParallel(model, device_ids=[0])
        outputs = single_gpu_test(model, data_loader)
    else:
        model = MMDistributedDataParallel(
            model.cuda(),
            device_ids=[torch.cuda.current_device()],
            broadcast_buffers=False)
        outputs = multi_gpu_test(model, data_loader, args.tmpdir,
                                 args.gpu_collect)

    rank, _ = get_dist_info()
    eval_config = cfg.get('evaluation', {})
    eval_config = merge_configs(eval_config, dict(metric=args.eval))

    if rank == 0:
        if args.out:
            print(f'\nwriting results to {args.out}')
            mmcv.dump(outputs, args.out)

        results = dataset.evaluate(outputs, args.work_dir, **eval_config)
        for k, v in sorted(results.items()):
            print(f'{k}: {v}')
示例#15
0
文件: test.py 项目: open-mmlab/mmpose
def main():
    args = parse_args()

    cfg = Config.fromfile(args.config)

    if args.cfg_options is not None:
        cfg.merge_from_dict(args.cfg_options)

    # set multi-process settings
    setup_multi_processes(cfg)

    # set cudnn_benchmark
    if cfg.get('cudnn_benchmark', False):
        torch.backends.cudnn.benchmark = True
    cfg.model.pretrained = None
    cfg.data.test.test_mode = True

    # work_dir is determined in this priority: CLI > segment in file > filename
    if args.work_dir is not None:
        # update configs according to CLI args if args.work_dir is not None
        cfg.work_dir = args.work_dir
    elif cfg.get('work_dir', None) is None:
        # use config filename as default work_dir if cfg.work_dir is None
        cfg.work_dir = osp.join('./work_dirs',
                                osp.splitext(osp.basename(args.config))[0])

    mmcv.mkdir_or_exist(osp.abspath(cfg.work_dir))

    # init distributed env first, since logger depends on the dist info.
    if args.launcher == 'none':
        distributed = False
    else:
        distributed = True
        init_dist(args.launcher, **cfg.dist_params)

    # build the dataloader
    dataset = build_dataset(cfg.data.test, dict(test_mode=True))
    # step 1: give default values and override (if exist) from cfg.data
    loader_cfg = {
        **dict(seed=cfg.get('seed'), drop_last=False, dist=distributed),
        **({} if torch.__version__ != 'parrots' else dict(
               prefetch_num=2,
               pin_memory=False,
           )),
        **dict((k, cfg.data[k]) for k in [
                   'seed',
                   'prefetch_num',
                   'pin_memory',
                   'persistent_workers',
               ] if k in cfg.data)
    }
    # step2: cfg.data.test_dataloader has higher priority
    test_loader_cfg = {
        **loader_cfg,
        **dict(shuffle=False, drop_last=False),
        **dict(workers_per_gpu=cfg.data.get('workers_per_gpu', 1)),
        **dict(samples_per_gpu=cfg.data.get('samples_per_gpu', 1)),
        **cfg.data.get('test_dataloader', {})
    }
    data_loader = build_dataloader(dataset, **test_loader_cfg)

    # build the model and load checkpoint
    model = build_posenet(cfg.model)
    fp16_cfg = cfg.get('fp16', None)
    if fp16_cfg is not None:
        wrap_fp16_model(model)
    load_checkpoint(model, args.checkpoint, map_location='cpu')

    if args.fuse_conv_bn:
        model = fuse_conv_bn(model)

    if not distributed:
        model = MMDataParallel(model, device_ids=[args.gpu_id])
        outputs = single_gpu_test(model, data_loader)
    else:
        model = MMDistributedDataParallel(
            model.cuda(),
            device_ids=[torch.cuda.current_device()],
            broadcast_buffers=False)
        outputs = multi_gpu_test(model, data_loader, args.tmpdir,
                                 args.gpu_collect)

    rank, _ = get_dist_info()
    eval_config = cfg.get('evaluation', {})
    eval_config = merge_configs(eval_config, dict(metric=args.eval))

    if rank == 0:
        if args.out:
            print(f'\nwriting results to {args.out}')
            mmcv.dump(outputs, args.out)

        results = dataset.evaluate(outputs, cfg.work_dir, **eval_config)
        for k, v in sorted(results.items()):
            print(f'{k}: {v}')