@@ -179,7 +179,7 @@ def test_get_tensors_to_cast(simple_model, keep_io_types, low_precision_type):
179179 )
180180
181181 # Test when relu node is in low precision
182- cast_down , cast_up = converter ._get_tensors_to_cast (["relu" ])
182+ cast_down , cast_up , _ = converter ._get_tensors_to_cast (["relu" ])
183183 assert "add_output" in cast_down # Input to relu should be cast down
184184 assert "Y" in cast_up # Output of relu should be cast up
185185 if not keep_io_types :
@@ -188,7 +188,7 @@ def test_get_tensors_to_cast(simple_model, keep_io_types, low_precision_type):
188188 ) # Input to gemm should be cast up, because network input are converted to FP16
189189
190190 # Test when add node is in low precision
191- cast_down , cast_up = converter ._get_tensors_to_cast (["add" ])
191+ cast_down , cast_up , _ = converter ._get_tensors_to_cast (["add" ])
192192 assert "gemm_output" in cast_down # Input to add should be cast down
193193 assert "add_init" not in cast_down # Initializer should not be in cast list
194194 assert "add_output" in cast_up # Output of add should be cast up
@@ -314,13 +314,13 @@ def test_get_tensors_to_cast_multiple_consumers(
314314 )
315315
316316 # Test when gemm2 and add1 nodes are in low precision
317- cast_down , cast_up = converter ._get_tensors_to_cast (["gemm2" , "add1" ])
317+ cast_down , cast_up , _ = converter ._get_tensors_to_cast (["gemm2" , "add1" ])
318318 assert "X" in cast_down # Input to gemm2 should be cast down
319319 assert "gemm2_output" in cast_up # Output of gemm2 should be cast up
320320 assert "Y1" in cast_up # Output of add1 should be cast up
321321
322322 # Test when all nodes except gemm1 are in low precision
323- cast_down , cast_up = converter ._get_tensors_to_cast (["gemm2" , "add1" , "add2" ])
323+ cast_down , cast_up , _ = converter ._get_tensors_to_cast (["gemm2" , "add1" , "add2" ])
324324 assert "gemm1_output" in cast_down # Input to gemm2 should be cast down
325325 assert "Y1" in cast_up # Output of add1 should be cast up
326326 assert "Y2" in cast_up # Output of add2 should be cast up
@@ -1173,3 +1173,154 @@ def test_casted_input_to_output_model(
11731173 high_precision_nodes = ["cast_input" ], low_precision_nodes = ["add1" , "add2" ]
11741174 )
11751175 onnx .checker .check_model (converted_model )
1176+
1177+
1178+ @pytest .fixture
1179+ def create_model_with_resize_op ():
1180+ """
1181+ Creates an ONNX model that contains a resize operation in the middle of the computation flow.
1182+
1183+ The model structure:
1184+ X -> Add -> Resize -> Relu -> Y
1185+ """
1186+ # Create inputs and outputs
1187+ x = helper .make_tensor_value_info ("X" , TensorProto .FLOAT , [1 , 3 , 32 , 32 ])
1188+ y = helper .make_tensor_value_info ("Y" , TensorProto .FLOAT , [1 , 3 , 64 , 64 ])
1189+
1190+ # Create initializer for add operation
1191+ add_const = np .ones ((1 , 3 , 32 , 32 ), dtype = np .float32 )
1192+ add_init = numpy_helper .from_array (add_const , name = "add_const" )
1193+
1194+ # Create resize parameters
1195+ roi_empty = numpy_helper .from_array (np .array ([], dtype = np .float32 ), name = "roi" )
1196+ scales = numpy_helper .from_array (
1197+ np .array ([1.0 , 1.0 , 2.0 , 2.0 ], dtype = np .float32 ), name = "scales"
1198+ )
1199+
1200+ # Create nodes: Add -> Resize -> Relu
1201+ add_node = helper .make_node ("Add" , ["X" , "add_const" ], ["add_out" ], name = "add" )
1202+ resize_node = helper .make_node (
1203+ "Resize" , ["add_out" , "roi" , "scales" ], ["resize_out" ], name = "resize" , mode = "nearest"
1204+ )
1205+ relu_node = helper .make_node ("Relu" , ["resize_out" ], ["Y" ], name = "relu" )
1206+
1207+ # Build the graph
1208+ graph = helper .make_graph (
1209+ [add_node , resize_node , relu_node ],
1210+ "model_with_resize" ,
1211+ [x ],
1212+ [y ],
1213+ [add_init , roi_empty , scales ],
1214+ )
1215+
1216+ model = helper .make_model (graph , producer_name = "model_with_resize" )
1217+ model .opset_import [0 ].version = 20
1218+ model .ir_version = 10
1219+ onnx .checker .check_model (model )
1220+
1221+ model = onnx_utils .infer_shapes (model )
1222+ value_info_map , initializer_map , node_to_init_map = utils .setup_mappings (model )
1223+
1224+ return model , value_info_map , initializer_map , node_to_init_map
1225+
1226+
1227+ @pytest .fixture
1228+ def create_model_with_resize_op_tensor_scales ():
1229+ """
1230+ Creates an ONNX model that contains a resize operation where the scales
1231+ are computed from a second network input through an Add operation.
1232+
1233+ The model structure:
1234+ X -> Add -> Resize -> Relu -> Y
1235+ scales_input -> Add -> scales_tensor /
1236+ """
1237+ # Create inputs and outputs
1238+ x = helper .make_tensor_value_info ("X" , TensorProto .FLOAT , [1 , 3 , 32 , 32 ])
1239+ scales_input = helper .make_tensor_value_info ("scales_input" , TensorProto .FLOAT , [4 ])
1240+ y = helper .make_tensor_value_info ("Y" , TensorProto .FLOAT , [1 , 3 , 64 , 64 ])
1241+
1242+ # Create initializers
1243+ add_const = np .ones ((1 , 3 , 32 , 32 ), dtype = np .float32 )
1244+ add_init = numpy_helper .from_array (add_const , name = "add_const" )
1245+
1246+ # Create scales computation initializer (add small offset to input scales)
1247+ scales_offset = np .array (
1248+ [0.0 , 0.0 , 1.0 , 1.0 ], dtype = np .float32
1249+ ) # Will result in [1,1,2,2] when added to [1,1,1,1] input
1250+ scales_offset_init = numpy_helper .from_array (scales_offset , name = "scales_offset" )
1251+
1252+ # Create resize parameters
1253+ roi_empty = numpy_helper .from_array (np .array ([], dtype = np .float32 ), name = "roi" )
1254+
1255+ # Create nodes
1256+ add_node = helper .make_node ("Add" , ["X" , "add_const" ], ["add_out" ], name = "add" )
1257+ scales_add_node = helper .make_node (
1258+ "Add" , ["scales_input" , "scales_offset" ], ["scales_tensor" ], name = "scales_add"
1259+ )
1260+ resize_node = helper .make_node (
1261+ "Resize" , ["add_out" , "roi" , "scales_tensor" ], ["resize_out" ], name = "resize" , mode = "nearest"
1262+ )
1263+ relu_node = helper .make_node ("Relu" , ["resize_out" ], ["Y" ], name = "relu" )
1264+
1265+ # Build the graph
1266+ graph = helper .make_graph (
1267+ [add_node , scales_add_node , resize_node , relu_node ],
1268+ "model_with_resize_tensor_scales" ,
1269+ [x , scales_input ], # Two network inputs
1270+ [y ],
1271+ [add_init , scales_offset_init , roi_empty ],
1272+ )
1273+
1274+ model = helper .make_model (graph , producer_name = "model_with_resize_tensor_scales" )
1275+ model .opset_import [0 ].version = 20
1276+ model .ir_version = 10
1277+ onnx .checker .check_model (model )
1278+
1279+ model = onnx_utils .infer_shapes (model )
1280+ value_info_map , initializer_map , node_to_init_map = utils .setup_mappings (model )
1281+
1282+ return model , value_info_map , initializer_map , node_to_init_map
1283+
1284+
1285+ @pytest .mark .parametrize ("keep_io_types" , [True , False ])
1286+ @pytest .mark .parametrize ("low_precision_type" , ["fp16" , "bf16" ])
1287+ def test_resize_op_initializer_conversion (
1288+ create_model_with_resize_op , keep_io_types , low_precision_type
1289+ ):
1290+ model , value_info_map , initializer_map , node_to_init_map = create_model_with_resize_op
1291+
1292+ converter = PrecisionConverter (
1293+ model ,
1294+ value_info_map ,
1295+ initializer_map ,
1296+ node_to_init_map ,
1297+ keep_io_types = keep_io_types ,
1298+ low_precision_type = low_precision_type ,
1299+ )
1300+ converted_model = converter .convert (
1301+ high_precision_nodes = [], low_precision_nodes = [node .name for node in model .graph .node ]
1302+ )
1303+ onnx .checker .check_model (converted_model )
1304+
1305+
1306+ @pytest .mark .parametrize ("keep_io_types" , [True , False ])
1307+ @pytest .mark .parametrize ("low_precision_type" , ["fp16" , "bf16" ])
1308+ def test_resize_op_tensor_scales_conversion (
1309+ create_model_with_resize_op_tensor_scales , keep_io_types , low_precision_type
1310+ ):
1311+ model , value_info_map , initializer_map , node_to_init_map = (
1312+ create_model_with_resize_op_tensor_scales
1313+ )
1314+
1315+ converter = PrecisionConverter (
1316+ model ,
1317+ value_info_map ,
1318+ initializer_map ,
1319+ node_to_init_map ,
1320+ keep_io_types = keep_io_types ,
1321+ low_precision_type = low_precision_type ,
1322+ )
1323+ converted_model = converter .convert (
1324+ high_precision_nodes = [], low_precision_nodes = [node .name for node in model .graph .node ]
1325+ )
1326+ onnx .checker .check_model (converted_model )
0 commit comments