Beispiel #1
0
    def __init__(self, args):
        super().__init__()

        # Input layer
        layers = [
            ConvLayer(args.cnn_in_channels,
                      args.cnn_hidden_channels,
                      num_classes=args.num_classes)
        ]
        # Hidden layers
        for _ in range(args.cnn_hidden_layers):
            layers.append(
                ConvLayer(args.cnn_hidden_channels,
                          args.cnn_hidden_channels,
                          num_classes=args.num_classes))
        # Output layer
        layers.append(
            ConvLayer(args.cnn_hidden_channels,
                      args.cnn_in_channels,
                      num_classes=args.num_classes,
                      normalize=False,
                      layer_activation=None))
        # Output layer

        self.model = nn.Sequential(*layers)
        self.residual = args.residual
Beispiel #2
0
	def set_from_config(config_json, init=None, return_class=True):
		_id = config_json['_id']
		'''number_of_block=config_json['number_of_block']
		number_of_base_channel=config_json['number_of_base_channel']
		depth=config_json['depth']'''
		layers = []
		
		import numpy as np
		
		#'''
		
		
		conv_i=0
		n_layers=2
		k=48
		input_filter_num=k*2
		layers.append(ConvLayer("conv_adjust",k*2))
		for i in range(3):
			for j in range(n_layers):
				layers.append(DenseNetLayer("DenseNetLayer_"+str(i*n_layers+j),k,4,3))
				#input_filter_num=input_filter_num+k
			if i<2:
				input_filter_num=(input_filter_num+k*n_layers)
				#layers.append(PoolLayer_inner("PoolLayer_"+str(i),input_filter_num,'avg'))
				layers.append(ConvLayer("conv_"+str(i),input_filter_num,1,1))
				layers.append(PoolLayer("pool_"+str(i),'avg',2))
				#append(ConvLayer_blocks("ConvLayer_blocks_"+str(i),12,(i+1)*11+1,2,2))
				#
		layers.append(PoolLayer("pool_"+str(i),'avg',8,use_bn=True, activation='relu'))
		layers.append(FCLayer("fc_0",10))

		#_id, _type,number_of_block=4, kernel_size=2
		'''
		for _i, layer_config in enumerate(config_json['layers']):
			layer_init = init['layers'][_i] if init is not None else None
			#print(layer_config['name'])
			layer = get_layer_by_name(layer_config['name'])
			layers.append(layer.set_from_config(layer_config, layer_init))
		#'''
		if return_class:
			return LayerCascade(_id, layers)
		else:
			return _id, layers
Beispiel #3
0
    def set_standard_convnet(self,
                             data_provider,
                             conv_blocks_config,
                             fc_block_config,
                             weight_decay,
                             drop_scheme,
                             bn_epsilon,
                             bn_decay,
                             print_info=True,
                             **kwargs):
        assert (isinstance(data_provider, DataProvider))
        self.net_config = {
            'weight_decay': weight_decay,
            'bn_epsilon': bn_epsilon,
            'bn_decay': bn_decay,
            'drop_scheme': drop_scheme,
        }

        image_size = data_provider.data_shape[0]

        layers = []
        conv_id = 0
        for _i, block_config in enumerate(conv_blocks_config):
            num_layers, kernel_size, filter_num = block_config
            for _j in range(num_layers):
                keep_prob = 1.0
                if 'conv' in drop_scheme['type']:
                    keep_prob = 1.0 if _i + _j == 0 else drop_scheme.get(
                        'conv_drop', 1.0)
                conv_layer = ConvLayer('conv_%d' % conv_id,
                                       filter_num,
                                       kernel_size=kernel_size,
                                       keep_prob=keep_prob,
                                       pre_activation=False)
                conv_id += 1
                layers.append(conv_layer)
            if _i < len(conv_blocks_config) - 1:
                keep_prob = 1.0
                if 'pool' in drop_scheme['type']:
                    keep_prob = drop_scheme.get('pool_drop', 1.0)
                pool_layer = PoolLayer('pool_%d' % _i,
                                       'max',
                                       keep_prob=keep_prob,
                                       pre_activation=False)
                layers.append(pool_layer)
                image_size = image_size // 2
        global_avg_pool = PoolLayer('pool_%d' % len(conv_blocks_config),
                                    'avg',
                                    kernel_size=image_size,
                                    strides=image_size,
                                    pre_activation=False)
        layers.append(global_avg_pool)
        for _i, units in enumerate(fc_block_config):
            keep_prob = 1.0
            if 'fc' in drop_scheme['type']:
                keep_prob = drop_scheme.get('fc_drop', 1.0)
            fc_layer = FCLayer('fc_%d' % _i, units, keep_prob=keep_prob)
            layers.append(fc_layer)
        final_fc_layer = FCLayer('fc_%d' % len(fc_block_config),
                                 data_provider.n_classes,
                                 use_bn=False,
                                 use_bias=True,
                                 activation=None)
        layers.append(final_fc_layer)
        self.layer_cascade = LayerCascade('SimpleConvNet', layers)

        if print_info:
            pass
        return self
