def test_hawq_behaviour__if_method_returns_none(mocker, method_name,
                                                expected_behavior):
    config = HAWQConfigBuilder().with_sample_size([1, 1, 4, 4]).build()
    config['compression']['initializer']['range']['num_init_samples'] = 0
    config['quantizer_setup_type'] = 'pattern_based'
    model = BasicConvTestModel()
    mock_train_loader = mocker.stub()
    mock_train_loader.batch_size = 1
    config.register_extra_structs([
        QuantizationPrecisionInitArgs(criterion_fn=mocker.stub(),
                                      criterion=mocker.stub(),
                                      data_loader=mock_train_loader,
                                      device='cuda')
    ])
    mocker.patch(
        'nncf.quantization.algo.QuantizationController.run_batchnorm_adaptation'
    )
    mocked_calc_traces = mocker.patch(
        'nncf.quantization.precision_init.hawq_init.HAWQPrecisionInitializer._calc_traces'
    )
    stub = mocker.stub()
    stub.traces_order = TracesOrder([0])
    mocked_calc_traces.return_value = stub

    mocked_method = mocker.patch(
        'nncf.quantization.precision_init.hawq_init.HAWQPrecisionInitializer.'
        + method_name)
    mocked_method.return_value = None

    with expected_behavior:
        create_compressed_model_and_algo_for_test(model, config)
Exemple #2
0
def test_can_restore_binary_mask_on_magnitude_algo_resume():
    config = get_empty_config()
    config['compression'] = {
        "algorithm": "magnitude_sparsity",
        "params": {
            "weight_importance": "abs",
            "schedule": "multistep",
            "multistep_sparsity_levels": [0.3, 0.5]
        }
    }

    sparse_model, _ = create_compressed_model_and_algo_for_test(
        MagnitudeTestModel(), config)
    with torch.no_grad():
        sparse_model(torch.ones([1, 1, 10, 10]))

    config = get_empty_config()
    config["compression"] = {"algorithm": "const_sparsity"}
    const_sparse_model, _ = create_compressed_model_and_algo_for_test(
        MagnitudeTestModel(), config)

    load_state(const_sparse_model, sparse_model.state_dict())

    op = const_sparse_model.conv1.pre_ops['0']
    check_equal(ref_mask_1, op.operand.binary_mask)

    op = const_sparse_model.conv2.pre_ops['0']
    check_equal(ref_mask_2, op.operand.binary_mask)
def test_load_state_interoperability(_algos, _model_wrapper, is_resume):
    config_save = get_empty_config()
    config_save['compression'] = [{
        'algorithm': algo
    } for algo in _algos['save_algos']]
    compressed_model_save, _ = create_compressed_model_and_algo_for_test(
        BasicConvTestModel(), config_save)
    model_save = _model_wrapper['save_model'](compressed_model_save)
    saved_model_state = model_save.state_dict()
    ref_num_loaded = len(saved_model_state)

    config_resume = get_empty_config()
    config_resume['compression'] = [{
        'algorithm': algo
    } for algo in _algos['load_algos']]
    compressed_model_resume, _ = create_compressed_model_and_algo_for_test(
        BasicConvTestModel(), config_resume)
    model_resume = _model_wrapper['resume_model'](compressed_model_resume)

    if not is_resume or (is_resume and _algos['is_resume_ok']):
        act_num_loaded = load_state(model_resume, saved_model_state, is_resume)

        if ('magnitude_sparsity' in _algos['load_algos'] or 'const_sparsity' in _algos['load_algos']) \
            and 'rb_sparsity' in _algos['save_algos']:
            # no need to load _mask and _uniform
            ref_num_loaded -= 2
        assert act_num_loaded == ref_num_loaded
    else:
        with pytest.raises(RuntimeError):
            load_state(model_resume, saved_model_state, is_resume)
