in tools/importers/darknet/darknet_to_ell.py [0:0]
def parse_cfg(filename):
"""Parses a Darknet .cfg file and returns a list of layers. Each layer has
properties denoting type, shape of input and outputs, padding requirements
and anything else needed to construct up the relevant ELL layers"""
with open(filename) as f:
content = f.read()
class DarknetConfigDict(OrderedDict):
def __init__(self, **kwargs):
OrderedDict.__init__(self, **kwargs)
self.__keysuffixes = {}
def __setitem__(self, key, value):
if isinstance(value, dict):
suffix = self.__keysuffixes.setdefault(key, 0)
self.__keysuffixes[key] += 1
key += "_" + str(suffix)
OrderedDict.__setitem__(self, key, value)
config = ConfigParser(dict_type=DarknetConfigDict, strict=False)
config.read_string(content)
network = []
for section in config._sections:
layer_desc = {'type': section[:section.rfind('_')]}
layer_desc.update(config._sections[section])
network.append(layer_desc)
def print_layer(layer):
_logger = logger.get()
PRETTY_TYPE_MAP = {
"convolutional": "BinaryConvolution" if layer.get("xnor") == 1 else
"Convolution",
"connected": "FullyConnected",
"maxpool": "MaxPooling",
"avgpool": "AveragePooling",
"softmax": "Softmax",
"region": "RegionDetection"
}
pretty_type = PRETTY_TYPE_MAP.get(layer.get("type"))
if not pretty_type:
return
_logger.info(("{} : {h}x{w}x{c} -> {out_h}x{out_w}x{out_c}"
" | input padding {inputPadding} output padding {outputPadding}"
).format(pretty_type, **layer))
# add extra information needed, size calculations and properties like padding
for i, layer in enumerate(network):
if layer['type'] == 'net':
layer['h'] = int(layer['height'])
layer['w'] = int(layer['width'])
layer['c'] = int(layer['channels'])
layer['out_h'] = int(layer['height'])
layer['out_w'] = int(layer['width'])
layer['out_c'] = int(layer['channels'])
elif layer['type'] == 'crop':
layer['c'] = network[i - 1]['out_c']
layer['h'] = network[i - 1]['out_h']
layer['w'] = network[i - 1]['out_w']
layer['out_h'] = layer['crop_height']
layer['out_w'] = layer['crop_width']
layer['out_c'] = network[i - 1]['out_c']
elif layer['type'] == 'convolutional':
if 'pad' not in layer:
layer['pad'] = 0
layer['padding'] = 0
elif 'padding' not in layer:
if ('pad' in layer):
if (int(layer['pad']) == 0):
layer['padding'] = 0
else:
layer['padding'] = int((int(layer['size']) - 1) / 2)
else:
layer['padding'] = int((int(layer['size']) - 1) / 2)
layer['h'] = int(network[i - 1]['out_h'])
layer['w'] = int(network[i - 1]['out_w'])
layer['c'] = int(network[i - 1]['out_c'])
layer['out_h'] = int(convolutional_out_height(layer))
layer['out_w'] = int(convolutional_out_width(layer))
layer['out_c'] = int(layer['filters'])
elif layer['type'] == 'connected':
layer['h'] = network[i - 1]['out_h']
layer['w'] = network[i - 1]['out_w']
layer['c'] = network[i - 1]['out_c']
layer['inputs'] = int(layer['h']) * int(layer['w']) * int(layer['c'])
layer['out_w'] = 1
layer['out_h'] = 1
layer['out_c'] = int(layer['output'])
elif layer['type'] == 'maxpool':
if 'padding' not in layer:
layer['padding'] = int((int(layer['size']) - 1) / 2)
layer['h'] = int(network[i - 1]['out_h'])
layer['w'] = int(network[i - 1]['out_w'])
layer['c'] = int(network[i - 1]['out_c'])
layer['out_h'] = int(((int(layer['h'])) + 2 * int(layer['padding'])) / int(layer['stride']))
layer['out_w'] = int(((int(layer['w'])) + 2 * int(layer['padding'])) / int(layer['stride']))
layer['out_c'] = layer['c']
elif layer['type'] == 'avgpool':
layer['c'] = network[i - 1]['out_c']
layer['out_c'] = layer['c']
layer['out_h'] = 1
layer['out_w'] = 1
layer['h'] = network[i - 1]['out_h']
layer['w'] = network[i - 1]['out_w']
layer['padding'] = 0
# Darknet's average pooling is across an entire layer. Fix up stride and size so ELL can behave that way.
layer['size'] = layer["w"]
layer['stride'] = layer["w"]
elif layer['type'] == 'softmax':
layer['c'] = network[i - 1]['out_c']
layer['h'] = network[i - 1]['out_h']
layer['w'] = network[i - 1]['out_w']
layer['out_c'] = layer['c']
layer['out_h'] = layer['h']
layer['out_w'] = layer['w']
elif layer['type'] == 'region':
layer['c'] = network[i - 1]['out_c']
layer['h'] = network[i - 1]['out_h']
layer['w'] = network[i - 1]['out_w']
layer['out_c'] = network[i - 1]['out_c']
layer['out_h'] = network[i - 1]['out_h']
layer['out_w'] = network[i - 1]['out_w']
else:
layer['c'] = network[i - 1]['out_c']
layer['h'] = network[i - 1]['out_h']
layer['w'] = network[i - 1]['out_w']
layer['out_c'] = network[i - 1]['out_c']
layer['out_h'] = network[i - 1]['out_h']
layer['out_w'] = network[i - 1]['out_w']
# Do another pass, setting input/output shape and outpadding to next layer's padding
# Set the ELL padding scheme and shape parameters
for i, layer in enumerate(network):
if 'padding' not in layer:
layer['inputPadding'] = 0
if layer['type'] == 'maxpool':
layer['inputPaddingScheme'] = ell.neural.PaddingScheme.min
else:
layer['inputPaddingScheme'] = ell.neural.PaddingScheme.zeros
else:
layer['inputPadding'] = int(layer['padding'])
if layer['type'] == 'maxpool':
layer['inputPaddingScheme'] = ell.neural.PaddingScheme.min
else:
layer['inputPaddingScheme'] = ell.neural.PaddingScheme.zeros
layer['inputShape'] = ell.math.TensorShape(
int(layer['h']) + 2 * int(layer['inputPadding']),
int(layer['w']) + 2 * int(layer['inputPadding']),
int(layer['c']))
if i < (len(network) - 1):
nextLayer = network[i + 1]
if 'padding' not in nextLayer:
layer['outputPadding'] = 0
else:
layer['outputPadding'] = int(nextLayer['padding'])
if nextLayer['type'] == 'maxpool':
layer['outputPaddingScheme'] = ell.neural.PaddingScheme.min
else:
layer['outputPaddingScheme'] = ell.neural.PaddingScheme.zeros
layer['outputShape'] = ell.math.TensorShape(
int(layer['out_h']) + 2 * int(layer['outputPadding']),
int(layer['out_w']) + 2 * int(layer['outputPadding']),
int(layer['out_c']))
layer['outputShapeMinusPadding'] = ell.math.TensorShape(
int(layer['out_h']),
int(layer['out_w']),
int(layer['out_c']))
else:
layer['outputPadding'] = 0
layer['outputPaddingScheme'] = ell.neural.PaddingScheme.zeros
layer['outputShape'] = ell.math.TensorShape(int(layer['out_h']), int(layer['out_w']), int(layer['out_c']))
layer['outputShapeMinusPadding'] = ell.math.TensorShape(
int(layer['out_h']),
int(layer['out_w']),
int(layer['out_c']))
print_layer(layer)
return network