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']]
    register_bn_adaptation_init_args(config_save)
    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']]
    register_bn_adaptation_init_args(config_resume)
    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)
示例#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']
    PTTensorListComparator.check_equal(ref_mask_1, op.operand.binary_mask)

    op = const_sparse_model.conv2.pre_ops['0']
    PTTensorListComparator.check_equal(ref_mask_2, op.operand.binary_mask)
def test_load_state__with_resume_checkpoint(_resume_algos, _model_wrapper,
                                            mocker):
    config_save = get_empty_config()
    config_save['compression'] = [{
        'algorithm': algo
    } for algo in _resume_algos['save_algos'] if algo != 'EMPTY']
    register_bn_adaptation_init_args(config_save)
    orig_model = BasicConvTestModel()
    num_model_params = len(orig_model.state_dict())
    model_save, compressed_ctrl_save = create_compressed_model_and_algo_for_test(
        orig_model, config_save)
    saved_model_state = model_save.state_dict()
    saved_checkpoint = compressed_ctrl_save.get_compression_state()
    ref_num_loaded = _resume_algos[
        'ref_num_compression_params'] + num_model_params + 1  # padding_value

    config_resume = get_empty_config()
    config_resume['compression'] = [{
        'algorithm': algo
    } for algo in _resume_algos['load_algos'] if algo != 'EMPTY']
    register_bn_adaptation_init_args(config_resume)
    from nncf.torch.checkpoint_loading import KeyMatcher
    key_matcher_run_spy = mocker.spy(KeyMatcher, 'run')
    model, _ = create_compressed_model_and_algo_for_test(
        BasicConvTestModel(),
        config_resume,
        compression_state=saved_checkpoint)
    load_state(model, saved_model_state, _resume_algos['is_strict'])
    key_matcher_run_spy.assert_called_once()
    act_num_loaded = len(key_matcher_run_spy.spy_return)
    assert act_num_loaded == ref_num_loaded
示例#4
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
 def create_config(self):
     self.with_range_init()
     config = get_empty_config()
     config.update(self.config_update)
     for config_updater in self._config_updaters:
         config = config_updater(config)
     return config
def test_building_block(model_creator, input_sizes, ref_building_blocks):
    model = model_creator()
    nncf_config = get_empty_config(input_sample_sizes=input_sizes)
    _, compressed_model = create_compressed_model(model, nncf_config)

    building_blocks = get_building_blocks(compressed_model)
    assert building_blocks == ref_building_blocks
示例#7
0
def test_can_do_sparsity_freeze_epoch():

    def compare_binary_mask(ref_sparse_module_info, sparse_module_info):
        for ref_sparse_layer, sparse_layer in zip(ref_sparse_module_info, sparse_module_info):
            if (ref_sparse_layer.operand.binary_mask != sparse_layer.operand.binary_mask).view(-1).sum() != 0:
                return False
        return True

    model = BasicConvTestModel()
    config = get_empty_config()
    config['compression'] = {"algorithm": "magnitude_sparsity",
                             "sparsity_init": 0.1,
                             "params": {"sparsity_target": 0.9,
                                        "sparsity_target_epoch": 3,
                                        "sparsity_freeze_epoch": 3}}
    _, compression_ctrl = create_compressed_model_and_algo_for_test(model, config)
    sparsified_minfo_before_update = deepcopy(compression_ctrl.sparsified_module_info)
    compression_ctrl.scheduler.epoch_step() # update binary_masks
    compression_ctrl.scheduler.epoch_step() # update binary_masks
    compression_ctrl.scheduler.epoch_step() # update binary_masks, freeze binary_masks
    sparsified_minfo_after_update = deepcopy(compression_ctrl.sparsified_module_info)

    assert not compare_binary_mask(sparsified_minfo_after_update, sparsified_minfo_before_update)

    compression_ctrl.scheduler.epoch_step() # don't update binary_masks
    sparsified_minfo_after_freeze = deepcopy(compression_ctrl.sparsified_module_info)

    assert compare_binary_mask(sparsified_minfo_after_update, sparsified_minfo_after_freeze)