def test_logarithm_scale_parameter(logarithm_scale_setting_1,
                                   logarithm_scale_setting_2,
                                   quantization_type):
    for logarithm_scales in [[False, True], [True, False]]:
        for symmetric in [False, True]:
            model0, _ = create_compressed_model_and_algo_for_test(
                TwoConvTestModel(),
                get_config_for_logarithm_scale(
                    logarithm_scale=logarithm_scale_setting_1,
                    quantization_type=quantization_type))

            model1, _ = create_compressed_model_and_algo_for_test(
                TwoConvTestModel(),
                get_config_for_logarithm_scale(
                    logarithm_scale=logarithm_scale_setting_2,
                    quantization_type=quantization_type))

            sd0 = model0.state_dict()
            model1.load_state_dict(sd0)
            sd1 = model1.state_dict()

            for k, v0 in sd0.items():
                v1 = sd1[k]
                diff = (v1 - v0).abs().sum().item() / v1.numel()
                assert diff < 1e-6, "symmetric {} logarithm_scales {} param {} is corrupted mean({}-{})={}".format(
                    symmetric, logarithm_scales, k, v0, v1, diff)
Exemple #5
0
def test_range_init_is_called(config_cutter, range_init_call_count,
                              precision_init_call_count,
                              bn_adaptation_call_count, mocker):
    config = HAWQConfigBuilder().build()
    config['compression']['initializer'].update(
        {'batchnorm_adaptation': {
            'num_bn_adaptation_steps': 5
        }})
    config['input_info'] = {"sample_size": [1, 1, 4, 4]}

    model = BasicConvTestModel()
    config = register_default_init_args(config, mocker.stub(), mocker.stub())
    range_init_spy = mocker.patch(
        'nncf.quantization.algo.QuantizationController._do_range_init')
    precision_init_spy = mocker.patch(
        'nncf.quantization.precision_init.hawq_init.HAWQPrecisionInitializer.apply_init'
    )
    bn_adaptation_spy = mocker.patch(
        'nncf.initialization.DataLoaderBNAdaptationRunner.run')

    config_cutter(config['compression'])
    create_compressed_model_and_algo_for_test(model, config)

    assert range_init_spy.call_count == range_init_call_count
    assert precision_init_spy.call_count == precision_init_call_count
    assert bn_adaptation_spy.call_count == bn_adaptation_call_count
Exemple #6
0
def test_both_targets_assert():
    config = get_basic_pruning_config()
    config['compression']['algorithm'] = 'filter_pruning'
    config['compression']['params']['pruning_target'] = 0.3
    config['compression']['params']['pruning_flops_target'] = 0.5

    model = PruningTestModel()
    with pytest.raises(ValueError):
        create_compressed_model_and_algo_for_test(model, config)
Exemple #7
0
def test_hawq_hw_vpu_config_e2e(_seed, dataset_dir, tmp_path):
    config = HAWQConfigBuilder().for_vpu().with_ratio(1.01).build()
    model = MobileNetV2(num_classes=10)
    criterion = nn.CrossEntropyLoss()
    if not dataset_dir:
        dataset_dir = str(tmp_path)
    train_loader, _ = create_test_dataloaders(config, dataset_dir)
    config = register_default_init_args(config, train_loader, criterion)

    create_compressed_model_and_algo_for_test(model, config)
def test_hawq_raises_error_if_method_returns_none(mocker, method_name):
    config = create_hawq_test_config()
    model = MockModel()
    config = register_default_init_args(config, mocker.stub(), mocker.stub())
    mocker.patch('nncf.quantization.algo.QuantizationController._do_range_init')
    mocker.patch('nncf.quantization.init_precision.HAWQPrecisionInitializer._calc_traces')

    mocked_trace = mocker.patch('nncf.quantization.init_precision.HAWQPrecisionInitializer.' + method_name)
    mocked_trace.return_value = None

    with pytest.raises(RuntimeError):
        create_compressed_model_and_algo_for_test(model, config)