Beispiel #4
0
    def set_standard_net(data_shape,
                         n_classes,
                         start_planes,
                         alpha,
                         block_per_group,
                         total_groups,
                         downsample_type,
                         bottleneck=4,
                         ops_order='bn_act_weight',
                         dropout_rate=0,
                         final_bn=True,
                         no_first_relu=True,
                         use_depth_sep_conv=False,
                         groups_3x3=1,
                         path_drop_rate=0,
                         use_zero_drop=True,
                         drop_only_add=False):
        image_channel, image_size = data_shape[0:2]

        addrate = alpha / (block_per_group * total_groups)  # add pyramid_net

        # initial conv
        features_dim = start_planes
        if ops_order == 'weight_bn_act':
            init_conv_layer = ConvLayer(image_channel,
                                        features_dim,
                                        kernel_size=3,
                                        use_bn=True,
                                        act_func='relu',
                                        dropout_rate=0,
                                        ops_order=ops_order)
        elif ops_order == 'act_weight_bn':
            init_conv_layer = ConvLayer(image_channel,
                                        features_dim,
                                        kernel_size=3,
                                        use_bn=True,
                                        act_func=None,
                                        dropout_rate=0,
                                        ops_order=ops_order)
        elif ops_order == 'bn_act_weight':
            init_conv_layer = ConvLayer(image_channel,
                                        features_dim,
                                        kernel_size=3,
                                        use_bn=False,
                                        act_func=None,
                                        dropout_rate=0,
                                        ops_order=ops_order)
        else:
            raise NotImplementedError
        if final_bn:
            init_bn_layer = IdentityLayer(features_dim,
                                          features_dim,
                                          use_bn=True,
                                          act_func=None,
                                          dropout_rate=0,
                                          ops_order=ops_order)
            transition2blocks = TransitionBlock(
                [init_conv_layer, init_bn_layer])
        else:
            transition2blocks = TransitionBlock([init_conv_layer])
        blocks = [transition2blocks]

        planes = start_planes
        for group_idx in range(total_groups):
            for block_idx in range(block_per_group):
                if group_idx > 0 and block_idx == 0:
                    stride = 2
                    image_size //= 2
                else:
                    stride = 1
                # prepare the residual block
                planes += addrate
                if stride == 1:
                    shortcut = IdentityLayer(features_dim,
                                             features_dim,
                                             use_bn=False,
                                             act_func=None,
                                             dropout_rate=0,
                                             ops_order=ops_order)
                else:
                    if downsample_type == 'avg_pool':
                        shortcut = PoolingLayer(features_dim,
                                                features_dim,
                                                'avg',
                                                kernel_size=2,
                                                stride=2,
                                                use_bn=False,
                                                act_func=None,
                                                dropout_rate=0,
                                                ops_order=ops_order)
                    elif downsample_type == 'max_pool':
                        shortcut = PoolingLayer(features_dim,
                                                features_dim,
                                                'max',
                                                kernel_size=2,
                                                stride=2,
                                                use_bn=False,
                                                act_func=None,
                                                dropout_rate=0,
                                                ops_order=ops_order)
                    else:
                        raise NotImplementedError

                out_plane = int(round(planes))
                if out_plane % groups_3x3 != 0:
                    out_plane -= out_plane % groups_3x3  # may change to +=
                if no_first_relu:
                    in_bottle = ConvLayer(features_dim,
                                          out_plane,
                                          kernel_size=1,
                                          use_bn=True,
                                          act_func=None,
                                          dropout_rate=dropout_rate,
                                          ops_order=ops_order)
                else:
                    in_bottle = ConvLayer(features_dim,
                                          out_plane,
                                          kernel_size=1,
                                          use_bn=True,
                                          act_func='relu',
                                          dropout_rate=dropout_rate,
                                          ops_order=ops_order)

                if use_depth_sep_conv:
                    cell_edge = DepthConvLayer(out_plane,
                                               out_plane,
                                               kernel_size=3,
                                               stride=stride,
                                               use_bn=True,
                                               act_func='relu',
                                               dropout_rate=dropout_rate,
                                               ops_order=ops_order)
                else:
                    cell_edge = ConvLayer(out_plane,
                                          out_plane,
                                          kernel_size=3,
                                          stride=stride,
                                          groups=groups_3x3,
                                          use_bn=True,
                                          act_func='relu',
                                          dropout_rate=dropout_rate,
                                          ops_order=ops_order)
                cell = TreeNode(child_nodes=[None],
                                edges=[cell_edge],
                                in_channels=out_plane,
                                out_channels=out_plane,
                                split_type=None,
                                merge_type=None,
                                path_drop_rate=path_drop_rate,
                                use_zero_drop=use_zero_drop,
                                drop_only_add=drop_only_add)

                out_bottle = ConvLayer(out_plane,
                                       out_plane * bottleneck,
                                       kernel_size=1,
                                       use_bn=True,
                                       act_func='relu',
                                       dropout_rate=dropout_rate,
                                       ops_order=ops_order)
                residual_block = ResidualBlock(cell,
                                               in_bottle,
                                               out_bottle,
                                               shortcut,
                                               final_bn=final_bn)
                blocks.append(residual_block)
                features_dim = out_plane * bottleneck
        if ops_order == 'weight_bn_act':
            global_avg_pool = PoolingLayer(features_dim,
                                           features_dim,
                                           'avg',
                                           kernel_size=image_size,
                                           stride=image_size,
                                           use_bn=False,
                                           act_func=None,
                                           dropout_rate=0,
                                           ops_order=ops_order)
        elif ops_order == 'act_weight_bn':
            global_avg_pool = PoolingLayer(features_dim,
                                           features_dim,
                                           'avg',
                                           kernel_size=image_size,
                                           stride=image_size,
                                           use_bn=False,
                                           act_func='relu',
                                           dropout_rate=0,
                                           ops_order=ops_order)
        elif ops_order == 'bn_act_weight':
            global_avg_pool = PoolingLayer(features_dim,
                                           features_dim,
                                           'avg',
                                           kernel_size=image_size,
                                           stride=image_size,
                                           use_bn=True,
                                           act_func='relu',
                                           dropout_rate=0,
                                           ops_order=ops_order)
        else:
            raise NotImplementedError
        transition2classes = TransitionBlock([global_avg_pool])
        blocks.append(transition2classes)

        classifier = LinearLayer(features_dim, n_classes, bias=True)
        tree_node_config = {
            'use_avg': True,
            'bn_before_add': False,
            'path_drop_rate': path_drop_rate,
            'use_zero_drop': use_zero_drop,
            'drop_only_add': drop_only_add,
        }

        return PyramidNet(blocks, classifier, ops_order, tree_node_config,
                          groups_3x3)
