    def __init__(self,
                 in_channels=[512, 1024, 2048],
                 norm_type='bn',
                 data_format='NCHW',
                 act='mish',
                 conv_block_num=3,
                 drop_block=False,
                 block_size=3,
                 keep_prob=1.0,
                 spp=False):
        """
        PPYOLOPAN layer with SPP, DropBlock and CSP connection.
        Args:
            in_channels (list): input channels for fpn
            norm_type (str): batch norm type, default bn
            data_format (str): data format, NCHW or NHWC
            act (str): activation function, default mish
            conv_block_num (int): conv block num of each pan block
            drop_block (bool): whether use DropBlock or not
            block_size (int): block size of DropBlock
            keep_prob (float): keep probability of DropBlock
            spp (bool): whether use spp or not
        """
        super(PPYOLOPAN, self).__init__()
        assert len(in_channels) > 0, "in_channels length should > 0"
        self.in_channels = in_channels
        self.num_blocks = len(in_channels)
        # parse kwargs
        self.drop_block = drop_block
        self.block_size = block_size
        self.keep_prob = keep_prob
        self.spp = spp
        self.conv_block_num = conv_block_num
        self.data_format = data_format
        if self.drop_block:
            dropblock_cfg = [[
                'dropblock', DropBlock, [self.block_size, self.keep_prob],
                dict()
            ]]
        else:
            dropblock_cfg = []

        # fpn
        # self.fpn_blocks = []
        self.fpn_blocks = nn.ModuleList()
        # self.fpn_routes = []
        self.fpn_routes = nn.ModuleDict()
        self.fpn_routes_names = []
        fpn_channels = []
        for i, ch_in in enumerate(self.in_channels[::-1]):
            if i > 0:
                ch_in += 512 // (2**(i - 1))
            channel = 512 // (2**i)
            base_cfg = []
            for j in range(self.conv_block_num):
                base_cfg += [
                    # name, layer, args
                    [
                        '{}_0'.format(j), ConvBNLayer, [channel, channel, 1],
                        dict(
                            padding=0, act=act, norm_type=norm_type)
                    ],
                    [
                        '{}_1'.format(j), ConvBNLayer, [channel, channel, 3],
                        dict(
                            padding=1, act=act, norm_type=norm_type)
                    ]
                ]

            if i == 0 and self.spp:
                base_cfg[3] = [
                    'spp', SPP, [channel * 4, channel, 1], dict(
                        pool_size=[5, 9, 13], act=act, norm_type=norm_type)
                ]

            cfg = base_cfg[:4] + dropblock_cfg + base_cfg[4:]
            name = 'fpn_{}'.format(i)
            # fpn_block = self.add_sublayer(
            #     name,
            #     PPYOLODetBlockCSP(cfg, ch_in, channel, act, norm_type, name,
            #                       data_format))
            # self.fpn_blocks.append(fpn_block)
            self.fpn_blocks.add_module(
                name,
                PPYOLODetBlockCSP(cfg, ch_in, channel, act, norm_type, name,
                                  data_format)
            )
            fpn_channels.append(channel * 2)
            if i < self.num_blocks - 1:
                name = 'fpn_transition_{}'.format(i)
                # route = self.add_sublayer(
                #     name,
                #     ConvBNLayer(
                #         ch_in=channel * 2,
                #         ch_out=channel,
                #         filter_size=1,
                #         stride=1,
                #         padding=0,
                #         act=act,
                #         norm_type=norm_type,
                #         data_format=data_format,
                #         name=name))
                # self.fpn_routes.append(route)

                self.fpn_routes.add_module(
                    name,
                    ConvBNLayer(
                        ch_in=channel * 2,
                        ch_out=channel,
                        filter_size=1,
                        stride=1,
                        padding=0,
                        act=act,
                        norm_type=norm_type,
                        data_format=data_format,
                        name=name)
                )
                self.fpn_routes_names.append(name)

                # self.fpn_routes.add_module(
                #     name,
                #     ConvBNLayer(
                #         ch_in=channel * 2,
                #         ch_out=channel,
                #         filter_size=1,
                #         stride=1,
                #         padding=0,
                #         act=act,
                #         norm_type=norm_type,
                #         data_format=data_format,
                #         name=name)
                # )
                # self.fpn_routes_names.append(name)

                # route = ConvBNLayer(
                #         ch_in=channel * 2,
                #         ch_out=channel,
                #         filter_size=1,
                #         stride=1,
                #         padding=0,
                #         act=act,
                #         norm_type=norm_type,
                #         data_format=data_format,
                #         name=name)
                # self.fpn_routes.append(route)

        # pan
        # self.pan_blocks = []
        self.pan_blocks = nn.ModuleDict()
        self.pan_blocks_names = []
        # self.pan_routes = []

        self.pan_routes = nn.ModuleDict()
        self.pan_routes_names = []
        self._out_channels = [512 // (2**(self.num_blocks - 2)), ]
        for i in reversed(range(self.num_blocks - 1)):
            name = 'pan_transition_{}'.format(i)

            # route = self.add_sublayer(
            #     name,
            #     ConvBNLayer(
            #         ch_in=fpn_channels[i + 1],
            #         ch_out=fpn_channels[i + 1],
            #         filter_size=3,
            #         stride=2,
            #         padding=1,
            #         act=act,
            #         norm_type=norm_type,
            #         data_format=data_format,
            #         name=name))
            # self.pan_routes = [route, ] + self.pan_routes

            # route = ConvBNLayer(
            #         ch_in=fpn_channels[i + 1],
            #         ch_out=fpn_channels[i + 1],
            #         filter_size=3,
            #         stride=2,
            #         padding=1,
            #         act=act,
            #         norm_type=norm_type,
            #         data_format=data_format,
            #         name=name)
            # self.pan_routes = [route, ] + self.pan_routes

            self.pan_routes.add_module(
                name,
                ConvBNLayer(
                    ch_in=fpn_channels[i + 1],
                    ch_out=fpn_channels[i + 1],
                    filter_size=3,
                    stride=2,
                    padding=1,
                    act=act,
                    norm_type=norm_type,
                    data_format=data_format,
                    name=name)
            )

            route_name = [name, ] + self.pan_routes_names
            self.pan_routes_names = route_name

            base_cfg = []
            ch_in = fpn_channels[i] + fpn_channels[i + 1]
            channel = 512 // (2**i)
            for j in range(self.conv_block_num):
                base_cfg += [
                    # name, layer, args
                    [
                        '{}_0'.format(j), ConvBNLayer, [channel, channel, 1],
                        dict(
                            padding=0, act=act, norm_type=norm_type)
                    ],
                    [
                        '{}_1'.format(j), ConvBNLayer, [channel, channel, 3],
                        dict(
                            padding=1, act=act, norm_type=norm_type)
                    ]
                ]

            cfg = base_cfg[:4] + dropblock_cfg + base_cfg[4:]
            name = 'pan_{}'.format(i)
            # pan_block = self.add_sublayer(
            #     name,
            #     PPYOLODetBlockCSP(cfg, ch_in, channel, act, norm_type, name,
            #                       data_format))

            # pan_block = PPYOLODetBlockCSP(cfg, ch_in, channel, act, norm_type, name,
            #                       data_format)
            # self.pan_blocks = [pan_block, ] + self.pan_blocks

            self.pan_blocks.add_module(
                name,
                PPYOLODetBlockCSP(cfg, ch_in, channel, act, norm_type, name,
                                  data_format)
            )

            pan_block_name = [name, ] + self.pan_blocks_names
            self.pan_blocks_names = pan_block_name


            self._out_channels.append(channel * 2)

        self._out_channels = self._out_channels[::-1]
PPYOLOPAN layer with SPP, DropBlock and CSP connection.
Args:
in_channels (list): input channels for fpn
norm_type (str): batch norm type, default bn
data_format (str): data format, NCHW or NHWC
act (str): activation function, default mish
conv_block_num (int): conv block num of each pan block
drop_block (bool): whether use DropBlock or not
block_size (int): block size of DropBlock
keep_prob (float): keep probability of DropBlock
spp (bool): whether use spp or not
ptstructure/layout/ptppyolov2/ppyolov2_yolo_fpn.py