Exemple #9
0
def test_hawq_behaviour__if_method_returns_none(mocker, method_name, expected_behavior):
    config = HAWQConfigBuilder().build()
    config['quantizer_setup_type'] = 'pattern_based'
    model = MockModel()
    config = register_default_init_args(config, mocker.stub(), mocker.stub())
    mocker.patch('nncf.quantization.algo.QuantizationController._do_range_init')
    mocker.patch('nncf.quantization.precision_init.hawq_init.HAWQPrecisionInitializer._calc_traces')

    mocked_trace = mocker.patch('nncf.quantization.precision_init.hawq_init.HAWQPrecisionInitializer.' + method_name)
    mocked_trace.return_value = None

    with expected_behavior:
        create_compressed_model_and_algo_for_test(model, config)
def test_context_independence(model_name, model_builder, input_size,
                              _case_config):

    config = get_basic_quantization_config(_case_config.quant_type,
                                           input_sample_sizes=input_size[0])
    compressed_models = [
        create_compressed_model_and_algo_for_test(model_builder[0](),
                                                  config)[0],
        create_compressed_model_and_algo_for_test(model_builder[1](),
                                                  config)[0]
    ]

    for i, compressed_model in enumerate(compressed_models):
        check_model_graph(compressed_model, model_name[i],
                          _case_config.graph_dir)
Exemple #11
0
def test_staged_quantization_saves_enabled_quantizers_in_state_dict(tmp_path):
    config = get_quantization_config_without_range_init()
    config["compression"]["params"] = {
        "activations_quant_start_epoch": 2,
        "weights_quant_start_epoch": 1
    }
    model_save, ctrl_save = create_compressed_model_and_algo_for_test(BasicConvTestModel(), config)
    ctrl_save.scheduler.epoch_step()

    _, ctrl_load = create_compressed_model_and_algo_for_test(BasicConvTestModel(), config,
                                                             resuming_state_dict=model_save.state_dict())
    for quantizer_info in ctrl_load.non_weight_quantizers.values():
        assert not quantizer_info.quantizer_module_ref.is_enabled_quantization()
    for quantizer in ctrl_load.weight_quantizers.values():
        assert quantizer.is_enabled_quantization()
Exemple #12
0
def test_export_stacked_bi_lstm(tmp_path):
    p = LSTMTestSizes(3, 3, 3, 3)
    config = get_empty_config(
        input_sample_sizes=[1, p.hidden_size, p.input_size])
    config['compression'] = {'algorithm': 'quantization'}

    # TODO: batch_first=True fails with building graph: ambiguous call to mul or sigmoid
    test_rnn = NNCF_RNN('LSTM',
                        input_size=p.input_size,
                        hidden_size=p.hidden_size,
                        num_layers=2,
                        bidirectional=True,
                        batch_first=False)
    model, algo = create_compressed_model_and_algo_for_test(test_rnn, config)

    test_path = str(tmp_path.joinpath('test.onnx'))
    algo.export_model(test_path)
    assert os.path.exists(test_path)

    onnx_num = 0
    model = onnx.load(test_path)
    # pylint: disable=no-member
    for node in model.graph.node:
        if node.op_type == 'FakeQuantize':
            onnx_num += 1
    assert onnx_num == 50
Exemple #13
0
def activation_quantizers_dumping_worker(current_gpu, config, tmp_path):
    model = resnet50(pretrained=False)
    quant_model, _ = create_compressed_model_and_algo_for_test(model, config)
    path = get_path_to_keys(tmp_path, current_gpu)
    print(path)
    with open(path, 'w') as f:
        f.writelines("%s\n" % key for key in quant_model.activation_quantizers.keys())
