Esempio n. 1
0
    def runTest(self):
        with fluid.unique_name.guard():
            net = MulNet()
            ratios = {}
            ratios['conv2d_0.w_0'] = 0.5
            pruners = []
            pruner = L1NormFilterPruner(net, [2, 6, 3, 3], skip_leaves=False)
            pruners.append(pruner)
            pruner = FPGMFilterPruner(net, [2, 6, 3, 3], skip_leaves=False)
            pruners.append(pruner)
            pruner = L2NormFilterPruner(net, [2, 6, 3, 3], skip_leaves=False)
            pruners.append(pruner)

            shapes = {
                'b': [3, 18],
                'conv2d_0.w_0': [3, 6, 1, 1],
                'conv2d_0.b_0': [3]
            }
            for pruner in pruners:
                plan = pruner.prune_vars(ratios, 0)
                for param in net.parameters():
                    if param.name not in shapes:
                        shapes[param.name] = param.shape

                    self.assertTrue(shapes[param.name] == param.shape)
                pruner.restore()
Esempio n. 2
0
    def runTest(self):
        with fluid.unique_name.guard():
            net = paddle.vision.models.LeNet()
            optimizer = paddle.optimizer.Adam(learning_rate=0.001,
                                              parameters=net.parameters())
            inputs = [Input([None, 1, 28, 28], 'float32', name='image')]
            labels = [Input([None, 1], 'int64', name='label')]
            model = paddle.Model(net, inputs, labels)
            model.prepare(optimizer, paddle.nn.CrossEntropyLoss(),
                          paddle.metric.Accuracy(topk=(1, 5)))
            model.fit(self.train_dataset, epochs=1, batch_size=128, verbose=1)
            pruners = []
            pruner = L1NormFilterPruner(net, [1, 1, 28, 28], opt=optimizer)
            pruners.append(pruner)
            pruner = FPGMFilterPruner(net, [1, 1, 28, 28], opt=optimizer)
            pruners.append(pruner)
            pruner = L2NormFilterPruner(net, [1, 1, 28, 28], opt=optimizer)
            pruners.append(pruner)

            def eval_fn():
                result = model.evaluate(self.val_dataset,
                                        batch_size=128,
                                        verbose=1)
                return result['acc_top1']

            sen_file = "_".join(["./dygraph_sen_", str(time.time())])
            for pruner in pruners:
                sen = pruner.sensitive(eval_func=eval_fn,
                                       sen_file=sen_file,
                                       target_vars=self._param_names)
                model.fit(self.train_dataset,
                          epochs=1,
                          batch_size=128,
                          verbose=1)
                base_acc = eval_fn()
                plan = pruner.sensitive_prune(0.01)
                pruner.restore()
                restore_acc = eval_fn()
                self.assertTrue(restore_acc == base_acc)

                plan = pruner.sensitive_prune(0.01, align=4)
                for param in net.parameters():
                    if param.name in self._param_names:
                        print(f"name: {param.name}; shape: {param.shape}")
                        self.assertTrue(param.shape[0] % 4 == 0)
                pruner.restore()
Esempio n. 3
0
    def runTest(self):
        with fluid.unique_name.guard():
            net = paddle.vision.models.mobilenet_v1()
            ratios = {}
            for param in net.parameters():
                if len(param.shape) == 4:
                    ratios[param.name] = 0.5
            pruners = []
            pruner = L1NormFilterPruner(net, [1, 3, 128, 128])
            pruners.append(pruner)
            pruner = FPGMFilterPruner(net, [1, 3, 128, 128])
            pruners.append(pruner)
            pruner = L2NormFilterPruner(net, [1, 3, 128, 128])
            pruners.append(pruner)

            shapes = {}
            for pruner in pruners:
                plan = pruner.prune_vars(ratios, 0)
                for param in net.parameters():
                    if param.name not in shapes:
                        shapes[param.name] = param.shape
                    assert (shapes[param.name] == param.shape)
                pruner.restore()