Beispiel #5
0
 def deepen(self, idx, new_layer_config, input_dim):
     assert idx < len(self.layers), 'Index out of range: %d' % idx
     if new_layer_config['name'] == 'fc':
         assert idx == len(self.layers) - 1 or isinstance(
             self.layers[idx + 1], FCLayer), 'Invalid'
         assert isinstance(self.layers[idx], FCLayer) or isinstance(
             self.layers[idx], PoolLayer), 'Invalid'
         # prepare the new fc layer
         units = input_dim
         for _i in range(idx, -1, -1):
             if isinstance(self.layers[_i], FCLayer):
                 units = self.layers[_i].units
                 break
             elif isinstance(self.layers[_i], ConvLayer):
                 units = self.layers[_i].filter_num
                 break
         fc_idx = 0
         for _i in range(0, idx + 1):
             if isinstance(self.layers[_i], FCLayer):
                 fc_idx += 1
         _id = 'fc_%d' % fc_idx
         # change the id of following fc layers
         for _i in range(idx + 1, len(self.layers)):
             if isinstance(self.layers[_i], FCLayer):
                 self.layers[_i].id = 'fc_%d' % (fc_idx + 1)
                 fc_idx += 1
         prev_layer = None
         for _i in range(idx, -1, -1):
             if self.layers[_i].ready:
                 prev_layer = self.layers[_i]
                 break
         assert prev_layer is not None, 'Invalid'
         new_fc_layer = FCLayer(_id, units, ready=False, **new_layer_config)
         # insert the new layer into the cascade
         self.layers = self.layers[:idx + 1] + [new_fc_layer
                                                ] + self.layers[idx + 1:]
         return new_fc_layer, prev_layer
     elif new_layer_config['name'] == 'conv':
         assert idx == len(self.layers) - 1 or not isinstance(
             self.layers[idx + 1], FCLayer), 'Invalid'
         assert isinstance(self.layers[idx], ConvLayer) or isinstance(
             self.layers[idx], FCLayer), 'Invalid'
         # prepare the new conv layer
         filter_num = input_dim
         for _i in range(idx, -1, -1):
             if isinstance(self.layers[_i], ConvLayer):
                 filter_num = self.layers[_i].filter_num
                 break
         conv_idx = 0
         for _i in range(0, idx + 1):
             if isinstance(self.layers[_i], ConvLayer):
                 conv_idx += 1
         _id = 'conv_%d' % conv_idx
         # change the id of following conv layers
         for _i in range(idx + 1, len(self.layers)):
             if isinstance(self.layers[_i], ConvLayer):
                 self.layers[_i].id = 'conv_%d' % (conv_idx + 1)
                 conv_idx += 1
         prev_layer = None
         for _i in range(idx, -1, -1):
             if self.layers[_i].ready:
                 prev_layer = self.layers[_i]
                 break
         assert prev_layer is not None, 'Invalid'
         new_conv_layer = ConvLayer(_id,
                                    filter_num,
                                    ready=False,
                                    **new_layer_config)
         self.layers = self.layers[:idx + 1] + [new_conv_layer
                                                ] + self.layers[idx + 1:]
         return new_conv_layer, prev_layer
     else:
         raise ValueError('Not support to insert a %s layer' %
                          new_layer_config['name'])