def test_flops(config_creator, ref_values):
    class ConvLinear(nn.Module):
        def __init__(self):
            super().__init__()
            self.conv1 = create_conv(1, 1, 2, -1, -2)
            self.fc = nn.Linear(3, 6)

        def forward(self, x):
            return self.fc(self.conv1(x))

    config = config_creator()
    model, compression_ctrl = create_compressed_model_and_algo_for_test(
        ConvLinear(), config)
    quantizers = compression_ctrl.weight_quantizers

    handler = WeightQuantizersHandler(model, quantizers,
                                      HardwareQuantizationConstraints())
    flops_counter = CompressionRatioCalculator(model, handler)

    assert flops_counter.ratio_for_bits_configuration([4, 8]) == ref_values[0]
    assert flops_counter.ratio_for_bits_configuration([8, 4]) == ref_values[1]
    assert flops_counter.ratio_limits([4, 8]) == ref_values[2]
    assert flops_counter.ratio_limits([2, 4, 8]) == ref_values[3]
    constraints = HardwareQuantizationConstraints()
    constraints.add(list(quantizers)[0], {8})
    assert flops_counter.ratio_limits([2, 8], constraints) == ref_values[4]
Exemple #15
0
def test_baseline_scheduler():
    """
    Test baseline scheduler parameters and changes of params during epochs.
    """
    config = get_pruning_baseline_config()
    config['compression']['algorithm'] = 'filter_pruning'
    model = PruningTestModel()
    _, compression_ctrl = create_compressed_model_and_algo_for_test(
        model, config)
    scheduler = compression_ctrl.scheduler

    # Check default params
    assert isinstance(scheduler, BaselinePruningScheduler)
    assert pytest.approx(scheduler.pruning_target) == 0.5
    assert pytest.approx(scheduler.initial_pruning) == 0.0
    assert scheduler.num_init_steps == 1

    # Check pruning params before epoch 0
    scheduler.epoch_step()
    assert pytest.approx(scheduler.current_pruning_level) == 0.0
    assert pytest.approx(compression_ctrl.pruning_rate) == 0.0
    assert scheduler.current_epoch == 0
    assert compression_ctrl.frozen is False

    # Check pruning params after epoch 0
    scheduler.epoch_step()
    assert pytest.approx(scheduler.current_pruning_level) == 0.5
    assert pytest.approx(compression_ctrl.pruning_rate) == 0.5
    assert scheduler.current_epoch == 1
    assert compression_ctrl.frozen is True
Exemple #16
0
    def test_scheduler_can_do_epoch_step(self, algo, schedule, get_params,
                                         ref_levels):
        model = BasicConvTestModel()
        config = get_empty_config()
        config['compression'] = {
            'algorithm': algo,
            "sparsity_init": 0.2,
            "params": {
                **get_params(), "schedule": schedule
            }
        }

        _, compression_ctrl = create_compressed_model_and_algo_for_test(
            model, config)

        scheduler = compression_ctrl.scheduler
        scheduler.epoch_step()
        assert pytest.approx(scheduler.current_sparsity_level) == ref_levels[0]
        for ref_level in ref_levels[1:]:
            scheduler.epoch_step()
            assert pytest.approx(scheduler.current_sparsity_level) == ref_level

        for m in compression_ctrl.sparsified_module_info:
            if hasattr(m.operand, "frozen"):
                assert m.operand.frozen
