def fc_with_batchnorm(use_feed):
    if use_feed:
        img = fluid.layers.data(name='image', shape=[784], dtype='float32')
        label = fluid.layers.data(name='label', shape=[1], dtype='int64')
    else:
        reader = fluid.layers.open_files(filenames=[MNIST_RECORDIO_FILE],
                                         shapes=[[-1, 784], [-1, 1]],
                                         lod_levels=[0, 0],
                                         dtypes=['float32', 'int64'])
        reader = fluid.layers.io.double_buffer(reader)
        img, label = fluid.layers.read_file(reader)

    hidden = img
    for _ in range(1):
        with fluid.name_scope("hidden"):
            hidden = fluid.layers.fc(
                hidden,
                size=200,
                act='tanh',
                bias_attr=fluid.ParamAttr(
                    initializer=fluid.initializer.Constant(value=1.0)))

            hidden = fluid.layers.batch_norm(input=hidden)
    with fluid.name_scope("fc_layer"):
        prediction = fluid.layers.fc(hidden, size=10, act='softmax')
    with fluid.name_scope("loss"):
        loss = fluid.layers.cross_entropy(input=prediction, label=label)
        loss = fluid.layers.mean(loss)
    return loss
Пример #2
0
def quant_dequant_residual_block(num, quant_skip_pattern=None):
    def conv_bn_layer(input,
                      ch_out,
                      filter_size,
                      stride,
                      padding,
                      act='relu',
                      bias_attr=False):
        tmp = fluid.layers.conv2d(
            input=input,
            filter_size=filter_size,
            num_filters=ch_out,
            stride=stride,
            padding=padding,
            act=None,
            bias_attr=bias_attr)
        return fluid.layers.batch_norm(input=tmp, act=act)

    data1 = fluid.layers.data(name='image', shape=[1, 32, 32], dtype='float32')
    data2 = fluid.layers.data(
        name='matmul_input', shape=[16, 32, 32], dtype='float32')
    label = fluid.layers.data(name='label', shape=[1], dtype='int64')
    hidden = data1
    for _ in six.moves.xrange(num):
        conv = conv_bn_layer(hidden, 16, 3, 1, 1, act=None, bias_attr=True)
        short = conv_bn_layer(hidden, 16, 1, 1, 0, act=None)
        hidden = fluid.layers.elementwise_add(x=conv, y=short, act='relu')
    hidden = fluid.layers.matmul(hidden, data2, True, True)
    if isinstance(quant_skip_pattern, str):
        with fluid.name_scope(quant_skip_pattern):
            pool1 = fluid.layers.pool2d(
                input=hidden, pool_size=2, pool_type='avg', pool_stride=2)
            pool2 = fluid.layers.pool2d(
                input=hidden, pool_size=2, pool_type='max', pool_stride=2)
            pool_add = fluid.layers.elementwise_add(
                x=pool1, y=pool2, act='relu')
    elif isinstance(quant_skip_pattern, list):
        assert len(
            quant_skip_pattern
        ) > 1, 'test config error: the len of quant_skip_pattern list should be greater than 1.'
        with fluid.name_scope(quant_skip_pattern[0]):
            pool1 = fluid.layers.pool2d(
                input=hidden, pool_size=2, pool_type='avg', pool_stride=2)
            pool2 = fluid.layers.pool2d(
                input=hidden, pool_size=2, pool_type='max', pool_stride=2)
        with fluid.name_scope(quant_skip_pattern[1]):
            pool_add = fluid.layers.elementwise_add(
                x=pool1, y=pool2, act='relu')
    else:
        pool1 = fluid.layers.pool2d(
            input=hidden, pool_size=2, pool_type='avg', pool_stride=2)
        pool2 = fluid.layers.pool2d(
            input=hidden, pool_size=2, pool_type='max', pool_stride=2)
        pool_add = fluid.layers.elementwise_add(x=pool1, y=pool2, act='relu')
    fc = fluid.layers.fc(input=pool_add, size=10)
    loss = fluid.layers.cross_entropy(input=fc, label=label)
    loss = fluid.layers.mean(loss)
    return loss
    def _residual_unit(self,
                       input,
                       num_in_filter,
                       num_mid_filter,
                       num_out_filter,
                       stride,
                       filter_size,
                       act=None,
                       use_se=False,
                       name=None):
        input_data = input
        conv0 = self._conv_bn_layer(
            input=input,
            filter_size=1,
            num_filters=num_mid_filter,
            stride=1,
            padding=0,
            if_act=True,
            act=act,
            name=name + '_expand')

        if self.block_stride == 4 and stride == 2:
            self.block_stride += 1
            if self.block_stride in self.feature_maps:
                self.end_points.append(conv0)

        with fluid.name_scope('res_conv1'):
            conv1 = self._conv_bn_layer(
                input=conv0,
                filter_size=filter_size,
                num_filters=num_mid_filter,
                stride=stride,
                padding=int((filter_size - 1) // 2),
                if_act=True,
                act=act,
                num_groups=num_mid_filter,
                use_cudnn=False,
                name=name + '_depthwise')

        if use_se:
            with fluid.name_scope('se_block'):
                conv1 = self._se_block(
                    input=conv1,
                    num_out_filter=num_mid_filter,
                    name=name + '_se')

        conv2 = self._conv_bn_layer(
            input=conv1,
            filter_size=1,
            num_filters=num_out_filter,
            stride=1,
            padding=0,
            if_act=False,
            name=name + '_linear')
        if num_in_filter != num_out_filter or stride != 1:
            return conv2
        else:
            return fluid.layers.elementwise_add(x=input_data, y=conv2, act=None)
Пример #4
0
def deeplabv3p(img, num_classes):
    # Backbone设置:xception 或 mobilenetv2
    data, decode_shortcut = resnet_vd(img)

    # 编码器解码器设置
    #cfg.MODEL.DEFAULT_EPSILON = 1e-5
    #if cfg.MODEL.DEEPLAB.ENCODER_WITH_ASPP:
    data = encoder(data)
    #if cfg.MODEL.DEEPLAB.ENABLE_DECODER:
    data = decoder(data, decode_shortcut)

    # 根据类别数设置最后一个卷积层输出,并resize到图片原始尺寸
    param_attr = fluid.ParamAttr(
        name=name_scope + 'weights',
        regularizer=fluid.regularizer.L2DecayRegularizer(
            regularization_coeff=0.0),
        initializer=fluid.initializer.TruncatedNormal(loc=0.0, scale=0.01))

    #if not cfg.MODEL.DEEPLAB.DECODER.OUTPUT_IS_LOGITS:
    with scope('logit'):
        with fluid.name_scope('last_conv'):
            logit = conv(
                    data,
                    num_classes,
                    1,
                    stride=1,
                    padding=0,
                    bias_attr=True,
                    param_attr=param_attr)
    #else:
    #    logit = data

    logit = fluid.layers.resize_bilinear(logit, img.shape[2:])
    return logit
Пример #5
0
def deeplabv3p(img, num_classes):
    # Backbone设置:xception 或 mobilenetv2
    if 'xception' in cfg.MODEL.DEEPLAB.BACKBONE:
        data, decode_shortcut = xception(img)
    elif 'mobilenet' in cfg.MODEL.DEEPLAB.BACKBONE:
        data, decode_shortcut = mobilenetv2(img)
    else:
        raise Exception("deeplab only support xception and mobilenet backbone")

    # 编码器解码器设置
    cfg.MODEL.DEFAULT_EPSILON = 1e-5
    if cfg.MODEL.DEEPLAB.ENCODER_WITH_ASPP:
        data = encoder(data)
    if cfg.MODEL.DEEPLAB.ENABLE_DECODER:
        data = decoder(data, decode_shortcut)

    # 根据类别数设置最后一个卷积层输出,并resize到图片原始尺寸
    param_attr = fluid.ParamAttr(
        name=name_scope + 'weights',
        regularizer=fluid.regularizer.L2DecayRegularizer(
            regularization_coeff=0.0),
        initializer=fluid.initializer.TruncatedNormal(loc=0.0, scale=0.01))
    with scope('logit'):
        with fluid.name_scope('last_conv'):
            logit = conv(data,
                         num_classes,
                         1,
                         stride=1,
                         padding=0,
                         bias_attr=True,
                         param_attr=param_attr)
        logit = fluid.layers.resize_bilinear(logit, img.shape[2:])

    return logit
Пример #6
0
    def _get_outputs(self, input, is_train=True):
        """
        Get YOLOv3 head output

        Args:
            input (list): List of Variables, output of backbone stages
            is_train (bool): whether in train or test mode

        Returns:
            outputs (list): Variables of each output layer
        """

        outputs = []

        # get last out_layer_num blocks in reverse order
        out_layer_num = len(self.anchor_masks)
        blocks = input[-1:-out_layer_num - 1:-1]

        route = None
        for i, block in enumerate(blocks):
            if i > 0:  # perform concat in first 2 detection_block
                block = fluid.layers.concat(input=[route, block], axis=1)
            route, tip = self._detection_block(block,
                                               channel=512 // (2**i),
                                               is_test=(not is_train),
                                               name=self.prefix_name +
                                               "yolo_block.{}".format(i))

            # out channel number = mask_num * (5 + class_num)
            num_filters = len(self.anchor_masks[i]) * (self.num_classes + 5)
            with fluid.name_scope('yolo_output'):
                block_out = fluid.layers.conv2d(
                    input=tip,
                    num_filters=num_filters,
                    filter_size=1,
                    stride=1,
                    padding=0,
                    act=None,
                    param_attr=ParamAttr(
                        name=self.prefix_name +
                        "yolo_output.{}.conv.weights".format(i)),
                    bias_attr=ParamAttr(regularizer=L2Decay(0.),
                                        name=self.prefix_name +
                                        "yolo_output.{}.conv.bias".format(i)))
                outputs.append(block_out)

            if i < len(blocks) - 1:
                # do not perform upsample in the last detection_block
                route = self._conv_bn(input=route,
                                      ch_out=256 // (2**i),
                                      filter_size=1,
                                      stride=1,
                                      padding=0,
                                      is_test=(not is_train),
                                      name=self.prefix_name +
                                      "yolo_transition.{}".format(i))
                # upsample
                route = self._upsample(route)

        return outputs
Пример #7
0
    def build_net(self, inputs):
        # 在两类分割情况下,当loss函数选择dice_loss或bce_loss的时候,最后logit输出通道数设置为1
        if self.use_dice_loss or self.use_bce_loss:
            self.num_classes = 1
        image = inputs['image']

        data, decode_shortcuts = self.backbone(image)
        decode_shortcut = decode_shortcuts[self.backbone.decode_points]

        # 编码器解码器设置
        if self.encoder_with_aspp:
            data = self._encoder(data)
        if self.enable_decoder:
            data = self._decoder(data, decode_shortcut)

        # 根据类别数设置最后一个卷积层输出,并resize到图片原始尺寸
        param_attr = fluid.ParamAttr(
            name=name_scope + 'weights',
            regularizer=fluid.regularizer.L2DecayRegularizer(
                regularization_coeff=0.0),
            initializer=fluid.initializer.TruncatedNormal(loc=0.0, scale=0.01))
        with scope('logit'):
            with fluid.name_scope('last_conv'):
                logit = conv(data,
                             self.num_classes,
                             1,
                             stride=1,
                             padding=0,
                             bias_attr=True,
                             param_attr=param_attr)
            image_shape = fluid.layers.shape(image)
            logit = fluid.layers.resize_bilinear(logit, image_shape[2:])

        if self.num_classes == 1:
            out = sigmoid_to_softmax(logit)
            out = fluid.layers.transpose(out, [0, 2, 3, 1])
        else:
            out = fluid.layers.transpose(logit, [0, 2, 3, 1])

        pred = fluid.layers.argmax(out, axis=3)
        pred = fluid.layers.unsqueeze(pred, axes=[3])

        if self.mode == 'train':
            label = inputs['label']
            mask = label != self.ignore_index
            return self._get_loss(logit, label, mask)

        elif self.mode == 'eval':
            label = inputs['label']
            mask = label != self.ignore_index
            loss = self._get_loss(logit, label, mask)
            return loss, pred, label, mask
        else:
            if self.num_classes == 1:
                logit = sigmoid_to_softmax(logit)
            else:
                logit = fluid.layers.softmax(logit, axis=1)
            return pred, logit

        return logit
Пример #8
0
    def _get_outputs(self, input, is_train=True):
        outputs = []

        # get last out_layer_num blocks in reverse order
        out_layer_num = len(self.anchor_masks)  # 输出层的数量,有3个输出层。

        # 倒序的写法。blocks是input的倒序。用于fpn的3个张量的倒序。
        # blocks = [backbone_s32, backbone_s16, backbone_s8]
        blocks = input[-1:-out_layer_num - 1:-1]

        route = None
        for i, block in enumerate(blocks):  # blocks = [backbone_s32, backbone_s16, backbone_s8]
            if i > 0:  # perform concat in first 2 detection_block
                block = fluid.layers.concat(input=[route, block], axis=1)

            # tip再接卷积进行预测。route用于上采样。
            route, tip = self._detection_block(
                block,
                channel=512 // (2 ** i),
                is_test=(not is_train),
                name=self.prefix_name + "yolo_block.{}".format(i))

            # out channel number = mask_num * (5 + class_num)
            num_filters = len(self.anchor_masks[i]) * (self.num_classes + 5)
            with fluid.name_scope('yolo_output'):
                # 输出卷积层的weights没加正则
                # 输出卷积层的bias加了L2正则
                block_out = fluid.layers.conv2d(
                    input=tip,
                    num_filters=num_filters,
                    filter_size=1,
                    stride=1,
                    padding=0,
                    act=None,
                    param_attr=ParamAttr(
                        name=self.prefix_name +
                             "yolo_output.{}.conv.weights".format(i)),
                    bias_attr=ParamAttr(
                        regularizer=L2Decay(0.),
                        name=self.prefix_name +
                             "yolo_output.{}.conv.bias".format(i)))
                outputs.append(block_out)

            # route用于上采样。
            if i < len(blocks) - 1:
                # do not perform upsample in the last detection_block
                route = self._conv_bn(
                    input=route,
                    ch_out=256 // (2 ** i),
                    filter_size=1,
                    stride=1,
                    padding=0,
                    is_test=(not is_train),
                    name=self.prefix_name + "yolo_transition.{}".format(i))
                # upsample
                route = self._upsample(route)
        return outputs
Пример #9
0
    def _head(self, input, is_train=True):
        outputs = []

        # get last out_layer_num blocks in reverse order
        out_layer_num = len(self.anchor_masks)
        blocks = input[-1:-out_layer_num - 1:-1]

        route = None
        for i, block in enumerate(blocks):
            if i > 0:  # perform concat in first 2 detection_block
                block = fluid.layers.concat(input=[route, block], axis=1)
            route, tip = self._detection_block(
                block,
                channel=64 * (2**out_layer_num) // (2**i),
                is_first=i == 0,
                is_test=(not is_train),
                conv_block_num=self.conv_block_num,
                name=self.prefix_name + "yolo_block.{}".format(i))

            # out channel number = mask_num * (5 + class_num)
            if self.iou_aware:
                num_filters = len(self.anchor_masks[i]) * (
                    self.num_classes + 6)
            else:
                num_filters = len(self.anchor_masks[i]) * (
                    self.num_classes + 5)
            with fluid.name_scope('yolo_output'):
                block_out = fluid.layers.conv2d(
                    input=tip,
                    num_filters=num_filters,
                    filter_size=1,
                    stride=1,
                    padding=0,
                    act=None,
                    param_attr=ParamAttr(
                        name=self.prefix_name +
                        "yolo_output.{}.conv.weights".format(i)),
                    bias_attr=ParamAttr(
                        regularizer=L2Decay(0.),
                        name=self.prefix_name +
                        "yolo_output.{}.conv.bias".format(i)))
                outputs.append(block_out)

            if i < len(blocks) - 1:
                # do not perform upsample in the last detection_block
                route = self._conv_bn(
                    input=route,
                    ch_out=256 // (2**i),
                    filter_size=1,
                    stride=1,
                    padding=0,
                    is_test=(not is_train),
                    name=self.prefix_name + "yolo_transition.{}".format(i))
                # upsample
                route = self._upsample(route)

        return outputs
Пример #10
0
def fc_with_batchnorm(use_feed):
    img = fluid.layers.data(name='image', shape=[784], dtype='float32')
    label = fluid.layers.data(name='label', shape=[1], dtype='int64')

    hidden = img
    for _ in range(1):
        with fluid.name_scope("hidden"):
            hidden = fluid.layers.fc(
                hidden,
                size=200,
                act='tanh',
                bias_attr=fluid.ParamAttr(
                    initializer=fluid.initializer.Constant(value=1.0)))

            hidden = fluid.layers.batch_norm(input=hidden)
    with fluid.name_scope("fc_layer"):
        prediction = fluid.layers.fc(hidden, size=10, act='softmax')
    with fluid.name_scope("loss"):
        loss = fluid.layers.cross_entropy(input=prediction, label=label)
        loss = fluid.layers.mean(loss)
    return loss
Пример #11
0
    def residual_unit(self,
                      input,
                      num_in_filter,
                      num_mid_filter,
                      num_out_filter,
                      stride,
                      filter_size,
                      act=None,
                      use_se=False,
                      name=None):

        input_data = input
        conv0 = self.conv_bn_layer(
            input=input,
            filter_size=1,
            num_filters=num_mid_filter,
            stride=1,
            padding=0,
            if_act=True,
            act=act,
            name=name + '_expand')

        conv1 = self.conv_bn_layer(
            input=conv0,
            filter_size=filter_size,
            num_filters=num_mid_filter,
            stride=stride,
            padding=int((filter_size - 1) // 2),
            if_act=True,
            act=act,
            num_groups=num_mid_filter,
            use_cudnn=False,
            name=name + '_depthwise')

        if use_se:
            with fluid.name_scope('se_block_skip'):
                conv1 = self.se_block(
                    input=conv1,
                    num_out_filter=num_mid_filter,
                    name=name + '_se')

        conv2 = self.conv_bn_layer(
            input=conv1,
            filter_size=1,
            num_filters=num_out_filter,
            stride=1,
            padding=0,
            if_act=False,
            name=name + '_linear')
        if num_in_filter != num_out_filter or stride != 1:
            return conv2
        else:
            return fluid.layers.elementwise_add(x=input_data, y=conv2, act=None)
Пример #12
0
    def test_name_scope(self):
        with fluid.name_scope("s1"):
            a = fluid.layers.data(name='data', shape=[1], dtype='int32')
            b = a + 1
            with fluid.name_scope("s2"):
                c = b * 1
            with fluid.name_scope("s3"):
                d = c / 1
        with fluid.name_scope("s1"):
            f = fluid.layers.pow(d, 2.0)
        with fluid.name_scope("s4"):
            g = f - 1

        for op in fluid.default_main_program().block(0).ops:
            if op.type == 'elementwise_add':
                self.assertEqual(op.desc.attr("op_namescope"), '/s1/')
            elif op.type == 'elementwise_mul':
                self.assertEqual(op.desc.attr("op_namescope"), '/s1/s2/')
            elif op.type == 'elementwise_div':
                self.assertEqual(op.desc.attr("op_namescope"), '/s1/s3/')
            elif op.type == 'elementwise_sub':
                self.assertEqual(op.desc.attr("op_namescope"), '/s4/')
            elif op.type == 'pow':
                self.assertEqual(op.desc.attr("op_namescope"), '/s1_1/')
Пример #13
0
def residual_block(num, quant_skip_pattern=None):
    def conv_bn_layer(input,
                      ch_out,
                      filter_size,
                      stride,
                      padding,
                      act='relu',
                      bias_attr=False):
        tmp = fluid.layers.conv2d(input=input,
                                  filter_size=filter_size,
                                  num_filters=ch_out,
                                  stride=stride,
                                  padding=padding,
                                  act=None,
                                  bias_attr=bias_attr)
        return fluid.layers.batch_norm(input=tmp, act=act)

    data = fluid.layers.data(name='image',
                             shape=[1, 1, 32, 32],
                             dtype='float32',
                             append_batch_size=False)
    label = fluid.layers.data(name='label',
                              shape=[1, 1],
                              dtype='int64',
                              append_batch_size=False)
    hidden = data
    for _ in six.moves.xrange(num):
        conv = conv_bn_layer(hidden, 16, 3, 1, 1, act=None, bias_attr=True)
        short = conv_bn_layer(hidden, 16, 1, 1, 0, act=None)
        hidden = fluid.layers.elementwise_add(x=conv, y=short, act='relu')
    matmul_weight = fluid.layers.create_parameter(shape=[1, 16, 32, 32],
                                                  dtype='float32')
    hidden = fluid.layers.matmul(hidden, matmul_weight, True, True)
    if quant_skip_pattern:
        with fluid.name_scope(quant_skip_pattern):
            pool = fluid.layers.pool2d(input=hidden,
                                       pool_size=2,
                                       pool_type='avg',
                                       pool_stride=2)
    else:
        pool = fluid.layers.pool2d(input=hidden,
                                   pool_size=2,
                                   pool_type='avg',
                                   pool_stride=2)
    fc = fluid.layers.fc(input=pool, size=10)
    loss = fluid.layers.cross_entropy(input=fc, label=label)
    loss = fluid.layers.mean(loss)
    return loss
def conv_net(img, label):
    conv_pool_1 = fluid.nets.simple_img_conv_pool(input=img,
                                                  filter_size=5,
                                                  num_filters=20,
                                                  pool_size=2,
                                                  pool_stride=2,
                                                  pool_type='max',
                                                  act="relu")
    conv_pool_2 = fluid.nets.simple_img_conv_pool(input=conv_pool_1,
                                                  filter_size=5,
                                                  num_filters=50,
                                                  pool_size=2,
                                                  pool_stride=2,
                                                  pool_type='avg',
                                                  act="relu")
    with fluid.name_scope("skip_quant"):
        hidden = fluid.layers.fc(input=conv_pool_1, size=100, act='relu')
    prediction = fluid.layers.fc(input=hidden, size=10, act='softmax')
    loss = fluid.layers.cross_entropy(input=prediction, label=label)
    avg_loss = fluid.layers.mean(loss)
    return avg_loss
Пример #15
0
    def net(self, input, class_dim=1000, scale=1.0):
        # conv1: 112x112
        input = self.conv_bn_layer(input,
                                   filter_size=3,
                                   channels=3,
                                   num_filters=int(32 * scale),
                                   stride=2,
                                   padding=1,
                                   name="conv1")

        # 56x56
        input = self.depthwise_separable(input,
                                         num_filters1=32,
                                         num_filters2=64,
                                         num_groups=32,
                                         stride=1,
                                         scale=scale,
                                         name="conv2_1")

        input = self.depthwise_separable(input,
                                         num_filters1=64,
                                         num_filters2=128,
                                         num_groups=64,
                                         stride=2,
                                         scale=scale,
                                         name="conv2_2")

        # 28x28
        input = self.depthwise_separable(input,
                                         num_filters1=128,
                                         num_filters2=128,
                                         num_groups=128,
                                         stride=1,
                                         scale=scale,
                                         name="conv3_1")

        input = self.depthwise_separable(input,
                                         num_filters1=128,
                                         num_filters2=256,
                                         num_groups=128,
                                         stride=2,
                                         scale=scale,
                                         name="conv3_2")

        # 14x14
        input = self.depthwise_separable(input,
                                         num_filters1=256,
                                         num_filters2=256,
                                         num_groups=256,
                                         stride=1,
                                         scale=scale,
                                         name="conv4_1")

        input = self.depthwise_separable(input,
                                         num_filters1=256,
                                         num_filters2=512,
                                         num_groups=256,
                                         stride=2,
                                         scale=scale,
                                         name="conv4_2")

        # 14x14
        for i in range(5):
            input = self.depthwise_separable(input,
                                             num_filters1=512,
                                             num_filters2=512,
                                             num_groups=512,
                                             stride=1,
                                             scale=scale,
                                             name="conv5" + "_" + str(i + 1))
        # 7x7
        input = self.depthwise_separable(input,
                                         num_filters1=512,
                                         num_filters2=1024,
                                         num_groups=512,
                                         stride=2,
                                         scale=scale,
                                         name="conv5_6")

        input = self.depthwise_separable(input,
                                         num_filters1=1024,
                                         num_filters2=1024,
                                         num_groups=1024,
                                         stride=1,
                                         scale=scale,
                                         name="conv6")

        input = fluid.layers.pool2d(input=input,
                                    pool_size=0,
                                    pool_stride=1,
                                    pool_type='avg',
                                    global_pooling=True)
        with fluid.name_scope('last_fc'):
            output = fluid.layers.fc(input=input,
                                     size=class_dim,
                                     act='softmax',
                                     param_attr=ParamAttr(initializer=MSRA(),
                                                          name="fc7_weights"),
                                     bias_attr=ParamAttr(name="fc7_offset"))

        return output
Пример #16
0
    def _get_outputs(self, input, is_train=True):
        """
        Get YOLOv3 head output

        Args:
            input (list): List of Variables, output of backbone stages
            is_train (bool): whether in train or test mode

        Returns:
            outputs (list): Variables of each output layer
        """

        # get last out_layer_num blocks in reverse order
        out_layer_num = len(self.anchor_masks)
        blocks = input[-1:-out_layer_num - 1:-1]

        # fpn
        yolo_feats = []
        route = None
        for i, block in enumerate(blocks):
            if i > 0:  # perform concat in first 2 detection_block
                block = fluid.layers.concat(input=[route, block], axis=1)
            route, tip = self._detection_block(
                block,
                channel=512 // (2**i),
                is_first=i == 0,
                is_test=(not is_train),
                conv_block_num=self.conv_block_num,
                name=self.prefix_name + "fpn.{}".format(i))

            yolo_feats.append(tip)

            if i < len(blocks) - 1:
                # do not perform upsample in the last detection_block
                route = self._conv_bn(input=route,
                                      ch_out=512 // (2**i),
                                      filter_size=1,
                                      stride=1,
                                      padding=0,
                                      act=self.act,
                                      name=self.prefix_name +
                                      "fpn_transition.{}".format(i))
                # upsample
                route = self._upsample(route)

        # pan
        pan_feats = [yolo_feats[-1]]
        route = yolo_feats[out_layer_num - 1]
        for i in reversed(range(out_layer_num - 1)):
            channel = 512 // (2**i)
            route = self._conv_bn(input=route,
                                  ch_out=channel,
                                  filter_size=3,
                                  stride=2,
                                  padding=1,
                                  act=self.act,
                                  name=self.prefix_name +
                                  "pan_transition.{}".format(i))
            block = yolo_feats[i]
            block = fluid.layers.concat(input=[route, block], axis=1)

            route, tip = self._detection_block(
                block,
                channel=channel,
                is_first=False,
                is_test=(not is_train),
                conv_block_num=self.conv_block_num,
                name=self.prefix_name + "pan.{}".format(i))

            pan_feats.append(tip)

        pan_feats = pan_feats[::-1]
        outputs = []
        for i, block in enumerate(pan_feats):
            if self.iou_aware:
                num_filters = len(
                    self.anchor_masks[i]) * (self.num_classes + 6)
            else:
                num_filters = len(
                    self.anchor_masks[i]) * (self.num_classes + 5)
            with fluid.name_scope('yolo_output'):
                block_out = fluid.layers.conv2d(
                    input=block,
                    num_filters=num_filters,
                    filter_size=1,
                    stride=1,
                    padding=0,
                    act=None,
                    param_attr=ParamAttr(
                        name=self.prefix_name +
                        "yolo_output.{}.conv.weights".format(i)),
                    bias_attr=ParamAttr(regularizer=L2Decay(0.),
                                        name=self.prefix_name +
                                        "yolo_output.{}.conv.bias".format(i)))
                outputs.append(block_out)

        return outputs