Beispiel #6
0
	def set_standard_dense_net(self, data_provider: DataProvider, growth_rate, depth, total_blocks,
							   keep_prob, weight_decay, model_type,
							   first_ratio=2, reduction=1.0, bc_ratio=4,
							   bn_epsilon=1e-5, bn_decay=0.9, print_info=True,
							   pre_activation=True, **kwargs):
		self.net_config = {
			'model_type': model_type,
			'weight_decay': weight_decay,
			'first_ratio': first_ratio,
			'reduction': reduction,
			'bc_ratio': bc_ratio,
			'bn_epsilon': bn_epsilon,
			'bn_decay': bn_decay,
			'pre_activation': pre_activation,
		}
		
		image_size = data_provider.data_shape[0]
		
		first_output_features = growth_rate * first_ratio
		bc_mode = (model_type == 'DenseNet-BC')
		layers_per_block = (depth - (total_blocks + 1)) // total_blocks
		if bc_mode: layers_per_block = layers_per_block // 2
		
		# initial conv
		if pre_activation:
			init_conv_layer = ConvLayer('conv_0', first_output_features, kernel_size=3, activation=None, use_bn=False)
		else:
			init_conv_layer = ConvLayer('conv_0', first_output_features, kernel_size=3, pre_activation=False)
		init_transition = TransitionBlock('T_0_first', [init_conv_layer])
		self.blocks = [init_transition]
		
		# Dense Blocks
		in_features_dim = first_output_features
		for block_idx in range(1, total_blocks + 1):
			miniblocks = []
			block_id = 'D_%d' % block_idx
			for miniblock_idx in range(1, layers_per_block + 1):
				miniblock_id = 'M_%d' % miniblock_idx
				in_bottle = None
				if bc_mode:
					bottelneck_layer = ConvLayer('conv_0', growth_rate * bc_ratio, kernel_size=1, keep_prob=keep_prob,
												 pre_activation=pre_activation)
					in_bottle = LayerCascade('in_bottle', [bottelneck_layer])
				
				branch_0 = LayerCascade('B_0', [
					ConvLayer('conv_0', growth_rate, kernel_size=3,
							  keep_prob=keep_prob, pre_activation=pre_activation)
				])
				miniblocks.append(LayerMultiBranch(miniblock_id, [branch_0], in_bottle=in_bottle))
			dense_block = DenseBlock(block_id, miniblocks)
			self.blocks += [dense_block]
			
			out_features_dim = dense_block.out_features_dim(in_features_dim)
			if block_idx != total_blocks:
				out_features_dim = int(out_features_dim * reduction)
				transition_id = 'T_%d_middle' % block_idx
				conv_layer = ConvLayer('conv_0', out_features_dim, kernel_size=1, keep_prob=keep_prob,
									   pre_activation=pre_activation)
				avg_pool_layer = PoolLayer('pool_0', 'avg', kernel_size=2, strides=2)
				transition = TransitionBlock(transition_id, [conv_layer, avg_pool_layer])
				self.blocks.append(transition)
				image_size = image_size // 2
			in_features_dim = out_features_dim
		
		# Transition to classes
		if pre_activation:
			global_avg_pool = PoolLayer('pool_0', 'avg', kernel_size=image_size, strides=image_size,
										activation='relu', use_bn=True)
		else:
			global_avg_pool = PoolLayer('pool_0', 'avg', kernel_size=image_size, strides=image_size,
										pre_activation=False)
		final_fc_layer = FCLayer('fc_0', data_provider.n_classes, use_bn=False, use_bias=True, activation=None)
		transition_to_classes = TransitionBlock('T_to_classes', [global_avg_pool, final_fc_layer])
		self.blocks.append(transition_to_classes)
		
		# print information about the network
		if print_info:
			print('Set Standard %s' % model_type)
		
			if not bc_mode:
				print('Build %s model with %d blocks, '
					  '%d composite layers each.' % (model_type, total_blocks, layers_per_block))
			if bc_mode:
				print('Build %s model with %d blocks, '
					  '%d bottleneck layers and %d composite layers each.' % (
						  model_type, total_blocks, layers_per_block, layers_per_block))
			print('Reduction at transition layers: %.2f' % reduction)
		return self