Exemple #17
0
    def test_number_of_calling_fq_for_lstm(self):
        p = LSTMTestSizes(1, 1, 1, 5)
        num_layers = 2
        bidirectional = True
        num_directions = 2 if bidirectional else 1
        bias = True
        batch_first = False
        config = get_empty_config(
            input_sample_sizes=[p.seq_length, p.batch, p.input_size])
        config['compression'] = {
            'algorithm': 'quantization',
            'quantize_inputs': True
        }

        test_data = TestLSTMCell.generate_lstm_data(p,
                                                    num_layers,
                                                    num_directions,
                                                    bias=bias,
                                                    batch_first=batch_first)

        test_rnn = NNCF_RNN('LSTM',
                            input_size=p.input_size,
                            hidden_size=p.hidden_size,
                            num_layers=num_layers,
                            bidirectional=bidirectional,
                            bias=bias,
                            batch_first=batch_first)
        TestLSTM.set_ref_lstm_weights(test_data, test_rnn, num_layers,
                                      num_directions, bias)
        test_hidden = TestLSTM.get_test_lstm_hidden(test_data)

        model, algo = create_compressed_model_and_algo_for_test(
            test_rnn, config)

        class Counter:
            def __init__(self):
                self.count = 0

            def next(self):
                self.count += 1

        def hook(model, input_, counter):
            counter.next()

        counters = {}
        counter_for_input_quantizer = None
        for name, quantizer in algo.all_quantizations.items():
            counter = Counter()
            quantizer.register_forward_pre_hook(partial(hook, counter=counter))
            if str(name) == '/nncf_model_input_0|OUTPUT':
                counter_for_input_quantizer = counter
                continue
            counters[name] = counter
        _ = model(test_data.x, test_hidden)
        assert model.get_graph().get_nodes_count(
        ) == 112  # NB: may always fail in debug due to superfluous 'cat' nodes
        assert len(counters) + 1 == 55  # 8 WQ + 46 AQ + 1 input AQ
        for counter in counters.values():
            assert counter.count == p.seq_length
        assert counter_for_input_quantizer.count == 1
def test_hawq_precision_init(_seed, dataset_dir, tmp_path, mocker, config_creator: Callable, filename_suffix: str,
                             avg_traces_creator: Callable):
    batch_size = 10
    config = config_creator(batch_size)
    model = MobileNetV2(num_classes=10)
    model.eval()

    criterion = nn.CrossEntropyLoss().cuda()
    if not dataset_dir:
        dataset_dir = str(tmp_path)
    train_loader, _ = create_test_dataloaders(config.get("model_size"), dataset_dir, batch_size)
    config = register_default_init_args(config, criterion, train_loader)

    mocked_trace = mocker.patch('nncf.quantization.hessian_trace.HessianTraceEstimator.get_average_traces')

    mocked_trace.return_value = avg_traces_creator(model, 'cuda')
    from torchvision.models.mobilenet import model_urls
    load_state(model, model_zoo.load_url(model_urls['mobilenet_v2']))
    model, algo_ctrl = create_compressed_model_and_algo_for_test(model, config)
    model = model.cuda()

    all_quantizers_per_full_scope = HAWQDebugger.get_all_quantizers_per_full_scope(model)
    quantizer_switcher = QuantizersSwitcher(list(all_quantizers_per_full_scope.values()))
    # graph may not contain some quantizers (e.g. in staged scenario)
    quantizer_switcher.enable_quantizers()
    model.rebuild_graph()
    graph = HAWQDebugger.get_bitwidth_graph(algo_ctrl, model, all_quantizers_per_full_scope)
    path_to_dot = 'mobilenet_v2_mixed_bitwidth_graph_{}.dot'.format(filename_suffix)
    check_graph(graph, path_to_dot, os.path.join('quantized', 'hawq'), sort_dot_graph=False)
Exemple #19
0
def test_staged_scheduler_with_empty_quantization():
    config = get_squeezenet_quantization_config()
    config['compression'].update({
        'params': {
            "activations_quant_start_epoch": 1,
            "weights_quant_start_epoch": 2,
        }
    })
    model = squeezenet1_1_custom(num_classes=10, pretrained=False, dropout=0)

    model, algo = create_compressed_model_and_algo_for_test(model, config)
    scheduler = algo.scheduler
    for module in algo.all_quantizations.values():
        assert not module.is_enabled_quantization()

    scheduler.epoch_step()
    for module in algo.all_quantizations.values():
        if module.is_weights:
            assert not module.is_enabled_quantization()
        else:
            assert module.is_enabled_quantization()

    scheduler.epoch_step()
    for module in algo.all_quantizations.values():
        assert module.is_enabled_quantization()
