from .src.graph_pb2 import GraphDef from .src.node_def_pb2 import NodeDef from .src.versions_pb2 import VersionDef from .src.attr_value_pb2 import AttrValue from .src.tensor_shape_pb2 import TensorShapeProto # from .src.onnx_pb2 import ModelProto def gg(fname): import onnx # 0.2.1 m = onnx.load(fname) nodes_proto = [] nodes = [] g = m.graph import itertools for node in itertools.chain(g.input, g.output): nodes_proto.append(node) for node in nodes_proto: shapeproto = TensorShapeProto( dim=[TensorShapeProto.Dim(size=d.dim_value) for d in node.type.tensor_type.shape.dim]) nodes.append(NodeDef( name=node.name, op='Variable', input=[], attr={ 'dtype': AttrValue(type=node.type.tensor_type.elem_type), 'shape': AttrValue(shape=shapeproto), }) ) for node in g.node: attr = [] for s in node.attribute: attr.append(' = '.join([str(f[1]) for f in s.ListFields()])) attr = ', '.join(attr).encode(encoding='utf_8') nodes.append(NodeDef( name=node.output[0], op=node.op_type, input=node.input, attr={'parameters': AttrValue(s=attr)}, )) # two pass token replacement, appends opname to object id mapping = {} for node in nodes: mapping[node.name] = node.op + '_' + node.name nodes, mapping = updatenodes(nodes, mapping) mapping = smartGrouping(nodes, mapping) nodes, mapping = updatenodes(nodes, mapping) return GraphDef(node=nodes, versions=VersionDef(producer=22)) def updatenodes(nodes, mapping): for node in nodes: newname = mapping[node.name] node.name = newname newinput = [] for inputnode in list(node.input): newinput.append(mapping[inputnode]) node.input.remove(inputnode) node.input.extend(newinput) newmap = {} for k, v in mapping.items(): newmap[v] = v return nodes, newmap def findnode(nodes, name): """ input: node name returns: node object """ for n in nodes: if n.name == name: return n def parser(s, nodes, node): print(s) if len(s) == 0: return if len(s) > 0: if s[0] == node.op: print(s[0], node.name, s[1], node.input) for n in node.input: print(n, s[1]) parser(s[1], nodes, findnode(nodes, n)) else: return False # TODO: use recursive parse def smartGrouping(nodes, mapping): # a Fully Conv is: (TODO: check var1.size(0)==var2.size(0)) # GEMM <-- Variable (c1) # ^-- Transpose (c2) <-- Variable (c3) # a Conv with bias is: (TODO: check var1.size(0)==var2.size(0)) # Add <-- Conv (c2) <-- Variable (c3) # ^-- Variable (c1) # # gemm = ('Gemm', ('Variable', ('Transpose', ('Variable')))) FCcounter = 1 Convcounter = 1 for node in nodes: if node.op == 'Gemm': c1 = c2 = c3 = False for name_in in node.input: n = findnode(nodes, name_in) if n.op == 'Variable': c1 = True c1name = n.name if n.op == 'Transpose': c2 = True c2name = n.name if len(n.input) == 1: nn = findnode(nodes, n.input[0]) if nn.op == 'Variable': c3 = True c3name = nn.name # print(n.op, n.name, c1, c2, c3) if c1 and c2 and c3: # print(c1name, c2name, c3name) mapping[c1name] = 'FC{}/{}'.format(FCcounter, c1name) mapping[c2name] = 'FC{}/{}'.format(FCcounter, c2name) mapping[c3name] = 'FC{}/{}'.format(FCcounter, c3name) mapping[node.name] = 'FC{}/{}'.format(FCcounter, node.name) FCcounter += 1 continue if node.op == 'Add': c1 = c2 = c3 = False for name_in in node.input: n = findnode(nodes, name_in) if n.op == 'Variable': c1 = True c1name = n.name if n.op == 'Conv': c2 = True c2name = n.name if len(n.input) >= 1: for nn_name in n.input: nn = findnode(nodes, nn_name) if nn.op == 'Variable': c3 = True c3name = nn.name if c1 and c2 and c3: # print(c1name, c2name, c3name) mapping[c1name] = 'Conv{}/{}'.format(Convcounter, c1name) mapping[c2name] = 'Conv{}/{}'.format(Convcounter, c2name) mapping[c3name] = 'Conv{}/{}'.format(Convcounter, c3name) mapping[node.name] = 'Conv{}/{}'.format(Convcounter, node.name) Convcounter += 1 return mapping