Skip to content

Commit

Permalink
Fixed unified FakeConverts duplication (#2877)
Browse files Browse the repository at this point in the history
### Changes

- Fixed the `MinMax` algorithm for the `FakeConvert` insertion case.

### Reason for changes

- Incorrect `MinMax` behaviour introduced in
#2622.

### Related tickets

- 149128

### Tests

- Manual

Incorrect behaviour - two identical layers were inserted:

![image](https://github.com/user-attachments/assets/28fb5419-c9ac-400d-a8cc-bcf1d0e32241)
Corrected behaviour - only one layer for each branch was inserted:

![image](https://github.com/user-attachments/assets/d0ab38e5-320a-49b3-8c02-5669b42257f4)
  • Loading branch information
KodiaqQ authored Aug 9, 2024
1 parent 01b748f commit 8634037
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 0 deletions.
1 change: 1 addition & 0 deletions nncf/quantization/algorithms/min_max/algorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -926,6 +926,7 @@ def filter_func(point: StatisticPoint) -> bool:
transformation_layout.register(
self._backend_entity.create_convert_insertion_command(quantization_target_point, parameters)
)
unified_ops_list.add(quantization_target_point)
continue
parameters = calculate_quantizer_parameters(unified_values, qconfig, q_group, narrow_range)
commands = self._backend_entity.create_unified_scales_quantizers_insertion_commands(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"Conv/fc_weights_1": {
"scale": [
[
[
[
550.8624267578125
]
]
],
[
[
[
490.8214416503906
]
]
],
[
[
[
479.1072692871094
]
]
]
],
"shift": [
[
[
[
0.0
]
]
],
[
[
[
0.0
]
]
],
[
[
[
0.0
]
]
]
]
},
"Cos/fc_output_0": {
"scale": 224.00006103515625,
"shift": 0.0
},
"Sin/fc_output_0": {
"scale": 224.00006103515625,
"shift": 0.0
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"Conv/fc_weights_1": {
"scale": [
[
[
[
70510.390625
]
]
],
[
[
[
62825.14453125
]
]
],
[
[
[
61325.73046875
]
]
]
],
"shift": [
[
[
[
0.0
]
]
],
[
[
[
0.0
]
]
],
[
[
[
0.0
]
]
]
]
},
"Cos/fc_output_0": {
"scale": 28672.0078125,
"shift": 0.0
},
"Sin/fc_output_0": {
"scale": 28672.0078125,
"shift": 0.0
}
}
17 changes: 17 additions & 0 deletions tests/openvino/native/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1139,3 +1139,20 @@ def _create_ov_model(self):
result.get_output_tensor(0).set_names(set(["Result"]))
model = ov.Model([result], [input])
return model


class UnifiedScalesModel(OVReferenceModel):
def _create_ov_model(self):
input = opset.parameter([1, 3, 4, 2], name="Input")
multiply = opset.multiply(input, self._rng.random((1, 2)).astype(np.float32), name="Mul")
sin = opset.sin(multiply, name="Sin")
cos = opset.cos(multiply, name="Cos")
concat = opset.concat([sin, cos], axis=0)
kernel = self._rng.random((3, 3, 1, 1)).astype(np.float32)
strides = [1, 1]
pads = [0, 0]
dilations = [1, 1]
conv = opset.convolution(concat, kernel, strides, pads, pads, dilations, name="Conv")
result = opset.result(conv, name="Result")
model = ov.Model([result], [input])
return model
35 changes: 35 additions & 0 deletions tests/openvino/native/quantization/test_fq_params_calculation.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from nncf.common.quantization.structs import QuantizationPreset
from nncf.openvino.graph.nncf_graph_builder import GraphConverter
from nncf.openvino.statistics.aggregator import OVStatisticsAggregator
from nncf.parameters import QuantizationMode
from nncf.quantization.advanced_parameters import OverflowFix
from nncf.quantization.algorithms.min_max.algorithm import MinMaxQuantization
from tests.openvino.native.common import convert_torch_model
Expand All @@ -28,6 +29,7 @@
from tests.openvino.native.models import FPModel
from tests.openvino.native.models import LinearModel
from tests.openvino.native.models import MatMul2DModel
from tests.openvino.native.models import UnifiedScalesModel
from tests.openvino.native.models import WeightsModel
from tests.openvino.native.models import get_torch_model_info
from tests.shared.helpers import compare_stats
Expand All @@ -51,6 +53,14 @@ def get_fq_nodes_stats_algo(model):
"output_low": output_low,
"output_high": output_high,
}
elif op.get_type_name() == "FakeConvert":
scale = op.input_value(1).get_node().data
shift = op.input_value(2).get_node().data

nodes[op.get_friendly_name()] = {
"scale": scale,
"shift": shift,
}
return nodes


Expand Down Expand Up @@ -94,6 +104,31 @@ def test_synthetic_models_fq_scales(model_creator_func, preset, inplace_statisti
compare_stats(ref_nodes, nodes)


@pytest.mark.parametrize(
"mode",
[QuantizationMode.FP8_E4M3, QuantizationMode.FP8_E5M2],
ids=[QuantizationMode.FP8_E4M3.value, QuantizationMode.FP8_E5M2.value],
)
@pytest.mark.parametrize("model_creator_func", [UnifiedScalesModel])
def test_synthetic_models_fc_scales(model_creator_func, mode):
model = model_creator_func()
quantized_model = quantize_model(model.ov_model, {"mode": mode})
real_nodes = [op for op in quantized_model.get_ops() if op.get_type_name() == "FakeConvert"]

ref_stats_name = model.ref_graph_name.split(".")[0] + f"_{mode.value}.json"
ref_stats_path = get_actual_reference_for_current_openvino(REFERENCE_SCALES_DIR / ref_stats_name)
ref_nodes = load_json(ref_stats_path)

assert len(ref_nodes) == len(real_nodes), "The number of the real FakeConvert nodes is not correct"
stat_nodes = get_fq_nodes_stats_algo(quantized_model)

# Uncomment lines below to generate reference for new models.
# from tests.shared.helpers import dump_to_json
# dump_to_json(ref_stats_path, nodes)

compare_stats(ref_nodes, stat_nodes)


@pytest.mark.parametrize(
"overflow_fix",
[OverflowFix.DISABLE, OverflowFix.ENABLE, OverflowFix.FIRST_LAYER],
Expand Down

0 comments on commit 8634037

Please sign in to comment.