示例#8
0
def test_quantization_preset_with_scope_overrides():
    model = QuantizeOutputsTestModel()
    config = get_empty_config(input_sample_sizes=[2, 3, 32, 32])
    config['target_device'] = "TRIAL"
    config['compression'] = {
        'algorithm': 'quantization',
        'preset': 'mixed',
        'scope_overrides': {
            'weights': {
                'QuantizeOutputsTestModel/NNCFConv2d[conv5]/conv2d_0': {
                    "mode": "asymmetric",
                }
            }
        }
    }
    register_bn_adaptation_init_args(config)
    _, compression_ctrl = create_compressed_model_and_algo_for_test(
        model, config)

    for wq_info in compression_ctrl.weight_quantizers.values():
        if wq_info.affected_insertions[0].target_node_name !=\
             'QuantizeOutputsTestModel/NNCFConv2d[conv5]/conv2d_0':
            assert isinstance(wq_info.quantizer_module_ref, SymmetricQuantizer)
        else:
            assert isinstance(wq_info.quantizer_module_ref,
                              AsymmetricQuantizer)

    for aq_info in compression_ctrl.non_weight_quantizers.values():
        assert isinstance(aq_info.quantizer_module_ref, AsymmetricQuantizer)
示例#9
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))
示例#10
0
def test_activation_quantizers_order_is_the_same__for_resnet50(
        tmp_path, runs_subprocess_in_precommit):
    if not torch.cuda.is_available():
        pytest.skip("Skipping CUDA test cases for CPU only setups")
    config = get_empty_config(input_sample_sizes=[1, 3, 224, 224])
    config['compression'] = {
        'algorithm': 'quantization',
        "initializer": {
            "range": {
                "num_init_samples": 0
            }
        }
    }
    register_bn_adaptation_init_args(config)
    ngpus_per_node = torch.cuda.device_count()

    torch.multiprocessing.spawn(activation_quantizers_dumping_worker,
                                nprocs=ngpus_per_node,
                                args=(config, tmp_path),
                                join=True)

    with open(get_path_to_keys(tmp_path, 0), 'r', encoding='utf8') as f:
        ref_list = f.readlines()
    for i in range(1, ngpus_per_node):
        with open(get_path_to_keys(tmp_path, i), 'r', encoding='utf8') as f:
            curr_list = f.readlines()
            assert curr_list == ref_list
示例#11
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'}
    register_bn_adaptation_init_args(config)

    # 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 == 54
示例#12
0
def test_can_restore_binary_mask_on_magnitude_quant_algo_resume(
        tmp_path, use_data_parallel):
    config = get_empty_config()
    config["compression"] = [{
        "algorithm": "magnitude_sparsity",
        "params": {
            "schedule": "multistep",
            "multistep_sparsity_levels": [0.3, 0.5],
            "weight_importance": "abs"
        }
    }, {
        "algorithm": "quantization"
    }]
    register_bn_adaptation_init_args(config)

    sparse_model, _ = create_compressed_model_and_algo_for_test(
        MagnitudeTestModel(), config)

    if use_data_parallel:
        if not torch.cuda.is_available():
            pytest.skip("Skipping CUDA test cases for CPU only setups")
        sparse_model.cuda()
        sparse_model = torch.nn.DataParallel(sparse_model)

    with torch.no_grad():
        sparse_model(torch.ones([1, 1, 10, 10]))

    config = get_empty_config()
    config["compression"] = [{
        "algorithm": "const_sparsity"
    }, {
        "algorithm": "quantization"
    }]
    register_bn_adaptation_init_args(config)
    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.get_nncf_wrapped_model().conv1.pre_ops['0']
    PTTensorListComparator.check_equal(ref_mask_1, op.operand.binary_mask)

    op = const_sparse_model.get_nncf_wrapped_model().conv2.pre_ops['0']
    PTTensorListComparator.check_equal(ref_mask_2, op.operand.binary_mask)
示例#13
0
def test_can_not_create_magnitude_algo__with_adaptive_scheduler():
    config = get_empty_config()
    config['compression'] = {
        'algorithm': 'magnitude_sparsity',
        "params": {
            "schedule": 'adaptive'
        }
    }
    with pytest.raises(TypeError):
        _, _ = create_compressed_model_and_algo_for_test(MockModel(), config)
def get_basic_quantization_config(quantization_type='symmetric', input_sample_sizes=None, input_info: Dict = None):
    config = get_empty_config(input_sample_sizes=input_sample_sizes, input_info=input_info)
    config["compression"] = {"algorithm": "quantization",
                             "activations": {
                                 "mode": quantization_type
                             },
                             "weights": {
                                 "mode": quantization_type
                             }}
    return config
