提交 b2b359c3 编写于 作者: Y Yuan Gao 提交者: qingqing01

Add norm to fpn's conv (#2990)

上级 d5a67d38
...@@ -24,6 +24,7 @@ from paddle.fluid.initializer import Xavier ...@@ -24,6 +24,7 @@ from paddle.fluid.initializer import Xavier
from paddle.fluid.regularizer import L2Decay from paddle.fluid.regularizer import L2Decay
from ppdet.core.workspace import register from ppdet.core.workspace import register
from ppdet.modeling.ops import ConvNorm
__all__ = ['FPN'] __all__ = ['FPN']
...@@ -39,6 +40,7 @@ class FPN(object): ...@@ -39,6 +40,7 @@ class FPN(object):
max_level (int): highest level of the backbone feature map to use max_level (int): highest level of the backbone feature map to use
spatial_scale (list): feature map scaling factor spatial_scale (list): feature map scaling factor
has_extra_convs (bool): whether has extral convolutions in higher levels has_extra_convs (bool): whether has extral convolutions in higher levels
norm_type (str|None): normalization type, 'bn'/'sync_bn'/'affine_channel'
""" """
def __init__(self, def __init__(self,
...@@ -46,28 +48,41 @@ class FPN(object): ...@@ -46,28 +48,41 @@ class FPN(object):
min_level=2, min_level=2,
max_level=6, max_level=6,
spatial_scale=[1. / 32., 1. / 16., 1. / 8., 1. / 4.], spatial_scale=[1. / 32., 1. / 16., 1. / 8., 1. / 4.],
has_extra_convs=False): has_extra_convs=False,
norm_type=None):
self.num_chan = num_chan self.num_chan = num_chan
self.min_level = min_level self.min_level = min_level
self.max_level = max_level self.max_level = max_level
self.spatial_scale = spatial_scale self.spatial_scale = spatial_scale
self.has_extra_convs = has_extra_convs self.has_extra_convs = has_extra_convs
self.norm_type = norm_type
def _add_topdown_lateral(self, body_name, body_input, upper_output): def _add_topdown_lateral(self, body_name, body_input, upper_output):
lateral_name = 'fpn_inner_' + body_name + '_lateral' lateral_name = 'fpn_inner_' + body_name + '_lateral'
topdown_name = 'fpn_topdown_' + body_name topdown_name = 'fpn_topdown_' + body_name
fan = body_input.shape[1] fan = body_input.shape[1]
lateral = fluid.layers.conv2d( if self.norm_type:
body_input, initializer = Xavier(fan_out=fan)
self.num_chan, lateral = ConvNorm(
1, body_input,
param_attr=ParamAttr( self.num_chan,
name=lateral_name + "_w", initializer=Xavier(fan_out=fan)), 1,
bias_attr=ParamAttr( initializer=initializer,
name=lateral_name + "_b", norm_type=self.norm_type,
learning_rate=2., name=lateral_name,
regularizer=L2Decay(0.)), bn_name=lateral_name)
name=lateral_name) else:
lateral = fluid.layers.conv2d(
body_input,
self.num_chan,
1,
param_attr=ParamAttr(
name=lateral_name + "_w", initializer=Xavier(fan_out=fan)),
bias_attr=ParamAttr(
name=lateral_name + "_b",
learning_rate=2.,
regularizer=L2Decay(0.)),
name=lateral_name)
shape = fluid.layers.shape(upper_output) shape = fluid.layers.shape(upper_output)
shape_hw = fluid.layers.slice(shape, axes=[0], starts=[2], ends=[4]) shape_hw = fluid.layers.slice(shape, axes=[0], starts=[2], ends=[4])
out_shape_ = shape_hw * 2 out_shape_ = shape_hw * 2
...@@ -97,17 +112,29 @@ class FPN(object): ...@@ -97,17 +112,29 @@ class FPN(object):
fpn_inner_name = 'fpn_inner_' + body_name_list[0] fpn_inner_name = 'fpn_inner_' + body_name_list[0]
body_input = body_dict[body_name_list[0]] body_input = body_dict[body_name_list[0]]
fan = body_input.shape[1] fan = body_input.shape[1]
self.fpn_inner_output[0] = fluid.layers.conv2d( if self.norm_type:
body_input, initializer = Xavier(fan_out=fan)
self.num_chan, self.fpn_inner_output[0] = ConvNorm(
1, body_input,
param_attr=ParamAttr( self.num_chan,
name=fpn_inner_name + "_w", initializer=Xavier(fan_out=fan)), 1,
bias_attr=ParamAttr( initializer=initializer,
name=fpn_inner_name + "_b", norm_type=self.norm_type,
learning_rate=2., name=fpn_inner_name,
regularizer=L2Decay(0.)), bn_name=fpn_inner_name)
name=fpn_inner_name) else:
self.fpn_inner_output[0] = fluid.layers.conv2d(
body_input,
self.num_chan,
1,
param_attr=ParamAttr(
name=fpn_inner_name + "_w",
initializer=Xavier(fan_out=fan)),
bias_attr=ParamAttr(
name=fpn_inner_name + "_b",
learning_rate=2.,
regularizer=L2Decay(0.)),
name=fpn_inner_name)
for i in range(1, num_backbone_stages): for i in range(1, num_backbone_stages):
body_name = body_name_list[i] body_name = body_name_list[i]
body_input = body_dict[body_name] body_input = body_dict[body_name]
...@@ -120,18 +147,29 @@ class FPN(object): ...@@ -120,18 +147,29 @@ class FPN(object):
for i in range(num_backbone_stages): for i in range(num_backbone_stages):
fpn_name = 'fpn_' + body_name_list[i] fpn_name = 'fpn_' + body_name_list[i]
fan = self.fpn_inner_output[i].shape[1] * 3 * 3 fan = self.fpn_inner_output[i].shape[1] * 3 * 3
fpn_output = fluid.layers.conv2d( if self.norm_type:
self.fpn_inner_output[i], initializer = Xavier(fan_out=fan)
self.num_chan, fpn_output = ConvNorm(
filter_size=3, self.fpn_inner_output[i],
padding=1, self.num_chan,
param_attr=ParamAttr( 3,
name=fpn_name + "_w", initializer=Xavier(fan_out=fan)), initializer=initializer,
bias_attr=ParamAttr( norm_type=self.norm_type,
name=fpn_name + "_b", name=fpn_name,
learning_rate=2., bn_name=fpn_name)
regularizer=L2Decay(0.)), else:
name=fpn_name) fpn_output = fluid.layers.conv2d(
self.fpn_inner_output[i],
self.num_chan,
filter_size=3,
padding=1,
param_attr=ParamAttr(
name=fpn_name + "_w", initializer=Xavier(fan_out=fan)),
bias_attr=ParamAttr(
name=fpn_name + "_b",
learning_rate=2.,
regularizer=L2Decay(0.)),
name=fpn_name)
fpn_dict[fpn_name] = fpn_output fpn_dict[fpn_name] = fpn_output
fpn_name_list.append(fpn_name) fpn_name_list.append(fpn_name)
if not self.has_extra_convs and self.max_level - self.min_level == len( if not self.has_extra_convs and self.max_level - self.min_level == len(
......
...@@ -15,15 +15,87 @@ ...@@ -15,15 +15,87 @@
from numbers import Integral from numbers import Integral
from paddle import fluid from paddle import fluid
from paddle.fluid.param_attr import ParamAttr
from paddle.fluid.initializer import MSRA
from paddle.fluid.regularizer import L2Decay
from ppdet.core.workspace import register, serializable from ppdet.core.workspace import register, serializable
__all__ = [ __all__ = [
'AnchorGenerator', 'RPNTargetAssign', 'GenerateProposals', 'MultiClassNMS', 'AnchorGenerator', 'RPNTargetAssign', 'GenerateProposals', 'MultiClassNMS',
'BBoxAssigner', 'MaskAssigner', 'RoIAlign', 'RoIPool', 'MultiBoxHead', 'BBoxAssigner', 'MaskAssigner', 'RoIAlign', 'RoIPool', 'MultiBoxHead',
'SSDOutputDecoder', 'SSDMetric', 'RetinaTargetAssign', 'RetinaOutputDecoder' 'SSDOutputDecoder', 'SSDMetric', 'RetinaTargetAssign',
'RetinaOutputDecoder', 'ConvNorm'
] ]
def ConvNorm(input,
num_filters,
filter_size,
stride=1,
groups=1,
norm_decay=0.,
norm_type='affine_channel',
freeze_norm=False,
act=None,
bn_name=None,
initializer=None,
name=None):
fan = num_filters
conv = fluid.layers.conv2d(
input=input,
num_filters=num_filters,
filter_size=filter_size,
stride=stride,
padding=(filter_size - 1) // 2,
groups=groups,
act=None,
param_attr=ParamAttr(
name=name + "_weights", initializer=initializer),
bias_attr=False,
name=name + '.conv2d.output.1')
norm_lr = 0. if freeze_norm else 1.
pattr = ParamAttr(
name=bn_name + '_scale',
learning_rate=norm_lr,
regularizer=L2Decay(norm_decay))
battr = ParamAttr(
name=bn_name + '_offset',
learning_rate=norm_lr,
regularizer=L2Decay(norm_decay))
if norm_type in ['bn', 'sync_bn']:
global_stats = True if freeze_norm else False
out = fluid.layers.batch_norm(
input=conv,
act=act,
name=bn_name + '.output.1',
param_attr=pattr,
bias_attr=battr,
moving_mean_name=bn_name + '_mean',
moving_variance_name=bn_name + '_variance',
use_global_stats=global_stats)
scale = fluid.framework._get_var(pattr.name)
bias = fluid.framework._get_var(battr.name)
elif norm_type == 'affine_channel':
scale = fluid.layers.create_parameter(
shape=[conv.shape[1]],
dtype=conv.dtype,
attr=pattr,
default_initializer=fluid.initializer.Constant(1.))
bias = fluid.layers.create_parameter(
shape=[conv.shape[1]],
dtype=conv.dtype,
attr=battr,
default_initializer=fluid.initializer.Constant(0.))
out = fluid.layers.affine_channel(
x=conv, scale=scale, bias=bias, act=act)
if freeze_norm:
scale.stop_gradient = True
bias.stop_gradient = True
return out
@register @register
@serializable @serializable
class AnchorGenerator(object): class AnchorGenerator(object):
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册