Exemple #20
0
def test_sparse_algo_can_collect_sparse_layers():
    model = TwoConvTestModel()

    config = get_basic_sparsity_config()
    _, compression_ctrl = create_compressed_model_and_algo_for_test(model, config)

    assert len(compression_ctrl.sparsified_module_info) == 2
def test_input_info_specification_from_config(mocker, input_info_test_struct):
    stub_fn = mocker.stub()
    mock_model = MockModel(stub_fn)
    config = get_basic_quantization_config("symmetric")
    input_info_config_entry = input_info_test_struct[0]
    target_argument_info = input_info_test_struct[
        1]  # type: List[ModelInputInfo]
    config["input_info"] = input_info_config_entry

    _, _ = create_compressed_model_and_algo_for_test(mock_model, config)
    forward_call_args = stub_fn.call_args[0]
    forward_call_kwargs = stub_fn.call_args[1]

    ref_args_info = list(
        filter(lambda x: x.keyword is None, target_argument_info))
    ref_kw_vs_arg_info = {
        x.keyword: x
        for x in target_argument_info if x.keyword is not None
    }

    def check_arg(arg: torch.Tensor, ref_arg_info: ModelInputInfo):
        assert list(arg.shape) == ref_arg_info.shape
        assert arg.dtype == ref_arg_info.type

    assert len(forward_call_args) == len(ref_args_info)
    assert len(forward_call_kwargs) == len(ref_kw_vs_arg_info)
    assert set(forward_call_kwargs.keys()) == set(ref_kw_vs_arg_info.keys())

    for idx, arg in enumerate(forward_call_args):
        check_arg(arg, ref_args_info[idx])

    for keyword, arg in forward_call_kwargs.items():
        check_arg(arg, ref_kw_vs_arg_info[keyword])
Exemple #22
0
def test_create_rb_algo_with_per_layer_loss():
    config = get_empty_config()
    config['compression'] = {'algorithm': 'rb_sparsity', "params": {"sparsity_level_setting_mode": 'local'}}
    _, compression_ctrl = create_compressed_model_and_algo_for_test(MockModel(), config)

    # pylint: disable=protected-access
    assert isinstance(compression_ctrl._loss, SparseLossForPerLayerSparsity)
def test_hawq_precision_init(_seed, dataset_dir, tmp_path, mocker, params):
    config = params.config_builder.build()
    model = params.model_creator().cuda()

    criterion = nn.CrossEntropyLoss().cuda()
    if not dataset_dir:
        dataset_dir = str(tmp_path)
    train_loader, _ = create_test_dataloaders(config, dataset_dir)
    config = register_default_init_args(config, train_loader, criterion)

    mocked_trace = mocker.patch(
        'nncf.quantization.hessian_trace.HessianTraceEstimator.get_average_traces',
        autospec=True)
    pregen_traces_for_all_layers = params.avg_traces_creator(model, 'cuda')

    # There may be less traces required to be calculated during HAWQ than there are weightable layers.
    def side_effect_fn(self, max_iter=500, tolerance=1e-5):
        #pylint:disable=protected-access
        return pregen_traces_for_all_layers[:len(self._parameter_handler.
                                                 parameters)]

    mocked_trace.side_effect = side_effect_fn
    model, algo_ctrl = create_compressed_model_and_algo_for_test(model, config)

    path_to_dot = '{}_{}.dot'.format(params.model_creator.__name__,
                                     params.config_builder.filename_suffix())
    graph_dir = os.path.join('quantized', 'hawq')
    check_bitwidth_graph(algo_ctrl, model, path_to_dot, graph_dir)