示例#15
0
def test_can_create_rb_algo__with_adaptive_scheduler():
    config = get_empty_config()
    config['compression'] = {
        'algorithm': 'rb_sparsity',
        "params": {
            "schedule": 'adaptive'
        }
    }
    _, compression_ctrl = create_compressed_model_and_algo_for_test(
        MockModel(), config)
    assert isinstance(compression_ctrl.scheduler, AdaptiveSparsityScheduler)
示例#16
0
def test_can_choose_scheduler(algo, schedule_type, scheduler_class):
    config = get_empty_config()
    config['compression'] = {
        'algorithm': algo,
        "params": {
            "schedule": schedule_type
        }
    }
    _, compression_ctrl = create_compressed_model_and_algo_for_test(
        MockModel(), config)
    assert isinstance(compression_ctrl.scheduler, scheduler_class)
示例#17
0
def get_quantization_config_without_range_init(model_size=4) -> NNCFConfig:
    config = get_empty_config(input_sample_sizes=[1, 1, model_size, model_size])
    config["compression"] = {
        "algorithm": "quantization",
        "initializer": {
            "range": {
                "num_init_samples": 0
            }
        }
    }
    return config
示例#18
0
def test_create_rb_algo_with_local_sparsity_mode():
    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)
    assert compression_ctrl.compression_stage(
    ) == CompressionStage.FULLY_COMPRESSED
示例#19
0
def create_config():
    config = get_empty_config()
    config['compression'] = {
        'algorithm': 'quantization',
        'initializer': {
            'range': {
                'num_init_samples': 1
            }
        }
    }
    register_bn_adaptation_init_args(config)
    return config
示例#20
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)
示例#21
0
def test_can_freeze_binary_masks():
    model = BasicConvTestModel()
    config = get_empty_config()
    config['compression'] = {'algorithm': "magnitude_sparsity"}
    _, compression_ctrl = create_compressed_model_and_algo_for_test(model, config)

    for sparse_layer in compression_ctrl.sparsified_module_info:
        assert not sparse_layer.operand.frozen

    compression_ctrl.freeze()

    for sparse_layer in compression_ctrl.sparsified_module_info:
        assert sparse_layer.operand.frozen
示例#22
0
 def test_can_create_sparse_scheduler__with_defaults(self, algo):
     config = get_empty_config()
     config['compression'] = {
         'algorithm': algo,
         "params": {
             "schedule": 'polynomial'
         }
     }
     _, compression_ctrl = create_compressed_model_and_algo_for_test(
         MockModel(), config)
     scheduler = compression_ctrl.scheduler
     assert scheduler.initial_level == 0
     assert scheduler.target_level == 0.5
     assert scheduler.target_epoch == 90
     assert scheduler.freeze_epoch == 100
    def test_sparse_network(self, desc: ModelDesc, algo):
        model = desc.model_builder()

        config = get_empty_config(input_sample_sizes=desc.input_sample_sizes)
        config["compression"] = {"algorithm": algo}

        compressed_model, compression_ctrl = \
            create_compressed_model_and_algo_for_test(model, config, dummy_forward_fn=desc.dummy_forward_fn,
                                                      wrap_inputs_fn=desc.wrap_inputs_fn)


        sparsifiable_modules = self.get_sparsifiable_modules(algo)
        ref_num_sparsed = len(get_all_modules_by_type(model, sparsifiable_modules))
        assert ref_num_sparsed == len(compression_ctrl.sparsified_module_info)
        check_model_graph(compressed_model, desc.dot_filename, algo)
def test_ordinary_load(algo, _model_wrapper, is_resume):
    config = get_empty_config()
    if algo:
        config['compression'] = {'algorithm': algo}
    register_bn_adaptation_init_args(config)

    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())
示例#25
0
def test_sparsity_statistics_add_module(algo):
    config = get_empty_config()
    sparsity_init = 0.5
    config['compression'] = {'algorithm': algo, 'sparsity_init': sparsity_init}
    model = TwoConvTestModel()
    fill_params_of_model_by_normal(model)
    submodule = TwoConvTestModel()
    fill_params_of_model_by_normal(submodule)
    model, compression_ctrl = create_compressed_model_and_algo_for_test(
        model, config)
    statistics_before = compression_ctrl.statistics()
    model.add_module('submodule', submodule)
    statistics_after = compression_ctrl.statistics()
    assert getattr(statistics_before, algo).model_statistics.sparsity_level == \
           getattr(statistics_after, algo).model_statistics.sparsity_level
    assert getattr(statistics_before, algo).model_statistics.sparsity_level_for_layers == \
           getattr(statistics_after, algo).model_statistics.sparsity_level_for_layers