Esempio n. 4
0
def main(config, device, logger, vdl_writer):
    # init dist environment
    if config['Global']['distributed']:
        dist.init_parallel_env()

    global_config = config['Global']

    # build dataloader
    train_dataloader = build_dataloader(config, 'Train', device, logger)
    if config['Eval']:
        valid_dataloader = build_dataloader(config, 'Eval', device, logger)
    else:
        valid_dataloader = None

    # build post process
    post_process_class = build_post_process(config['PostProcess'],
                                            global_config)

    # build model
    # for rec algorithm
    if hasattr(post_process_class, 'character'):
        char_num = len(getattr(post_process_class, 'character'))
        config['Architecture']["Head"]['out_channels'] = char_num
    model = build_model(config['Architecture'])

    flops = paddle.flops(model, [1, 3, 640, 640])
    logger.info(f"FLOPs before pruning: {flops}")

    from paddleslim.dygraph import FPGMFilterPruner
    model.train()
    pruner = FPGMFilterPruner(model, [1, 3, 640, 640])

    # build loss
    loss_class = build_loss(config['Loss'])

    # build optim
    optimizer, lr_scheduler = build_optimizer(
        config['Optimizer'],
        epochs=config['Global']['epoch_num'],
        step_each_epoch=len(train_dataloader),
        parameters=model.parameters())

    # build metric
    eval_class = build_metric(config['Metric'])
    # load pretrain model
    pre_best_model_dict = init_model(config, model, logger, optimizer)

    logger.info(
        'train dataloader has {} iters, valid dataloader has {} iters'.format(
            len(train_dataloader), len(valid_dataloader)))
    # build metric
    eval_class = build_metric(config['Metric'])

    logger.info(
        'train dataloader has {} iters, valid dataloader has {} iters'.format(
            len(train_dataloader), len(valid_dataloader)))

    def eval_fn():
        metric = program.eval(model, valid_dataloader, post_process_class,
                              eval_class)
        logger.info(f"metric['hmean']: {metric['hmean']}")
        return metric['hmean']

    params_sensitive = pruner.sensitive(eval_func=eval_fn,
                                        sen_file="./sen.pickle",
                                        skip_vars=[
                                            "conv2d_57.w_0",
                                            "conv2d_transpose_2.w_0",
                                            "conv2d_transpose_3.w_0"
                                        ])

    logger.info(
        "The sensitivity analysis results of model parameters saved in sen.pickle"
    )
    # calculate pruned params's ratio
    params_sensitive = pruner._get_ratios_by_loss(params_sensitive, loss=0.02)
    for key in params_sensitive.keys():
        logger.info(f"{key}, {params_sensitive[key]}")

    plan = pruner.prune_vars(params_sensitive, [0])
    for param in model.parameters():
        if ("weights" in param.name
                and "conv" in param.name) or ("w_0" in param.name
                                              and "conv2d" in param.name):
            logger.info(f"{param.name}: {param.shape}")

    flops = paddle.flops(model, [1, 3, 640, 640])
    logger.info(f"FLOPs after pruning: {flops}")

    # start train

    program.train(config, train_dataloader, valid_dataloader, device, model,
                  loss_class, optimizer, lr_scheduler, post_process_class,
                  eval_class, pre_best_model_dict, logger, vdl_writer)
Esempio n. 5
0
def main(config, device, logger, vdl_writer):

    global_config = config['Global']

    # build dataloader
    valid_dataloader = build_dataloader(config, 'Eval', device, logger)

    # build post process
    post_process_class = build_post_process(config['PostProcess'],
                                            global_config)

    # build model
    # for rec algorithm
    if hasattr(post_process_class, 'character'):
        char_num = len(getattr(post_process_class, 'character'))
        config['Architecture']["Head"]['out_channels'] = char_num
    model = build_model(config['Architecture'])

    flops = paddle.flops(model, [1, 3, 640, 640])
    logger.info(f"FLOPs before pruning: {flops}")

    from paddleslim.dygraph import FPGMFilterPruner
    model.train()
    pruner = FPGMFilterPruner(model, [1, 3, 640, 640])

    # build metric
    eval_class = build_metric(config['Metric'])

    def eval_fn():
        metric = program.eval(model, valid_dataloader, post_process_class,
                              eval_class)
        logger.info(f"metric['hmean']: {metric['hmean']}")
        return metric['hmean']

    params_sensitive = pruner.sensitive(eval_func=eval_fn,
                                        sen_file="./sen.pickle",
                                        skip_vars=[
                                            "conv2d_57.w_0",
                                            "conv2d_transpose_2.w_0",
                                            "conv2d_transpose_3.w_0"
                                        ])

    logger.info(
        "The sensitivity analysis results of model parameters saved in sen.pickle"
    )
    # calculate pruned params's ratio
    params_sensitive = pruner._get_ratios_by_loss(params_sensitive, loss=0.02)
    for key in params_sensitive.keys():
        logger.info(f"{key}, {params_sensitive[key]}")

    plan = pruner.prune_vars(params_sensitive, [0])

    flops = paddle.flops(model, [1, 3, 640, 640])
    logger.info(f"FLOPs after pruning: {flops}")

    # load pretrain model
    pre_best_model_dict = init_model(config, model, logger, None)
    metric = program.eval(model, valid_dataloader, post_process_class,
                          eval_class)
    logger.info(f"metric['hmean']: {metric['hmean']}")

    # start export model
    from paddle.jit import to_static

    infer_shape = [3, -1, -1]
    if config['Architecture']['model_type'] == "rec":
        infer_shape = [3, 32, -1]  # for rec model, H must be 32

        if 'Transform' in config['Architecture'] and config['Architecture'][
                'Transform'] is not None and config['Architecture'][
                    'Transform']['name'] == 'TPS':
            logger.info(
                'When there is tps in the network, variable length input is not supported, and the input size needs to be the same as during training'
            )
            infer_shape[-1] = 100
    model = to_static(model,
                      input_spec=[
                          paddle.static.InputSpec(shape=[None] + infer_shape,
                                                  dtype='float32')
                      ])

    save_path = '{}/inference'.format(config['Global']['save_inference_dir'])
    paddle.jit.save(model, save_path)
    logger.info('inference model is saved to {}'.format(save_path))