Exemple #24
0
def test_magnitude_algo_binary_masks_are_applied():
    model = BasicConvTestModel()
    config = get_empty_config()
    config['compression'] = {'algorithm': "magnitude_sparsity"}
    compressed_model, compression_ctrl = create_compressed_model_and_algo_for_test(
        model, config)
    minfo_list = compression_ctrl.sparsified_module_info  # type: List[SparseModuleInfo]
    minfo = minfo_list[0]  # type: SparseModuleInfo

    minfo.operand.binary_mask = torch.ones_like(minfo.module.weight)  # 1x1x2x2
    input_ = torch.ones(size=(1, 1, 5, 5))
    ref_output_1 = -4 * torch.ones(size=(2, 4, 4))
    output_1 = compressed_model(input_)
    assert torch.all(torch.eq(output_1, ref_output_1))

    minfo.operand.binary_mask[0][0][0][1] = 0
    minfo.operand.binary_mask[1][0][1][0] = 0
    ref_output_2 = -3 * torch.ones_like(ref_output_1)
    output_2 = compressed_model(input_)
    assert torch.all(torch.eq(output_2, ref_output_2))

    minfo.operand.binary_mask[1][0][0][1] = 0
    ref_output_3 = ref_output_2.clone()
    ref_output_3[1] = -2 * torch.ones_like(ref_output_1[1])
    output_3 = compressed_model(input_)
    assert torch.all(torch.eq(output_3, ref_output_3))
def test_quantization_configs__with_precisions_list():
    model = ModelForTest()

    config = get_quantization_config_without_range_init()
    config['compression']['initializer'].update({
        "precision": {
            "bitwidth_per_scope": [[2, 'ModelForTest/NNCFConv2d[conv1]'],
                                   [4, 'ModelForTest/NNCFConv2d[conv2]']]
        }
    })
    config['compression']["activations"] = {"bits": 6}
    config['quantizer_setup_type'] = 'pattern_based'
    model, compression_ctrl = create_compressed_model_and_algo_for_test(
        model, config)

    ref_bits = [('ModelForTest/NNCFConv2d[conv1]module_weight', 2),
                ('ModelForTest/NNCFConv2d[conv2]module_weight', 4),
                ('ModelForTest/NNCFConv2d[conv2]/conv2d_0|OUTPUT', 6),
                ('ModelForTest/NNCFConv2d[conv1]/conv2d_0|OUTPUT', 6),
                ('/nncf_model_input_0|OUTPUT', 6)]

    for key, quantizer in compression_ctrl.all_quantizations.items():
        expected_bit = [
            ref_bit for (name, ref_bit) in ref_bits if name == str(key)
        ][0]
        assert quantizer.num_bits == expected_bit, 'Unexpected number of bits for {}'.format(
            key)

    ref_rows = [['2', '20', '0', '20'], ['4', '20', '0', '20'],
                ['6', '0', '60', '60']]
    table = compression_ctrl.non_stable_metric_collectors[0].get_bits_stat()
    # pylint: disable=protected-access
    assert table._rows == ref_rows
Exemple #26
0
def test_can_create_magnitude_sparse_algo__with_defaults():
    model = MagnitudeTestModel()
    config = get_basic_magnitude_sparsity_config()
    config['compression']['params'] = \
        {'schedule': 'multistep'}
    sparse_model, compression_ctrl = create_compressed_model_and_algo_for_test(
        deepcopy(model), config)

    assert isinstance(compression_ctrl, MagnitudeSparsityController)
    assert compression_ctrl.scheduler.current_sparsity_level == approx(0.1)
    assert len(list(sparse_model.modules())) == 12

    _, sparse_model_conv = check_correct_nncf_modules_replacement(
        model, sparse_model)

    i = 0

    stats = compression_ctrl.statistics()
    assert stats["sparsity_threshold"] == approx(0.24, 0.1)
    assert isinstance(compression_ctrl.weight_importance,
                      type(normed_magnitude))

    for sparse_module in sparse_model_conv.values():
        store = []
        ref_mask = torch.ones_like(
            sparse_module.weight) if i == 0 else ref_mask_2
        i += 1
        for op in sparse_module.pre_ops.values():
            if isinstance(op, UpdateWeight) and isinstance(
                    op.operand, BinaryMask):
                assert torch.allclose(op.operand.binary_mask, ref_mask)
                assert op.__class__.__name__ not in store
                store.append(op.__class__.__name__)
