Skip to content

Commit 349603f

Browse files
[ONNX] Remove names of removed initializers from graph inputs (#3885)
### Changes Fix the `compress_quantize_weights_transformation()` method by removing names of removed initializers from graph inputs.
1 parent a97100c commit 349603f

2 files changed

Lines changed: 46 additions & 10 deletions

File tree

src/nncf/onnx/graph/passes.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ def compress_quantize_weights_transformation(model: onnx.ModelProto):
9595
"""
9696
initializer = {x.name: x for x in model.graph.initializer}
9797
nodes_to_remove = []
98+
removed_initializers = []
9899

99100
version = max(model.opset_import[0].version, 19)
100101
QuantizeLinear = load_op("", "QuantizeLinear", version)
@@ -129,11 +130,19 @@ def compress_quantize_weights_transformation(model: onnx.ModelProto):
129130
block_size = get_node_attr_value(node, "block_size")
130131
y = QuantizeLinear.eval(x, y_scale, y_zero_point, axis=axis, block_size=block_size)
131132

132-
# Update an existing initializer. The new name is the name of the `QuantizeLinear` output.
133+
# Create a new initializer with the `QuantizeLinear` output name
133134
tensor_proto = onnx.numpy_helper.from_array(y, name=node.output[0])
134-
initializer[x_name].CopyFrom(tensor_proto)
135+
# Remove the old initializer
136+
model.graph.initializer.remove(initializer[x_name])
137+
removed_initializers.append(x_name)
138+
# Add the new initializer
139+
model.graph.initializer.append(tensor_proto)
135140

136141
# `QuantizeLinear` and `DequantizeLinear` nodes share initializers on ports 1 and 2,
137142
# so these initializers should not be removed.
138143
for x in nodes_to_remove:
139144
model.graph.node.remove(x)
145+
146+
for inp in list(model.graph.input):
147+
if inp.name in removed_initializers:
148+
model.graph.input.remove(inp)

tests/onnx/quantization/test_ptq_regression.py

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
99
# See the License for the specific language governing permissions and
1010
# limitations under the License.
11+
from dataclasses import dataclass
1112
from pathlib import Path
1213

1314
import numpy as np
@@ -25,21 +26,40 @@
2526

2627
import nncf
2728

29+
30+
@dataclass
31+
class TestModel:
32+
model_url: str
33+
model_name: str
34+
int8_ref_top1: float
35+
num_inputs_initial_model: int
36+
num_inputs_quantized_model: int
37+
38+
def __str__(self) -> str:
39+
return self.model_name
40+
41+
2842
MODELS = [
29-
(
43+
TestModel(
3044
"https://github.com/onnx/models/raw/5faef4c33eba0395177850e1e31c4a6a9e634c82/vision/classification/mobilenet/model/mobilenetv2-12.onnx",
3145
"mobilenetv2-12",
3246
0.7864968152866242,
47+
1,
48+
1,
3349
),
34-
(
50+
TestModel(
3551
"https://github.com/onnx/models/raw/5faef4c33eba0395177850e1e31c4a6a9e634c82/vision/classification/resnet/model/resnet50-v1-7.onnx",
3652
"resnet50-v1-7",
3753
0.8114649681528663,
54+
300,
55+
246,
3856
),
39-
(
57+
TestModel(
4058
"https://github.com/onnx/models/raw/5faef4c33eba0395177850e1e31c4a6a9e634c82/vision/classification/efficientnet-lite4/model/efficientnet-lite4-11.onnx",
4159
"efficientnet-lite4-11",
4260
0.8035668789808917,
61+
1,
62+
1,
4363
),
4464
]
4565

@@ -111,9 +131,9 @@ def res_callback(infer_request: ov.InferRequest, userdata) -> None:
111131
return accuracy_score(predictions, references)
112132

113133

114-
@pytest.mark.parametrize("model_url, model_name, int8_ref_top1", MODELS, ids=[model_name[1] for model_name in MODELS])
115-
def test_compression(tmp_path, model_dir, data_dir, model_url, model_name, int8_ref_top1):
116-
original_model_path = download_model(model_url, model_dir)
134+
@pytest.mark.parametrize("test_model", MODELS, ids=str)
135+
def test_compression(tmp_path, model_dir, data_dir, test_model):
136+
original_model_path = download_model(test_model.model_url, model_dir)
117137
dataset_path = download_dataset(data_dir)
118138

119139
normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
@@ -126,7 +146,9 @@ def test_compression(tmp_path, model_dir, data_dir, model_url, model_name, int8_
126146
transforms.ToTensor(),
127147
normalize,
128148
transforms.Lambda(
129-
lambda images: torch.moveaxis(images, 0, 2) if model_name == "efficientnet-lite4-11" else images
149+
lambda images: torch.moveaxis(images, 0, 2)
150+
if test_model.model_name == "efficientnet-lite4-11"
151+
else images
130152
),
131153
]
132154
),
@@ -142,10 +164,15 @@ def transform_fn(data_item):
142164
images, _ = data_item
143165
return {input_name: images.numpy()}
144166

167+
assert len([inp.name for inp in converted_model.graph.input]) == test_model.num_inputs_initial_model
168+
145169
calibration_dataset = nncf.Dataset(val_loader, transform_fn)
146170
quantized_model = nncf.quantize(converted_model, calibration_dataset)
171+
172+
assert len([inp.name for inp in quantized_model.graph.input]) == test_model.num_inputs_quantized_model
173+
147174
int8_model_path = tmp_path / "quantized_model.onnx"
148175
onnx.save_model(quantized_model, str(int8_model_path))
149176
int8_top1 = validate(int8_model_path, val_loader)
150177
print(f"INT8 metrics = {int8_top1}")
151-
assert abs(int8_top1 - int8_ref_top1) < 3e-3 # 0.03 deviations
178+
assert abs(int8_top1 - test_model.int8_ref_top1) < 3e-3 # 0.03 deviations

0 commit comments

Comments
 (0)