Esempio n. 6
0
def main(config, device, logger, vdl_writer):
    # init dist environment
    if config['Global']['distributed']:
        dist.init_parallel_env()

    global_config = config['Global']

    # build dataloader
    train_dataloader = build_dataloader(config, 'Train', device, logger)
    if config['Eval']:
        valid_dataloader = build_dataloader(config, 'Eval', device, logger)
    else:
        valid_dataloader = None

    # build post process
    post_process_class = build_post_process(config['PostProcess'],
                                            global_config)

    # build model
    # for rec algorithm
    if hasattr(post_process_class, 'character'):
        char_num = len(getattr(post_process_class, 'character'))
        config['Architecture']["Head"]['out_channels'] = char_num
    model = build_model(config['Architecture'])
    if config['Architecture']['model_type'] == 'det':
        input_shape = [1, 3, 640, 640]
    elif config['Architecture']['model_type'] == 'rec':
        input_shape = [1, 3, 32, 320]
    flops = paddle.flops(model, input_shape)

    logger.info("FLOPs before pruning: {}".format(flops))

    from paddleslim.dygraph import FPGMFilterPruner
    model.train()

    pruner = FPGMFilterPruner(model, input_shape)

    # build loss
    loss_class = build_loss(config['Loss'])

    # build optim
    optimizer, lr_scheduler = build_optimizer(
        config['Optimizer'],
        epochs=config['Global']['epoch_num'],
        step_each_epoch=len(train_dataloader),
        parameters=model.parameters())

    # build metric
    eval_class = build_metric(config['Metric'])
    # load pretrain model
    pre_best_model_dict = load_model(config, model, optimizer)

    logger.info(
        'train dataloader has {} iters, valid dataloader has {} iters'.format(
            len(train_dataloader), len(valid_dataloader)))
    # build metric
    eval_class = build_metric(config['Metric'])

    logger.info(
        'train dataloader has {} iters, valid dataloader has {} iters'.format(
            len(train_dataloader), len(valid_dataloader)))

    def eval_fn():
        metric = program.eval(model, valid_dataloader, post_process_class,
                              eval_class, False)
        if config['Architecture']['model_type'] == 'det':
            main_indicator = 'hmean'
        else:
            main_indicator = 'acc'

        logger.info("metric[{}]: {}".format(main_indicator,
                                            metric[main_indicator]))
        return metric[main_indicator]

    run_sensitive_analysis = False
    """
    run_sensitive_analysis=True: 
        Automatically compute the sensitivities of convolutions in a model. 
        The sensitivity of a convolution is the losses of accuracy on test dataset in 
        differenct pruned ratios. The sensitivities can be used to get a group of best 
        ratios with some condition.
    
    run_sensitive_analysis=False: 
        Set prune trim ratio to a fixed value, such as 10%. The larger the value, 
        the more convolution weights will be cropped.

    """

    if run_sensitive_analysis:
        params_sensitive = pruner.sensitive(
            eval_func=eval_fn,
            sen_file="./deploy/slim/prune/sen.pickle",
            skip_vars=[
                "conv2d_57.w_0", "conv2d_transpose_2.w_0",
                "conv2d_transpose_3.w_0"
            ])
        logger.info(
            "The sensitivity analysis results of model parameters saved in sen.pickle"
        )
        # calculate pruned params's ratio
        params_sensitive = pruner._get_ratios_by_loss(params_sensitive,
                                                      loss=0.02)
        for key in params_sensitive.keys():
            logger.info("{}, {}".format(key, params_sensitive[key]))
    else:
        params_sensitive = {}
        for param in model.parameters():
            if 'transpose' not in param.name and 'linear' not in param.name:
                # set prune ratio as 10%. The larger the value, the more convolution weights will be cropped
                params_sensitive[param.name] = 0.1

    plan = pruner.prune_vars(params_sensitive, [0])

    flops = paddle.flops(model, input_shape)
    logger.info("FLOPs after pruning: {}".format(flops))

    # start train

    program.train(config, train_dataloader, valid_dataloader, device, model,
                  loss_class, optimizer, lr_scheduler, post_process_class,
                  eval_class, pre_best_model_dict, logger, vdl_writer)