def test_magnitude_scheduler_can_do_epoch_step__with_norm():
    _ = MagnitudeTestModel()
    config = get_multistep_normed_abs_config()
    _, compression_ctrl = create_compressed_model_and_algo_for_test(
        MagnitudeTestModel(), config)
    scheduler = compression_ctrl.scheduler
    assert isinstance(scheduler, MultiStepSparsityScheduler)

    assert compression_ctrl.scheduler.current_sparsity_level == pytest.approx(
        0.1)
    assert compression_ctrl.statistics(
    )["sparsity_threshold"] == pytest.approx(0.219, 0.01)
    assert scheduler.prev_ind == 0

    scheduler.epoch_step()
    assert compression_ctrl.scheduler.current_sparsity_level == pytest.approx(
        0.5)
    assert compression_ctrl.statistics(
    )["sparsity_threshold"] == pytest.approx(0.243, 0.01)
    assert scheduler.prev_ind == 1

    scheduler.epoch_step()
    assert compression_ctrl.scheduler.current_sparsity_level == pytest.approx(
        0.5)
    assert compression_ctrl.statistics(
    )["sparsity_threshold"] == pytest.approx(0.243, 0.01)
    assert scheduler.prev_ind == 1

    scheduler.epoch_step()
    assert compression_ctrl.scheduler.current_sparsity_level == pytest.approx(
        0.9)
    assert compression_ctrl.statistics(
    )["sparsity_threshold"] == pytest.approx(0.371, 0.01)
    assert scheduler.prev_ind == 2
Exemple #28
0
def test_can_not_set_sparsity_more_than_one_for_magnitude_sparse_algo():
    config = get_basic_magnitude_sparsity_config()
    _, compression_ctrl = create_compressed_model_and_algo_for_test(
        MagnitudeTestModel(), config)
    with pytest.raises(AttributeError):
        compression_ctrl.set_sparsity_level(1)
        compression_ctrl.set_sparsity_level(1.2)
def test_ordinary_load(algo, _model_wrapper, is_resume):
    config = get_empty_config()
    if algo:
        config['compression'] = {'algorithm': algo}

    compressed_model_save, _ = create_compressed_model_and_algo_for_test(
        BasicConvTestModel(), config)
    model_save = _model_wrapper['save_model'](compressed_model_save)

    compressed_model_resume, _ = create_compressed_model_and_algo_for_test(
        BasicConvTestModel(), config)
    model_resume = _model_wrapper['resume_model'](compressed_model_resume)

    num_loaded = load_state(model_resume, model_save.state_dict(), is_resume)

    assert num_loaded == len(model_save.state_dict())
Exemple #30
0
def test_can_load_quant_algo__with_defaults():
    model = BasicConvTestModel()
    config = get_quantization_config_without_range_init()
    compression_algo_builder_list = create_compression_algorithm_builders(config)
    assert len(compression_algo_builder_list) == 1
    assert isinstance(compression_algo_builder_list[0], QuantizationBuilder)

    quant_model, _ = create_compressed_model_and_algo_for_test(deepcopy(model), config)

    model_conv = get_all_modules_by_type(model, 'Conv2d')
    quant_model_conv = get_all_modules_by_type(quant_model.get_nncf_wrapped_model(), 'NNCFConv2d')
    assert len(model_conv) == len(quant_model_conv)

    for module_scope, _ in model_conv.items():
        quant_scope = deepcopy(module_scope)  # type: Scope
        quant_scope.pop()
        quant_scope.push(ScopeElement('NNCFConv2d', 'conv'))
        assert quant_scope in quant_model_conv.keys()

        store = []
        for op in quant_model_conv[quant_scope].pre_ops.values():
            if isinstance(op, (UpdateInputs, UpdateWeight)) and isinstance(op.operand, SymmetricQuantizer):
                assert op.__class__.__name__ not in store
                store.append(op.__class__.__name__)
        assert UpdateWeight.__name__ in store