Beispiel #7
0
    def set_standard_net(data_shape,
                         n_classes,
                         start_planes,
                         block_per_group,
                         total_groups,
                         downsample_type='avg_pool',
                         ops_order='bn_act_weight',
                         dropout_rate=0,
                         use_identity=False,
                         use_depth_sep_conv=False,
                         groups_3x3=1,
                         path_drop_rate=0,
                         use_zero_drop=True,
                         drop_only_add=False):
        image_channel, image_size = data_shape[0:2]

        # initial conv
        features_dim = start_planes
        if ops_order == 'weight_bn_act':
            init_conv_layer = ConvLayer(image_channel,
                                        features_dim,
                                        kernel_size=3,
                                        use_bn=True,
                                        act_func='relu',
                                        dropout_rate=0,
                                        ops_order=ops_order)
        elif ops_order == 'act_weight_bn':
            init_conv_layer = ConvLayer(image_channel,
                                        features_dim,
                                        kernel_size=3,
                                        use_bn=True,
                                        act_func=None,
                                        dropout_rate=0,
                                        ops_order=ops_order)
        elif ops_order == 'bn_act_weight':
            init_conv_layer = ConvLayer(image_channel,
                                        features_dim,
                                        kernel_size=3,
                                        use_bn=False,
                                        act_func=None,
                                        dropout_rate=0,
                                        ops_order=ops_order)
        else:
            raise NotImplementedError
        transition2blocks = TransitionBlock([init_conv_layer])
        blocks = [transition2blocks]

        if use_identity:
            assert 'pool' in downsample_type, 'Error'
        for group_idx in range(total_groups):
            for block_idx in range(block_per_group):
                if downsample_type is None and group_idx > 0 and block_idx == 0:
                    stride = 2
                    image_size //= 2
                    out_dim = features_dim * 2
                else:
                    stride = 1
                    out_dim = features_dim
                # prepare the chain block
                if use_identity:
                    cell_edge = IdentityLayer(features_dim,
                                              features_dim,
                                              use_bn=False,
                                              act_func=None,
                                              dropout_rate=0,
                                              ops_order=ops_order)
                elif use_depth_sep_conv:
                    cell_edge = DepthConvLayer(features_dim,
                                               out_dim,
                                               kernel_size=3,
                                               stride=stride,
                                               use_bn=True,
                                               act_func='relu',
                                               dropout_rate=dropout_rate,
                                               ops_order=ops_order)
                else:
                    cell_edge = ConvLayer(features_dim,
                                          out_dim,
                                          kernel_size=3,
                                          stride=stride,
                                          groups=groups_3x3,
                                          use_bn=True,
                                          act_func='relu',
                                          dropout_rate=dropout_rate,
                                          ops_order=ops_order)
                cell = TreeNode(child_nodes=[None],
                                edges=[cell_edge],
                                in_channels=features_dim,
                                out_channels=out_dim,
                                split_type=None,
                                merge_type=None,
                                path_drop_rate=path_drop_rate,
                                use_zero_drop=use_zero_drop,
                                drop_only_add=drop_only_add)
                chain_block = ChainBlock(cell)
                blocks.append(chain_block)
                features_dim = out_dim
            if group_idx != total_groups - 1 and downsample_type is not None:
                if 'pool' in downsample_type:
                    conv_layer = ConvLayer(features_dim,
                                           2 * features_dim,
                                           kernel_size=1,
                                           stride=1,
                                           use_bn=True,
                                           act_func='relu',
                                           dropout_rate=dropout_rate,
                                           ops_order=ops_order)
                    features_dim *= 2
                    if downsample_type == 'avg_pool':
                        pool_layer = PoolingLayer(features_dim,
                                                  features_dim,
                                                  'avg',
                                                  kernel_size=2,
                                                  stride=2,
                                                  use_bn=False,
                                                  act_func=None,
                                                  dropout_rate=0,
                                                  ops_order=ops_order)
                    else:
                        pool_layer = PoolingLayer(features_dim,
                                                  features_dim,
                                                  'max',
                                                  kernel_size=2,
                                                  stride=2,
                                                  use_bn=False,
                                                  act_func=None,
                                                  dropout_rate=0,
                                                  ops_order=ops_order)
                    transition_layers = [conv_layer, pool_layer]
                elif downsample_type == 'conv':
                    conv_layer = ConvLayer(features_dim,
                                           2 * features_dim,
                                           kernel_size=3,
                                           stride=2,
                                           use_bn=True,
                                           act_func='relu',
                                           dropout_rate=dropout_rate,
                                           ops_order=ops_order)
                    features_dim *= 2
                    transition_layers = [conv_layer]
                else:
                    raise NotImplementedError
                image_size //= 2
                inter_block_transition = TransitionBlock(transition_layers)
                blocks.append(inter_block_transition)

        if ops_order == 'weight_bn_act':
            global_avg_pool = PoolingLayer(features_dim,
                                           features_dim,
                                           'avg',
                                           kernel_size=image_size,
                                           stride=image_size,
                                           use_bn=False,
                                           act_func=None,
                                           dropout_rate=0,
                                           ops_order=ops_order)
        elif ops_order == 'act_weight_bn':
            global_avg_pool = PoolingLayer(features_dim,
                                           features_dim,
                                           'avg',
                                           kernel_size=image_size,
                                           stride=image_size,
                                           use_bn=False,
                                           act_func='relu',
                                           dropout_rate=0,
                                           ops_order=ops_order)
        elif ops_order == 'bn_act_weight':
            global_avg_pool = PoolingLayer(features_dim,
                                           features_dim,
                                           'avg',
                                           kernel_size=image_size,
                                           stride=image_size,
                                           use_bn=True,
                                           act_func='relu',
                                           dropout_rate=0,
                                           ops_order=ops_order)
        else:
            raise NotImplementedError
        transition2classes = TransitionBlock([global_avg_pool])
        blocks.append(transition2classes)

        classifier = LinearLayer(features_dim, n_classes, bias=True)
        tree_node_config = {
            'use_avg': True,
            'bn_before_add': False,
            'path_drop_rate': path_drop_rate,
            'use_zero_drop': use_zero_drop,
            'drop_only_add': drop_only_add,
        }

        return ChainNet(blocks, classifier, ops_order, tree_node_config)
