# ref http://192.168.200.1:8088/jiyuan/converter_scripts.git import sys import onnx from tools import other, helper """ Change onnx model from version 1.3 to version 1.4. - Modify the BN node by removing the spatial attribute - Modify the Upsample node by removing the 'scales' attribute, and adding a constant node instead. - Model's ir_version and opset_import are updated. """ def remove_BN_spatial(g): for node in g.node: if node.op_type != "BatchNormalization": continue for att in node.attribute: if att.name == "spatial": node.attribute.remove(att) def upsample_attribute_to_const(g): for node in g.node: if node.op_type != "Upsample": continue scales_exist = False for att in node.attribute: if att.name == "scales": scales_exist = True break if not scales_exist: continue shape = [len(att.floats)] node.attribute.remove(att) new_node = helper.list_to_constant( node.name + "_input", shape, att.floats ) g.node.extend([new_node]) value_info = onnx.helper.make_tensor_value_info( node.name + "_input", onnx.TensorProto.FLOAT, shape ) node.input.extend([node.name + "_input"]) g.value_info.extend([value_info]) def relu6_to_clip(g): for node in g.node: if node.op_type != "Relu": continue max_val = helper.get_var_attribute_by_name(node, "max", "float") if max_val is None: continue new_node = onnx.helper.make_node( "Clip", node.input, node.output, name=node.name, max=max_val, min=0.0, ) g.node.remove(node) g.node.extend([new_node]) def PRelu_weight_reshape(g): # For PRelu with single dimension weight. Expand it to 1, x, 1, 1 for node in g.node: if node.op_type != "PRelu": continue slope = helper.find_node_by_output_name(g, node.input[1]) if slope is not None: # Constant node if len(slope.attribute[0].t.dims) != 1: continue slope.attribute[0].t.dims.append(slope.attribute[0].t.dims[0]) slope.attribute[0].t.dims[0] = 1 slope.attribute[0].t.dims.append(1) slope.attribute[0].t.dims.append(1) else: # Initializer for i in g.initializer: if i.name == node.input[1]: slope = i break if len(slope.dims) != 1: continue slope.dims.append(slope.dims[0]) slope.dims[0] = 1 slope.dims.append(1) slope.dims.append(1) input_value = helper.find_input_by_name(g, node.input[1]) new_input = onnx.helper.make_tensor_value_info( node.input[1], input_value.type.tensor_type.elem_type, (1, slope.dims[1], 1, 1), ) g.input.remove(input_value) g.input.append(new_input) value_info = helper.find_value_by_name(g, node.input[1]) if value_info is not None: g.value_info.remove(value_info) def do_convert(m): graph = m.graph # Modify the nodes. remove_BN_spatial(graph) upsample_attribute_to_const(graph) relu6_to_clip(graph) PRelu_weight_reshape(graph) other.topological_sort(graph) # Change model properties. m.ir_version = 4 m.opset_import[0].version = 9 return m if __name__ == "__main__": if len(sys.argv) != 3: print("Usage:{} file_in file_out".format(sys.argv[0])) exit(1) model = onnx.load(sys.argv[1]) graph = model.graph # Modify the nodes. remove_BN_spatial(graph) upsample_attribute_to_const(graph) relu6_to_clip(graph) PRelu_weight_reshape(graph) other.topological_sort(graph) # Change model properties. model.ir_version = 4 model.opset_import[0].version = 9 onnx.save(model, sys.argv[2])