def buildGraph(pbfile, opmap): gdef = tf.GraphDef() gdef.ParseFromString(open(pbfile, 'rb').read()) open('frozen.txt', 'w').write(str(gdef)) def extract(name): n = name # return n n = re.sub(r'^\^', '', n) n = re.sub(r':\d+$', '', n) return n nodedict = OrderedDict() for node in gdef.node: nd = MyGraph.MyNode() nd.name = node.name if node.op in opmap: nd.op = opmap[node.op] else: nd.op = node.op nd.input = node.input nd.attr = node.attr nd.input_norm = [extract(i) for i in node.input] nodedict[extract(node.name)] = nd mygraph = MyGraph(nodedict) mygraph.type = 'tf' return mygraph
def buildGraph(config_path, weights_path): unique_config_file = unique_config_sections(config_path) cfg_parser = configparser.ConfigParser() cfg_parser.read_file(unique_config_file) weights_file = open(weights_path, 'rb') # read out major, minor, revision, net.seen readfile(weights_file, (4*4), 'head') mydict = OrderedDict() # record the output of the original layer mylist = [] count = 4 import queue for _section in cfg_parser.sections(): sec_q = queue.Queue(0) sec_q.put(cfg_parser[_section]) while not sec_q.empty(): sec = sec_q.get() section = sec.name print('Parsing section {}'.format(section)) # this section will can be a subsection if section.startswith('activation') or section.endswith('activation'): activation = sec.get('activation', fallback = 'logistic') if activation == 'linear': pass elif activation == 'linear' or activation == 'leaky' or activation == 'relu': node = MyGraph.MyNode() node.name = section node.op = 'Leaky' if activation == 'linear': node.slope = 1 elif activation == 'leaky': node.slope = 0.1 elif activation == 'relu': node.slope = 0 node.input = [prev_output] node.input_norm = node.input #node.attr = [] mydict[node.name] = node prev_output = node.name # prev_layer_filters no change else: raise ValueError( 'Unknown activation function `{}` in section {}'.format( activation, section)) if section.startswith('activation'): mylist.append(section) elif re.match(r'^(convolutional|depthwise|groupwise)_\d+$', section): if section.startswith('convolutional'): conv = 'conv' filters = sec.getint('filters', fallback = 1) groups = 1 op = 'Conv2D' elif section.startswith('depthwise'): conv = 'dconv' filters = prev_layer_filters multiplier = sec.getint('multiplier', fallback = 1) assert multiplier == 1 groups = filters op = 'DepthwiseConv2dNative' elif section.startswith('groupwise'): conv = 'gconv' filters = sec.getint('filters', fallback=1) groups = sec.getint('groups', fallback = 1) op = 'DepthwiseConv2dNative' size = sec.getint('size', fallback = 1) stride = sec.getint('stride', fallback = 1) pad = sec.getint('pad', fallback = 0) padding = sec.getint('padding', fallback = 0) activation = sec.get('activation', fallback = 'logistic') batch_normalize = sec.getint('batch_normalize', 0) # padding='same' is equivalent to Darknet pad=1 # padding = 'same' if pad == 1 else 'valid' if pad: padding = size//2 # Setting weights. # Darknet serializes convolutional weights as: # [bias/beta, [gamma, mean, variance], conv_weights] #prev_layer_shape = prev_layer.shape # TODO: This assumes channel last dim_ordering. if conv == 'conv': weights_shape = (size, size, prev_layer_filters, filters) idx_tf2darknet = [0, 1, 2, 3] elif conv == 'dconv': weights_shape = (size, size, filters) idx_tf2darknet = [0, 1, 2] elif conv == 'gconv': weights_shape = (size, size, prev_layer_filters//groups, filters//groups, groups) idx_tf2darknet = [0, 1, 2, 3, 4] idxmap = {x: i for i, x in enumerate(idx_tf2darknet)} idx_dartnet2tf = [idxmap[i] for i in range(len(idxmap))] weights_size = np.product(weights_shape) print(' ' + conv, 'bn' if batch_normalize else ' ', activation, weights_shape) conv_bias = np.ndarray( shape=(filters, ), dtype=np.float32, buffer=readfile(weights_file, (filters * 4), section+'-bias')) count += filters if batch_normalize: bn_weights = np.ndarray( shape=(3, filters), dtype=np.float32, buffer=readfile(weights_file, (filters * 12), section+'-batchnorm')) count += 3 * filters # TODO: Keras BatchNormalization mistakenly refers to var # as std. bn_weight_list = [ bn_weights[0], # scale gamma conv_bias, # shift beta bn_weights[1], # running mean bn_weights[2] # running var ] conv_weights = np.ndarray( shape=[weights_shape[i] for i in idx_tf2darknet], dtype=np.float32, buffer=readfile(weights_file, (weights_size * 4), section+'-weights')) count += weights_size # DarkNet conv_weights are serialized Caffe-style: # (out_dim, in_dim, height, width) # We would like to set these to Tensorflow order: # (height, width, in_dim, out_dim) # TODO: Add check for Theano dim ordering. #print("the darknet shape is ", conv_weights.shape) conv_weights = np.transpose(conv_weights, idx_dartnet2tf) #print("the tf shape is ", conv_weights.shape) conv_weights = [conv_weights] if batch_normalize else [ conv_weights, conv_bias ] # Create nodes #conv_layer = np.zeros([1, 1, filters], dtype = np.float32) node = MyGraph.MyNode() node.name = section node.op = op node.input = [prev_output] node.input_norm = node.input node.kernel = conv_weights[0] node.padding = padding node.strides = [1,stride,stride,1] node.groups = groups node.filters = filters mydict[node.name] = node prev_output = node.name prev_layer_filters = filters if batch_normalize: node = MyGraph.MyNode() node.name = section + '_batch_normalize' node.op = 'FusedBatchNorm' node.input = [prev_output] node.input_norm = node.input #node.attr = [] node.gamma = bn_weights[0] node.beta = conv_bias node.mean = bn_weights[1] node.variance = bn_weights[2] mydict[node.name] = node prev_output = node.name # prev_layer_filters no change else: node = MyGraph.MyNode() node.name = section + '_bias' node.op = 'BiasAdd' node.input = [prev_output] node.input_norm = node.input #node.attr = [] node.bias = conv_bias mydict[node.name] = node prev_output = node.name if activation == 'linear': mylist.append(prev_output) else: tmp_parser = configparser.ConfigParser() name = section + '_activation' tmp_parser.add_section(name) tmp_parser.set(name, 'activation', activation) sec_q.put(tmp_parser[name]) mylist.append(name) elif section.startswith('shuffle'): node = MyGraph.MyNode() node.name = section node.op = 'Shuffle' node.input = [prev_output] node.input_norm = node.input node.groups = int(cfg_parser[section]['groups']) mydict[node.name] = node prev_output = node.name mylist.append(section) elif re.match(r'^(pooling|maxpool|avgpool)_\d+$', section): node = MyGraph.MyNode() node.stride = sec.getint('stride', fallback = 1) node.size = sec.getint('size', node.stride) node.padding = sec.getint('padding', fallback = (node.size-1)//2) if section.startswith('pooling'): node.mode = str(cfg_parser[section]['mode']) node.global_pooling = 0 elif section.startswith('maxpool'): node.mode = 'max' node.global_pooling = 0 elif section.startswith('avgpool'): node.mode = 'avg' node.global_pooling = 1 node.name = section node.op = 'Pooling' node.input = [prev_output] node.input_norm = node.input mydict[node.name] = node prev_output = node.name #print('pooling ', vars(node)) mylist.append(section) elif section.startswith('route'): ids = [int(i) for i in cfg_parser[section]['layers'].split(',')] node = MyGraph.MyNode() node.name = section node.op = 'NCNNConcat' node.input = [mylist[i] for i in ids] #print('mylist is ', mylist, 'the ids is ', ids, 'node input is ', node.input) node.input_norm = node.input node.axis = 0 node.filters = sum([getFilters(mydict, mylist[i]) for i in ids]) mydict[node.name] = node prev_output = node.name mylist.append(section) prev_layer_filters = node.filters elif section.startswith('reorg'): node = MyGraph.MyNode() node.name = section node.op = 'DarknetReorg' node.input = [prev_output] node.stride = sec.getint('stride', fallback = 1) node.input_norm = node.input node.filters = getFilters(mydict, node.input[0]) * node.stride * node.stride mydict[node.name] = node prev_output = node.name mylist.append(section) prev_layer_filters = node.filters elif re.match(r'^(shortcut)_\d+$', section): activation = sec.get('activation', fallback = 'logistic') from_ = sec.getint('from') node = MyGraph.MyNode() node.name = section node.op = 'BinaryOp' node.op_type = 0 node.input = [prev_output, mylist[from_]] #print('mylist is ', mylist, 'the from_ is ', from_, 'node input is ', node.input) node.input_norm = node.input mydict[node.name] = node prev_output = node.name if activation == 'linear': mylist.append(prev_output) else: tmp_parser = configparser.ConfigParser() name = section + '_activation' tmp_parser.add_section(name) tmp_parser.set(name, 'activation', activation) sec_q.put(tmp_parser[name]) # NOTE: this section has relative reference mylist.append(name) elif section.startswith('connected'): activation = sec.get('activation', fallback='linear') filters = sec.getint('output', 2) bias_data = np.ndarray( shape=[filters], dtype=np.float32, buffer=readfile(weights_file, (filters * 4), section+'-bias')) fc_data = np.ndarray( shape=[prev_layer_filters, filters], dtype=np.float32, buffer=readfile(weights_file, (prev_layer_filters * filters * 4), section+'-weight')) node = MyGraph.MyNode() node.name = section node.op = 'MatMul' node.input = [prev_output] node.input_norm = node.input node.multiplier = fc_data mydict[node.name] = node prev_output = node.name prev_layer_filters = filters node = MyGraph.MyNode() node.name = section + '_bias' node.op = 'BiasAdd' node.input = [prev_output] node.input_norm = node.input # node.attr = [] node.bias = bias_data mydict[node.name] = node prev_output = node.name if activation == 'linear': mylist.append(prev_output) else: tmp_parser = configparser.ConfigParser() name = section + '_activation' tmp_parser.add_section(name) tmp_parser.set(name, 'activation', activation) sec_q.put(tmp_parser[name]) mylist.append(name) elif section.startswith('net'): node = MyGraph.MyNode() node.name = section node.op = 'DarknetNet' node.input = [] node.input_norm = [] node.width = int(cfg_parser['net_0']['width']) node.height = int(cfg_parser['net_0']['height']) node.channels = int(cfg_parser['net_0']['channels']) node.filters = node.channels # print(vars(node)) # node.attr = [] mydict[node.name] = node # start here prev_output = node.name prev_layer_filters = node.channels mylist.append(section) elif section.startswith('region'): node = MyGraph.MyNode() node.name = section node.op = 'DarknetRegion' node.input = [prev_output] node.input_norm = node.input node.classes = int(cfg_parser[section]['classes']) node.num = int(cfg_parser[section]['num']) node.softmax = int(cfg_parser[section]['softmax']) node.anchors = [float(i) for i in re.split(r',', cfg_parser[section]['anchors'])] #print(vars(node)) #node.attr = [] mydict[node.name] = node prev_output = node.name mylist.append(section) elif section.startswith('softmax'): node = MyGraph.MyNode() node.name = section node.op = 'Softmax' node.input = [prev_output] node.input_norm = node.input mydict[node.name] = node prev_output = node.name mylist.append(section) pass elif section.startswith('cost'): pass # Configs not currently handled during model definition. else: raise ValueError( 'Unsupported section header type: {}'.format(section)) print(' out filters ', prev_layer_filters) print('loaded {} bytes in weights file'.format(count*4)) mygraph = MyGraph(mydict) mygraph.type = 'darknet' return mygraph