Beispiel #8
0
    def set_standard_net(data_shape,
                         n_classes,
                         growth_rate,
                         dense_block_per_group,
                         total_groups,
                         downsample_type,
                         first_ratio=2,
                         reduction=0.5,
                         bottleneck=4,
                         final_bn=False,
                         no_first_relu=False,
                         use_depth_sep_conv=False,
                         groups_3x3=1,
                         ops_order='bn_act_weight',
                         dropout_rate=0,
                         path_drop_rate=0,
                         use_zero_drop=True,
                         drop_only_add=False):
        image_channel, image_size = data_shape[0:2]
        features_dim = growth_rate * first_ratio
        if ops_order == 'weight_bn_act':
            init_conv_layer = ConvLayer(image_channel,
                                        features_dim,
                                        kernel_size=3,
                                        use_bn=True,
                                        act_func='relu',
                                        dropout_rate=0,
                                        ops_order=ops_order)
        elif ops_order == 'act_weight_bn':
            init_conv_layer = ConvLayer(image_channel,
                                        features_dim,
                                        kernel_size=3,
                                        use_bn=True,
                                        act_func=None,
                                        dropout_rate=0,
                                        ops_order=ops_order)
        elif ops_order == 'bn_act_weight':
            init_conv_layer = ConvLayer(image_channel,
                                        features_dim,
                                        kernel_size=3,
                                        use_bn=False,
                                        act_func=None,
                                        dropout_rate=0,
                                        ops_order=ops_order)
        else:
            raise NotImplementedError
        if final_bn:
            init_bn_layer = IdentityLayer(features_dim,
                                          features_dim,
                                          use_bn=True,
                                          act_func=None,
                                          dropout_rate=0,
                                          ops_order=ops_order)
            transition2blocks = TransitionBlock(
                [init_conv_layer, init_bn_layer])
        else:
            transition2blocks = TransitionBlock([init_conv_layer])

        blocks = [transition2blocks]
        for group_idx in range(total_groups):
            for block_idx in range(dense_block_per_group):
                if no_first_relu:
                    in_bottle = ConvLayer(features_dim,
                                          growth_rate * bottleneck,
                                          kernel_size=1,
                                          use_bn=True,
                                          act_func=None,
                                          dropout_rate=dropout_rate,
                                          ops_order=ops_order)
                else:
                    in_bottle = ConvLayer(features_dim,
                                          growth_rate * bottleneck,
                                          kernel_size=1,
                                          use_bn=True,
                                          act_func='relu',
                                          dropout_rate=dropout_rate,
                                          ops_order=ops_order)

                if use_depth_sep_conv:
                    cell_edge = DepthConvLayer(growth_rate * bottleneck,
                                               growth_rate,
                                               kernel_size=3,
                                               use_bn=True,
                                               act_func='relu',
                                               dropout_rate=dropout_rate,
                                               ops_order=ops_order)
                else:
                    cell_edge = ConvLayer(growth_rate * bottleneck,
                                          growth_rate,
                                          kernel_size=3,
                                          groups=groups_3x3,
                                          use_bn=True,
                                          act_func='relu',
                                          dropout_rate=dropout_rate,
                                          ops_order=ops_order)
                cell = TreeNode(child_nodes=[None],
                                edges=[cell_edge],
                                in_channels=growth_rate * bottleneck,
                                out_channels=growth_rate,
                                split_type=None,
                                merge_type=None,
                                path_drop_rate=path_drop_rate,
                                use_zero_drop=use_zero_drop,
                                drop_only_add=drop_only_add)
                dense_block = DenseBlock(cell,
                                         in_bottle,
                                         out_bottle=None,
                                         final_bn=final_bn)
                blocks.append(dense_block)
                features_dim += growth_rate
            if group_idx != total_groups - 1:
                if downsample_type == 'pool':
                    pool_layer = PoolingLayer(features_dim,
                                              features_dim,
                                              'avg',
                                              kernel_size=2,
                                              stride=2,
                                              use_bn=False,
                                              act_func=None,
                                              dropout_rate=0,
                                              ops_order=ops_order)
                    transition_layers = [pool_layer]
                elif downsample_type == 'conv-pool':
                    conv_layer = ConvLayer(features_dim,
                                           int(features_dim * reduction),
                                           kernel_size=1,
                                           stride=1,
                                           use_bn=True,
                                           act_func='relu',
                                           dropout_rate=dropout_rate,
                                           ops_order=ops_order)
                    features_dim = int(features_dim * reduction)
                    pool_layer = PoolingLayer(features_dim,
                                              features_dim,
                                              'avg',
                                              kernel_size=2,
                                              stride=2,
                                              use_bn=False,
                                              act_func=None,
                                              dropout_rate=0,
                                              ops_order=ops_order)
                    transition_layers = [conv_layer, pool_layer]
                else:
                    raise NotImplementedError
                image_size //= 2
                inter_block_transition = TransitionBlock(transition_layers)
                blocks.append(inter_block_transition)
        if ops_order == 'weight_bn_act':
            global_avg_pool = PoolingLayer(features_dim,
                                           features_dim,
                                           'avg',
                                           kernel_size=image_size,
                                           stride=image_size,
                                           use_bn=False,
                                           act_func=None,
                                           dropout_rate=0,
                                           ops_order=ops_order)
        elif ops_order == 'act_weight_bn':
            global_avg_pool = PoolingLayer(features_dim,
                                           features_dim,
                                           'avg',
                                           kernel_size=image_size,
                                           stride=image_size,
                                           use_bn=False,
                                           act_func='relu',
                                           dropout_rate=0,
                                           ops_order=ops_order)
        elif ops_order == 'bn_act_weight':
            global_avg_pool = PoolingLayer(features_dim,
                                           features_dim,
                                           'avg',
                                           kernel_size=image_size,
                                           stride=image_size,
                                           use_bn=True,
                                           act_func='relu',
                                           dropout_rate=0,
                                           ops_order=ops_order)
        else:
            raise NotImplementedError
        transition2classes = TransitionBlock([global_avg_pool])
        blocks.append(transition2classes)

        classifier = LinearLayer(features_dim, n_classes, bias=True)
        tree_node_config = {
            'use_avg': True,
            'bn_before_add': False,
            'path_drop_rate': path_drop_rate,
            'use_zero_drop': use_zero_drop,
            'drop_only_add': drop_only_add,
        }

        return DenseNet(blocks, classifier, ops_order, tree_node_config)