def create_frcn_model(frcn_fine_tune=False): b1 = BranchNode(name="b1") imagenet_layers = add_vgg_layers() HW = (7, 7) frcn_layers = [ RoiPooling(layers=imagenet_layers, HW=HW, bprop_enabled=frcn_fine_tune), Affine(nout=4096, init=Gaussian(scale=0.005), bias=Constant(.1), activation=Rectlin()), Dropout(keep=0.5), Affine(nout=4096, init=Gaussian(scale=0.005), bias=Constant(.1), activation=Rectlin()), Dropout(keep=0.5), b1, Affine(nout=21, init=Gaussian(scale=0.01), bias=Constant(0), activation=Softmax()) ] bb_layers = [ b1, Affine(nout=84, init=Gaussian(scale=0.001), bias=Constant(0), activation=Identity()) ] return Model(layers=Tree([frcn_layers, bb_layers]))
def __init__(self): self.in_shape = (1, 32, 32) init_norm = Gaussian(loc=0.0, scale=0.01) normrelu = dict(init=init_norm, activation=Rectlin()) normsigm = dict(init=init_norm, activation=Logistic(shortcut=True)) normsoft = dict(init=init_norm, activation=Softmax()) # setup model layers b1 = BranchNode(name="b1") b2 = BranchNode(name="b2") p1 = [ Affine(nout=100, name="main1", **normrelu), b1, Affine(nout=32, name="main2", **normrelu), Affine(nout=160, name="main3", **normrelu), b2, Affine(nout=32, name="main2", **normrelu), # make next layer big to check sizing Affine(nout=320, name="main2", **normrelu), Affine(nout=10, name="main4", **normsoft) ] p2 = [ b1, Affine(nout=16, name="branch1_1", **normrelu), Affine(nout=10, name="branch1_2", **normsigm) ] p3 = [ b2, Affine(nout=16, name="branch2_1", **normrelu), Affine(nout=10, name="branch2_2", **normsigm) ] self.cost = Multicost(costs=[ GeneralizedCost(costfunc=CrossEntropyMulti()), GeneralizedCost(costfunc=CrossEntropyBinary()), GeneralizedCost(costfunc=CrossEntropyBinary()) ], weights=[1, 0., 0.]) self.layers = SingleOutputTree([p1, p2, p3], alphas=[1, .2, .2]) self.model = Model(layers=self.layers) self.model.initialize(self.in_shape, cost=self.cost)
def __init__(self, overlapping_classes=None, exclusive_classes=None, analytics_input=True, network_type='conv_net', num_words=60, width=100, lookup_size=0, lookup_dim=0, optimizer=Adam()): assert (overlapping_classes is not None) or (exclusive_classes is not None) self.width = width self.num_words = num_words self.overlapping_classes = overlapping_classes self.exclusive_classes = exclusive_classes self.analytics_input = analytics_input self.recurrent = network_type == 'lstm' self.lookup_size = lookup_size self.lookup_dim = lookup_dim init = GlorotUniform() activation = Rectlin(slope=1E-05) gate = Logistic() input_layers = self.input_layers(analytics_input, init, activation, gate) if self.overlapping_classes is None: output_layers = [ Affine(len(self.exclusive_classes), init, activation=Softmax()) ] elif self.exclusive_classes is None: output_layers = [ Affine(len(self.overlapping_classes), init, activation=Logistic()) ] else: output_branch = BranchNode(name='exclusive_overlapping') output_layers = Tree([[ SkipNode(), output_branch, Affine(len(self.exclusive_classes), init, activation=Softmax()) ], [ output_branch, Affine(len(self.overlapping_classes), init, activation=Logistic()) ]]) layers = [ input_layers, # this is where inputs meet, and where we may want to add depth or # additional functionality Dropout(keep=0.8), output_layers ] super(ClassifierNetwork, self).__init__(layers, optimizer=optimizer)
def make_tree(trunk, branch1, branch2, alphas): # Make one copy that is the Tree version _trunk = [l['layer'](**l['config']) for l in trunk] bnode = [BranchNode(name='bnode')] _branch1 = [l['layer'](**l['config']) for l in branch1] _branch2 = [l['layer'](**l['config']) for l in branch2] v1 = Tree([_trunk + bnode + _branch1, bnode + _branch2], alphas) # Now a second copy with no sharing as the reference version _trunkb = [l['layer'](**l['config']) for l in trunk] _branch1b = [l['layer'](**l['config']) for l in branch1] _branch2b = [l['layer'](**l['config']) for l in branch2] return (v1, _trunkb, _branch1b, _branch2b)
def create_normalize_branch(self, leafs, branch_node, layer): """ Append leafs to trunk_layers at the branch_node. If normalize, add a Normalize layer. """ tree_branch = BranchNode(name=layer + '_norm_branch') branch1 = [ Normalize(init=Constant(20.0), name=layer + '_norm'), tree_branch, leafs['mbox_loc'] ] branch2 = [tree_branch, leafs['mbox_conf']] new_tree = Tree([branch1, branch2]) return [branch_node, new_tree]
(X_train, y_train), (X_test, y_test), nclass = load_mnist(path=args.data_dir) # setup a training set iterator train_set = DataIterator(X_train, y_train, nclass=nclass) # setup a validation data set iterator valid_set = DataIterator(X_test, y_test, nclass=nclass) # setup weight initialization function init_norm = Gaussian(loc=0.0, scale=0.01) normrelu = dict(init=init_norm, activation=Rectlin()) normsigm = dict(init=init_norm, activation=Logistic(shortcut=True)) normsoft = dict(init=init_norm, activation=Softmax()) # setup model layers b1 = BranchNode(name="b1") b2 = BranchNode(name="b2") p1 = [Affine(nout=100, linear_name="m_l1", **normrelu), b1, Affine(nout=32, linear_name="m_l2", **normrelu), Affine(nout=16, linear_name="m_l3", **normrelu), b2, Affine(nout=10, linear_name="m_l4", **normsoft)] p2 = [b1, Affine(nout=16, linear_name="b1_l1", **normrelu), Affine(nout=10, linear_name="b1_l2", **normsigm)] p3 = [b2,
def build_model(dataset, frcn_rois_per_img, train_pre_nms_N=12000, train_post_nms_N=2000, test_pre_nms_N=6000, test_post_nms_N=300, inference=False): """ Returns the Faster-RCNN model. For inference, also returns a reference to the proposal layer. Faster-RCNN contains three modules: VGG, the Region Proposal Network (RPN), and the Classification Network (ROI-pooling + Fully Connected layers), organized as a tree. Tree has 4 branches: VGG -> b1 -> Conv (3x3) -> b2 -> Conv (1x1) -> CrossEntropyMulti (objectness label) b2 -> Conv (1x1) -> SmoothL1Loss (bounding box targets) b1 -> PropLayer -> ROI -> Affine -> Affine -> b3 -> Affine -> CrossEntropyMulti b3 -> Affine -> SmoothL1Loss When the model is constructed for inference, several elements are different: - The number of regions to keep before and after non-max suppression is (6000, 300) for training and (12000, 2000) for inference. - The out_shape of the proposalLayer of the network is equal to post_nms_N (number of rois to keep after performaing nms). This is configured by passing the inference flag to the proposalLayer constructor. Arguments: dataset (objectlocalization): Dataset object. frcn_rois_per_img (int): Number of ROIs per image considered by the classification network. inference (bool): Construct the model for inference. Default is False. Returns: model (Model): Faster-RCNN model. proposalLayer (proposalLayer): Reference to proposalLayer in the model. Returned only for inference=True. """ num_classes = dataset.num_classes # define the branch points b1 = BranchNode(name="conv_branch") b2 = BranchNode(name="rpn_branch") b3 = BranchNode(name="roi_branch") # define VGG VGG = util.add_vgg_layers() # define RPN rpn_init = dict(strides=1, init=Gaussian(scale=0.01), bias=Constant(0)) # these references are passed to the ProposalLayer. RPN_3x3 = Conv((3, 3, 512), activation=Rectlin(), padding=1, **rpn_init) RPN_1x1_obj = Conv((1, 1, 18), activation=PixelwiseSoftmax(c=2), padding=0, **rpn_init) RPN_1x1_bbox = Conv((1, 1, 36), activation=Identity(), padding=0, **rpn_init) # inference uses different network settings if not inference: pre_nms_N = train_pre_nms_N # default 12000 post_nms_N = train_post_nms_N # default 2000 else: pre_nms_N = test_pre_nms_N # default 6000 post_nms_N = test_post_nms_N # default 300 proposalLayer = ProposalLayer([RPN_1x1_obj, RPN_1x1_bbox], dataset, pre_nms_N=pre_nms_N, post_nms_N=post_nms_N, num_rois=frcn_rois_per_img, inference=inference) # define ROI classification network ROI = [ proposalLayer, RoiPooling(HW=(7, 7)), Affine(nout=4096, init=Gaussian(scale=0.005), bias=Constant(.1), activation=Rectlin()), Dropout(keep=0.5), Affine(nout=4096, init=Gaussian(scale=0.005), bias=Constant(.1), activation=Rectlin()), Dropout(keep=0.5) ] ROI_category = Affine(nout=num_classes, init=Gaussian(scale=0.01), bias=Constant(0), activation=Softmax()) ROI_bbox = Affine(nout=4 * num_classes, init=Gaussian(scale=0.001), bias=Constant(0), activation=Identity()) # build the model # the four branches of the tree mirror the branches listed above frcn_tree = Tree([ROI + [b3, ROI_category], [b3, ROI_bbox]]) model = Model(layers=Tree([ VGG + [b1, RPN_3x3, b2, RPN_1x1_obj], [b2, RPN_1x1_bbox], [b1] + [frcn_tree], ])) if inference: return (model, proposalLayer) else: return model
# setup cost function as CrossEntropy cost = Multicost( costs=[ GeneralizedCost(costfunc=CrossEntropyMulti()), GeneralizedCost(costfunc=CrossEntropyMulti()), GeneralizedCost(costfunc=CrossEntropyMulti()) ], weights=[1, 0., 0.]) # We only want to consider the CE of the main path if not args.resume: # build the model from scratch and run it # Now construct the model branch_nodes = [BranchNode(name='branch{}'.format(i)) for i in (0, 1)] main1 = main_branch(branch_nodes) aux1 = aux_branch(branch_nodes[0], ind=1) aux2 = aux_branch(branch_nodes[1], ind=2) model = Model(layers=Tree([main1, aux1, aux2], alphas=[1.0, 0.3, 0.3])) else: # load up the save model model = Model('serialize_test_2.pkl') model.initialize(train, cost=cost) # configure callbacks callbacks = Callbacks(model, progress_bar=True, output_file='temp1.h5',
# setup backend be = gen_backend(**extract_valid_args(args, gen_backend)) # setup training dataset train_set = PASCALVOC('trainval', '2007', path=args.data_dir, output_type=0, n_mb=n_mb, img_per_batch=img_per_batch, rois_per_img=rois_per_img) # setup layers b1 = BranchNode(name="b1") imagenet_layers = [ Conv((11, 11, 64), init=Gaussian(scale=0.01), bias=Constant(0), activation=Rectlin(), padding=3, strides=4), Pooling(3, strides=2), Conv((5, 5, 192), init=Gaussian(scale=0.01), bias=Constant(1), activation=Rectlin(), padding=2), Pooling(3, strides=2),
def test_branch_model_fork(): from neon.layers import BranchNode, Tree NervanaObject.be = gen_backend("gpu", batch_size=64) be = NervanaObject.be bnode = BranchNode() i1 = inception([(32, ), (32, 32), ('max', 16)]) top1 = top_branch() top2 = top_branch() p1 = Sequential(main_branch() + [bnode, i1] + top1) p2 = [bnode] + top2 alpha2 = 0.3 neon_layer = Tree([p1, p2], alphas=[1.0, alpha2]) inshape = (3, 224, 224) insize = np.prod(inshape) inpa = np.random.random((insize, batch_size)) neon_layer.configure(inshape) inp = neon_layer.be.array(inpa) neon_layer.allocate() print neon_layer.nested_str() neon_layer.layers[0].layers[0].prev_layer = True neon_layer.allocate_deltas() neon_layer.layers[0].layers[0].set_deltas([be.iobuf(inshape)]) neon_out_dev = neon_layer.fprop(inp) neon_out = [d.get() for d in neon_out_dev] # Now make the reference pathways: main_trunk2 = Sequential(main_branch()) main_trunk2.configure(inshape) main2 = main_trunk2.layers main2[0].prev_layer = True main2[0].set_deltas([be.iobuf(inshape)]) branch2 = Sequential(top_branch()) lbranch2 = branch2.layers (b1, b2, b3) = inception_bare(i1, [(32, ), (32, 32), ('max', 16)]) for bb in (b1, b2, b3, lbranch2): oshape = inshape for ll in main2 + bb: oshape = ll.configure(oshape) main1_trunk = neon_layer.layers[0].layers[:8] for ll, lo in zip(main2, main1_trunk): if ll.has_params: ll.set_params({'params': {'W': lo.W.get()}}) ll.allocate() ll.set_deltas([be.iobuf(ll.in_shape)]) for ll, lo in zip(lbranch2, neon_layer.layers[1].layers[1:]): if ll.has_params: ll.set_params({'params': {'W': lo.W.get()}}) for bb in (b1, b2, b3, lbranch2): for ll in bb: ll.allocate() ll.set_deltas([be.iobuf(ll.in_shape)]) # Create the combined output buffer merge_output = be.empty_like(neon_layer.layers[0].layers[9].outputs) x = inp for ll in main2: x = ll.fprop(x) main2_out = x start = 0 for bb in (b1, b2, b3): xb = main2_out for ll in bb: xb = ll.fprop(xb) end = start + xb.shape[0] merge_output[start:end] = xb start = end x = merge_output top_trunk = Sequential(top1).layers for ll in top_trunk: x = ll.fprop(x) neon_out_ref = x.get() difference = neon_out_ref - neon_out[0] assert np.max(np.abs(difference)) < 1e-7 print np.max(np.abs(difference)) # Now do second branch neon_out_ref2 = branch2.fprop(main2_out).get() difference = neon_out_ref2 - neon_out[1] assert np.max(np.abs(difference)) < 1e-7 print np.max(np.abs(difference)) print "Beginning Back prop" erra = [np.random.random(d.shape) for d in neon_out] err = [be.array(d) for d in erra] neon_layer.layers[0].layers[0].deltas = be.iobuf(inshape) neon_layer.bprop(err) bottom_neon_deltas = neon_layer.layers[0].layers[1].deltas.get() middle_neon_deltas = neon_layer.layers[1].layers[1].deltas.get() err0 = err[0] for ll in reversed(top_trunk): err0 = ll.bprop(err0) err1 = err[1] for ll in reversed(lbranch2): err1 = ll.bprop(err1) for bb, errb in zip((b1, b2, b3), neon_layer.layers[0].layers[-5].error_views): for ll in reversed(bb): errb = ll.bprop(errb) # Now sum up the deltas at the root of the branch layer and compare ref_deltas = be.zeros_like(b1[0].deltas) ref_deltas[:] = b1[0].deltas + b2[0].deltas + b3[ 0].deltas + alpha2 * lbranch2[0].deltas neon_ref_deltas = ref_deltas.get() difference = middle_neon_deltas - neon_ref_deltas print np.max(np.abs(difference)) assert np.max(np.abs(difference)) < 1e-8 x = ref_deltas main2[0].deltas = be.iobuf(inshape) for ll in reversed(main2): x = ll.bprop(x) bottom_neon_ref_deltas = main2[1].deltas.get() difference = bottom_neon_deltas - bottom_neon_ref_deltas print np.max(np.abs(difference)) assert np.max(np.abs(difference)) < 1e-8
print 'train_set OK' #tate=lt.plot(X_train[0, 12]) #plt.savefigure('data_img.png') # setup weight initialization function init = Gaussian(scale=0.01) # discriminiator using convolution layers lrelu = Rectlin(slope=0.1) # leaky relu for discriminator # sigmoid = Logistic() # sigmoid activation function conv1 = dict(init=init, batch_norm=False, activation=lrelu, bias=init) conv2 = dict(init=init, batch_norm=False, activation=lrelu, padding=2, bias=init) conv3 = dict(init=init, batch_norm=False, activation=lrelu, padding=1, bias=init) b1 = BranchNode("b1") b2 = BranchNode("b2") branch1 = [ b1, Conv((5, 5, 5, 32), **conv1), Dropout(keep = 0.8), Conv((5, 5, 5, 8), **conv2), BatchNorm(), Dropout(keep = 0.8), Conv((5, 5, 5, 8), **conv2), BatchNorm(), Dropout(keep = 0.8), Conv((5, 5, 5, 8), **conv3), BatchNorm(), Dropout(keep = 0.8), Pooling((2, 2, 2)),
] def aux_branch(bnode): return [ bnode, Pooling(fshape=5, strides=3, op="avg"), Conv((1, 1, 128), **common), Affine(nout=1024, init=init1, activation=relu, bias=bias), Dropout(keep=0.3), Affine(nout=1000, init=init1, activation=Softmax(), bias=Constant(0)) ] # Now construct the model branch_nodes = [BranchNode(name='branch' + str(i)) for i in range(2)] main1 = main_branch(branch_nodes) aux1 = aux_branch(branch_nodes[0]) aux2 = aux_branch(branch_nodes[1]) model = Model(layers=Tree([main1, aux1, aux2], alphas=[1.0, 0.3, 0.3])) valmetric = TopKMisclassification(k=5) # dummy optimizer for benchmarking # training implementation coming soon opt_gdm = GradientDescentMomentum(0.0, 0.0) opt_biases = GradientDescentMomentum(0.0, 0.0) opt = MultiOptimizer({'default': opt_gdm, 'Bias': opt_biases}) # setup cost function as CrossEntropy
def test_branch_model_fork(backend_gpu): from neon.layers import BranchNode, Tree np.random.seed(0) be = NervanaObject.be if be.gpu_memory_size < 6.1 * 1024 * 1024 * 1024: pytest.skip(msg='Test requires more than 6.1GB') be.bsz = 64 bnode = BranchNode() i1 = inception([(32,), (32, 32), ('max', 16)]) top1 = top_branch() top2 = top_branch() p1 = Sequential(main_branch() + [bnode, i1] + top1) p2 = [bnode] + top2 alpha2 = 0.3 neon_layer = Tree([p1, p2], alphas=[1.0, alpha2]) inshape = (4, 224, 224) insize = np.prod(inshape) inpa = np.random.random((insize, batch_size)) neon_layer.configure(inshape) inp = neon_layer.be.array(inpa) neon_layer.allocate() neon_layer.layers[0].layers[0].prev_layer = True neon_layer.allocate_deltas() neon_out_dev = neon_layer.fprop(inp) neon_out = [d.get() for d in neon_out_dev] # Now make the reference pathways: main_trunk2 = Sequential(main_branch()) main_trunk2.configure(inshape) main2 = main_trunk2.layers main2[0].prev_layer = True main2[0].deltas = be.iobuf(inshape) branch2 = Sequential(top_branch()) lbranch2 = branch2.layers (b1, b2, b3) = inception_bare(i1, [(32,), (32, 32), ('max', 16)]) for bb in (b1, b2, b3, lbranch2): oshape = inshape for ll in main2 + bb: oshape = ll.configure(oshape) main1_trunk = neon_layer.layers[0].layers[:8] for ll, lo in zip(main2, main1_trunk): if ll.has_params: ll.set_params({'params': {'W': lo.W.get()}}) ll.allocate() temp_deltas = DeltasTree() temp_deltas.proc_layer(ll) temp_deltas.allocate_buffers() ll.set_deltas(temp_deltas) for ll, lo in zip(lbranch2, neon_layer.layers[1].layers[1:]): if ll.has_params: ll.set_params({'params': {'W': lo.W.get()}}) for bb in (b1, b2, b3, lbranch2): for ll in bb: ll.allocate() temp_deltas = DeltasTree() temp_deltas.proc_layer(ll) temp_deltas.allocate_buffers() ll.set_deltas(temp_deltas) # Create the combined output buffer merge_output = be.empty_like(neon_layer.layers[0].layers[9].outputs) x = inp for ll in main2: x = ll.fprop(x) main2_out = x start = 0 for bb in (b1, b2, b3): xb = main2_out for ll in bb: xb = ll.fprop(xb) end = start + xb.shape[0] merge_output[start:end] = xb start = end x = merge_output top_trunk = Sequential(top1).layers for ll in top_trunk: x = ll.fprop(x) neon_out_ref = x.get() assert allclose_with_out(neon_out_ref, neon_out[0], rtol=0) # Now do second branch neon_out_ref2 = branch2.fprop(main2_out).get() assert allclose_with_out(neon_out_ref2, neon_out[1]) neon_logger.display("Beginning Back prop") erra = [np.random.random(d.shape) for d in neon_out] err = [be.array(d) for d in erra] neon_layer.layers[0].layers[0].deltas = be.iobuf(inshape) neon_layer.bprop(err) bottom_neon_deltas = neon_layer.layers[0].layers[1].deltas.get() middle_neon_deltas = neon_layer.layers[1].layers[1].deltas.get() err0 = err[0] for ll in reversed(top_trunk): err0 = ll.bprop(err0) err1 = err[1] for ll in reversed(lbranch2): err1 = ll.bprop(err1) for bb, errb in zip((b1, b2, b3), neon_layer.layers[0].layers[-5].error_views): for ll in reversed(bb): errb = ll.bprop(errb) # Now sum up the deltas at the root of the branch layer and compare ref_deltas = be.zeros_like(b1[0].deltas) ref_deltas[:] = alpha2 * lbranch2[0].deltas ref_deltas[:] = ref_deltas + b3[0].deltas + b2[0].deltas + b1[0].deltas neon_ref_deltas = ref_deltas.get() assert allclose_with_out(middle_neon_deltas, neon_ref_deltas, rtol=0) x = ref_deltas main2[0].deltas = be.iobuf(inshape) for ll in reversed(main2): x = ll.bprop(x) bottom_neon_ref_deltas = main2[1].deltas.get() assert allclose_with_out(bottom_neon_deltas, bottom_neon_ref_deltas, rtol=0)
def generate_layers(self): conv_params = { 'strides': 1, 'padding': 1, 'init': Xavier(local=True), 'bias': Constant(0), 'activation': Rectlin() } params = { 'init': Xavier(local=True), 'bias': Constant(0), 'activation': Rectlin() } # Set up the model layers trunk_layers = [] # set up 3x3 conv stacks with different feature map sizes # use same names as Caffe model for comparison purposes trunk_layers.append(Conv((3, 3, 64), name='conv1_1', **conv_params)) # conv1_1 trunk_layers.append(Conv((3, 3, 64), name='conv1_2', **conv_params)) trunk_layers.append(Pooling(2, strides=2)) trunk_layers.append(Conv((3, 3, 128), name='conv2_1', **conv_params)) # conv2_1 trunk_layers.append(Conv((3, 3, 128), name='conv2_2', **conv_params)) trunk_layers.append(Pooling(2, strides=2)) trunk_layers.append(Conv((3, 3, 256), name='conv3_1', **conv_params)) # conv3_1 trunk_layers.append(Conv((3, 3, 256), name='conv3_2', **conv_params)) trunk_layers.append(Conv((3, 3, 256), name='conv3_3', **conv_params)) trunk_layers.append(Pooling(2, strides=2)) trunk_layers.append(Conv((3, 3, 512), name='conv4_1', **conv_params)) # conv4_1 trunk_layers.append(Conv((3, 3, 512), name='conv4_2', **conv_params)) trunk_layers.append(Conv((3, 3, 512), name='conv4_3', **conv_params)) trunk_layers.append(Pooling(2, strides=2)) trunk_layers.append(Conv((3, 3, 512), name='conv5_1', **conv_params)) # conv5_1 trunk_layers.append(Conv((3, 3, 512), name='conv5_2', **conv_params)) trunk_layers.append(Conv((3, 3, 512), name='conv5_3', **conv_params)) trunk_layers.append(Pooling(3, strides=1, padding=1)) trunk_layers.append( Conv((3, 3, 1024), dilation=6, padding=6, name='fc6', **params)) # fc6 trunk_layers.append( Conv((1, 1, 1024), dilation=1, padding=0, name='fc7', **params)) # fc7 trunk_layers.append( Conv((1, 1, 256), strides=1, padding=0, name='conv6_1', **params)) trunk_layers.append( Conv((3, 3, 512), strides=2, padding=1, name='conv6_2', **params)) trunk_layers.append( Conv((1, 1, 128), strides=1, padding=0, name='conv7_1', **params)) trunk_layers.append( Conv((3, 3, 256), strides=2, padding=1, name='conv7_2', **params)) # append conv8, conv9, conv10, etc. (if needed) matches = [re.search('conv(\d+)_2', key) for key in self.ssd_config] layer_nums = [ int(m.group(1)) if m is not None else -1 for m in matches ] max_layer_num = np.max(layer_nums) if max_layer_num is not None: for layer_num in range(8, max_layer_num + 1): trunk_layers.append( Conv((1, 1, 128), strides=1, padding=0, name='conv{}_1'.format(layer_num), **params)) trunk_layers.append( Conv((3, 3, 256), strides=1, padding=0, name='conv{}_2'.format(layer_num), **params)) layers = [] output_config = OrderedDict() mbox_index = 1 for layer in self.ssd_config: index = self.find_insertion_index(trunk_layers, layer) conv_layer = self.get_conv_layer(trunk_layers, index) branch_node = BranchNode(name=layer + '_branch') trunk_layers.insert(index, branch_node) leafs = self.generate_leafs(layer) is_terminal = layer == 'conv{}_2'.format(max_layer_num) # append leafs to layers # mbox_loc_index and mbox_conf_index map to locations # in the output list of the model. if self.ssd_config[layer]['normalize']: branch = self.create_normalize_branch(leafs, branch_node, layer) layers.append(branch) mbox_loc_index = (mbox_index, 0) mbox_conf_index = (mbox_index, 1) mbox_index += 1 else: if is_terminal: trunk_layers.append(leafs['mbox_loc']) mbox_loc_index = (0, ) else: layers.append([branch_node, leafs['mbox_loc']]) mbox_loc_index = (mbox_index, ) mbox_index += 1 layers.append([branch_node, leafs['mbox_conf']]) mbox_conf_index = (mbox_index, ) mbox_index += 1 output_config[layer] = { 'layers': leafs, 'conv_layer': conv_layer, 'index': { 'mbox_conf': mbox_conf_index, 'mbox_loc': mbox_loc_index } } layers.insert(0, trunk_layers) return layers, output_config