示例#26
0
def test_export_lstm_cell(tmp_path):
    config = get_empty_config(model_size=1, input_sample_sizes=[1, 1])
    config['compression'] = {'algorithm': 'quantization'}
    register_bn_adaptation_init_args(config)

    model, algo = create_compressed_model_and_algo_for_test(
        LSTMCellNNCF(1, 1), 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 == 14
    def test_sparse_quantize_network(self, desc: ModelDesc):
        model = desc.model_builder()

        config = get_empty_config(input_sample_sizes=desc.input_sample_sizes)
        config["compression"] = [
            {"algorithm": "rb_sparsity"},
            {"algorithm": "quantization"}
        ]
        register_bn_adaptation_init_args(config)

        compressed_model, compression_ctrl = \
            create_compressed_model_and_algo_for_test(model, config, dummy_forward_fn=desc.dummy_forward_fn,
                                                      wrap_inputs_fn=desc.wrap_inputs_fn)

        sparsifiable_modules = self.get_sparsifiable_modules('rb_sparsity')
        ref_num_sparsed = len(get_all_modules_by_type(compressed_model, sparsifiable_modules))

        assert ref_num_sparsed == len(compression_ctrl.child_ctrls[0].sparsified_module_info)
        check_model_graph(compressed_model, desc.dot_filename, "quantized_rb_sparsity")
示例#28
0
def test_rb_sparsity__can_set_sparsity_level_for_module():
    config = get_empty_config()
    config['compression'] = {
        'algorithm': 'rb_sparsity',
        "params": {
            "sparsity_level_setting_mode": 'local'
        }
    }
    _, compression_ctrl = create_compressed_model_and_algo_for_test(
        BasicConvTestModel(), config)

    # pylint: disable=protected-access
    assert list(compression_ctrl._loss.per_layer_target.values())[0] == 1

    compression_ctrl.set_sparsity_level(
        0.7, compression_ctrl.sparsified_module_info[0])
    assert list(
        compression_ctrl._loss.per_layer_target.values())[0] == pytest.approx(
            0.3)
def test_kd_sparsity_statistics(algo: str):
    model = TwoConvTestModel()
    fill_params_of_model_by_normal(model)
    model_with_kd = deepcopy(model)
    config = get_empty_config()
    sparsity_init = 0.5
    config['compression'] = {'algorithm': algo, 'sparsity_init': sparsity_init}
    config_with_kd = deepcopy(config)
    config_with_kd = get_kd_config(config_with_kd)

    model, compression_ctrl = create_compressed_model_and_algo_for_test(
        model, config)
    model_with_kd, compression_ctrl_with_kd = create_compressed_model_and_algo_for_test(
        model_with_kd, config_with_kd)
    statistics = compression_ctrl.statistics()
    statistics_with_kd = compression_ctrl_with_kd.statistics()
    assert getattr(statistics, algo).model_statistics.sparsity_level ==\
           getattr(statistics_with_kd, algo).model_statistics.sparsity_level
    assert getattr(statistics, algo).model_statistics.sparsity_level_for_layers ==\
           getattr(statistics_with_kd, algo).model_statistics.sparsity_level_for_layers
示例#30
0
def test_quantization_preset(data):
    model = BasicConvTestModel()
    config = get_empty_config(input_sample_sizes=[1, 1, 4, 4])
    config['target_device'] = data['target_device']
    config['compression'] = {
        'algorithm': 'quantization',
        'preset': data['preset']
    }
    config['compression'].update(data['overrided_param'])
    register_bn_adaptation_init_args(config)
    _, compression_ctrl = create_compressed_model_and_algo_for_test(
        model, config)

    for wq_info in compression_ctrl.weight_quantizers.values():
        assert isinstance(wq_info.quantizer_module_ref,
                          data['expected_weights_q'])

    for aq_info in compression_ctrl.non_weight_quantizers.values():
        assert isinstance(aq_info.quantizer_module_ref,
                          data['expected_activations_q'])