vgg.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. from __future__ import division
  2. import paddle
  3. import paddle.nn as nn
  4. import paddle.nn.functional as F
  5. from paddle import ParamAttr
  6. from paddle.nn import Conv2D, MaxPool2D
  7. from paddlex.ppdet.core.workspace import register, serializable
  8. from ..shape_spec import ShapeSpec
  9. __all__ = ['VGG']
  10. VGG_cfg = {16: [2, 2, 3, 3, 3], 19: [2, 2, 4, 4, 4]}
  11. class ConvBlock(nn.Layer):
  12. def __init__(self,
  13. in_channels,
  14. out_channels,
  15. groups,
  16. pool_size=2,
  17. pool_stride=2,
  18. pool_padding=0,
  19. name=None):
  20. super(ConvBlock, self).__init__()
  21. self.groups = groups
  22. self.conv0 = nn.Conv2D(
  23. in_channels=in_channels,
  24. out_channels=out_channels,
  25. kernel_size=3,
  26. stride=1,
  27. padding=1,
  28. weight_attr=ParamAttr(name=name + "1_weights"),
  29. bias_attr=ParamAttr(name=name + "1_bias"))
  30. self.conv_out_list = []
  31. for i in range(1, groups):
  32. conv_out = self.add_sublayer(
  33. 'conv{}'.format(i),
  34. Conv2D(
  35. in_channels=out_channels,
  36. out_channels=out_channels,
  37. kernel_size=3,
  38. stride=1,
  39. padding=1,
  40. weight_attr=ParamAttr(
  41. name=name + "{}_weights".format(i + 1)),
  42. bias_attr=ParamAttr(name=name + "{}_bias".format(i + 1))))
  43. self.conv_out_list.append(conv_out)
  44. self.pool = MaxPool2D(
  45. kernel_size=pool_size,
  46. stride=pool_stride,
  47. padding=pool_padding,
  48. ceil_mode=True)
  49. def forward(self, inputs):
  50. out = self.conv0(inputs)
  51. out = F.relu(out)
  52. for conv_i in self.conv_out_list:
  53. out = conv_i(out)
  54. out = F.relu(out)
  55. pool = self.pool(out)
  56. return out, pool
  57. class ExtraBlock(nn.Layer):
  58. def __init__(self,
  59. in_channels,
  60. mid_channels,
  61. out_channels,
  62. padding,
  63. stride,
  64. kernel_size,
  65. name=None):
  66. super(ExtraBlock, self).__init__()
  67. self.conv0 = Conv2D(
  68. in_channels=in_channels,
  69. out_channels=mid_channels,
  70. kernel_size=1,
  71. stride=1,
  72. padding=0)
  73. self.conv1 = Conv2D(
  74. in_channels=mid_channels,
  75. out_channels=out_channels,
  76. kernel_size=kernel_size,
  77. stride=stride,
  78. padding=padding)
  79. def forward(self, inputs):
  80. out = self.conv0(inputs)
  81. out = F.relu(out)
  82. out = self.conv1(out)
  83. out = F.relu(out)
  84. return out
  85. class L2NormScale(nn.Layer):
  86. def __init__(self, num_channels, scale=1.0):
  87. super(L2NormScale, self).__init__()
  88. self.scale = self.create_parameter(
  89. attr=ParamAttr(initializer=paddle.nn.initializer.Constant(scale)),
  90. shape=[num_channels])
  91. def forward(self, inputs):
  92. out = F.normalize(inputs, axis=1, epsilon=1e-10)
  93. # out = self.scale.unsqueeze(0).unsqueeze(2).unsqueeze(3).expand_as(
  94. # out) * out
  95. out = self.scale.unsqueeze(0).unsqueeze(2).unsqueeze(3) * out
  96. return out
  97. @register
  98. @serializable
  99. class VGG(nn.Layer):
  100. def __init__(
  101. self,
  102. depth=16,
  103. normalizations=[20., -1, -1, -1, -1, -1],
  104. extra_block_filters=[[256, 512, 1, 2, 3], [128, 256, 1, 2, 3],
  105. [128, 256, 0, 1, 3], [128, 256, 0, 1, 3]]):
  106. super(VGG, self).__init__()
  107. assert depth in [16, 19], \
  108. "depth as 16/19 supported currently, but got {}".format(depth)
  109. self.depth = depth
  110. self.groups = VGG_cfg[depth]
  111. self.normalizations = normalizations
  112. self.extra_block_filters = extra_block_filters
  113. self._out_channels = []
  114. self.conv_block_0 = ConvBlock(
  115. 3, 64, self.groups[0], 2, 2, 0, name="conv1_")
  116. self.conv_block_1 = ConvBlock(
  117. 64, 128, self.groups[1], 2, 2, 0, name="conv2_")
  118. self.conv_block_2 = ConvBlock(
  119. 128, 256, self.groups[2], 2, 2, 0, name="conv3_")
  120. self.conv_block_3 = ConvBlock(
  121. 256, 512, self.groups[3], 2, 2, 0, name="conv4_")
  122. self.conv_block_4 = ConvBlock(
  123. 512, 512, self.groups[4], 3, 1, 1, name="conv5_")
  124. self._out_channels.append(512)
  125. self.fc6 = Conv2D(
  126. in_channels=512,
  127. out_channels=1024,
  128. kernel_size=3,
  129. stride=1,
  130. padding=6,
  131. dilation=6)
  132. self.fc7 = Conv2D(
  133. in_channels=1024,
  134. out_channels=1024,
  135. kernel_size=1,
  136. stride=1,
  137. padding=0)
  138. self._out_channels.append(1024)
  139. # extra block
  140. self.extra_convs = []
  141. last_channels = 1024
  142. for i, v in enumerate(self.extra_block_filters):
  143. assert len(v) == 5, "extra_block_filters size not fix"
  144. extra_conv = self.add_sublayer("conv{}".format(6 + i),
  145. ExtraBlock(last_channels, v[0],
  146. v[1], v[2], v[3], v[4]))
  147. last_channels = v[1]
  148. self.extra_convs.append(extra_conv)
  149. self._out_channels.append(last_channels)
  150. self.norms = []
  151. for i, n in enumerate(self.normalizations):
  152. if n != -1:
  153. norm = self.add_sublayer(
  154. "norm{}".format(i),
  155. L2NormScale(self.extra_block_filters[i][1], n))
  156. else:
  157. norm = None
  158. self.norms.append(norm)
  159. def forward(self, inputs):
  160. outputs = []
  161. conv, pool = self.conv_block_0(inputs['image'])
  162. conv, pool = self.conv_block_1(pool)
  163. conv, pool = self.conv_block_2(pool)
  164. conv, pool = self.conv_block_3(pool)
  165. outputs.append(conv)
  166. conv, pool = self.conv_block_4(pool)
  167. out = self.fc6(pool)
  168. out = F.relu(out)
  169. out = self.fc7(out)
  170. out = F.relu(out)
  171. outputs.append(out)
  172. if not self.extra_block_filters:
  173. return outputs
  174. # extra block
  175. for extra_conv in self.extra_convs:
  176. out = extra_conv(out)
  177. outputs.append(out)
  178. for i, n in enumerate(self.normalizations):
  179. if n != -1:
  180. outputs[i] = self.norms[i](outputs[i])
  181. return outputs
  182. @property
  183. def out_shape(self):
  184. return [ShapeSpec(channels=c) for c in self._out_channels]