densenet.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve.
  2. #
  3. #Licensed under the Apache License, Version 2.0 (the "License");
  4. #you may not use this file except in compliance with the License.
  5. #You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. #Unless required by applicable law or agreed to in writing, software
  10. #distributed under the License is distributed on an "AS IS" BASIS,
  11. #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. #See the License for the specific language governing permissions and
  13. #limitations under the License.
  14. from __future__ import absolute_import
  15. from __future__ import division
  16. from __future__ import print_function
  17. import paddle
  18. import paddle.fluid as fluid
  19. import math
  20. from paddle.fluid.param_attr import ParamAttr
  21. __all__ = ["DenseNet"]
  22. class DenseNet(object):
  23. def __init__(self, layers=121, bn_size=4, dropout=0, num_classes=None):
  24. assert layers in [121, 161, 169, 201, 264], \
  25. "supported layers are {} but input layer is {}".format(supported_layers, layers)
  26. self.layers = layers
  27. self.bn_size = bn_size
  28. self.dropout = dropout
  29. self.num_classes = num_classes
  30. def __call__(self, input):
  31. layers = self.layers
  32. densenet_spec = {
  33. 121: (64, 32, [6, 12, 24, 16]),
  34. 161: (96, 48, [6, 12, 36, 24]),
  35. 169: (64, 32, [6, 12, 32, 32]),
  36. 201: (64, 32, [6, 12, 48, 32]),
  37. 264: (64, 32, [6, 12, 64, 48])
  38. }
  39. num_init_features, growth_rate, block_config = densenet_spec[layers]
  40. conv = fluid.layers.conv2d(
  41. input=input,
  42. num_filters=num_init_features,
  43. filter_size=7,
  44. stride=2,
  45. padding=3,
  46. act=None,
  47. param_attr=ParamAttr(name="conv1_weights"),
  48. bias_attr=False)
  49. conv = fluid.layers.batch_norm(
  50. input=conv,
  51. act='relu',
  52. param_attr=ParamAttr(name='conv1_bn_scale'),
  53. bias_attr=ParamAttr(name='conv1_bn_offset'),
  54. moving_mean_name='conv1_bn_mean',
  55. moving_variance_name='conv1_bn_variance')
  56. conv = fluid.layers.pool2d(
  57. input=conv,
  58. pool_size=3,
  59. pool_stride=2,
  60. pool_padding=1,
  61. pool_type='max')
  62. num_features = num_init_features
  63. for i, num_layers in enumerate(block_config):
  64. conv = self.make_dense_block(
  65. conv,
  66. num_layers,
  67. self.bn_size,
  68. growth_rate,
  69. self.dropout,
  70. name='conv' + str(i + 2))
  71. num_features = num_features + num_layers * growth_rate
  72. if i != len(block_config) - 1:
  73. conv = self.make_transition(
  74. conv, num_features // 2, name='conv' + str(i + 2) + '_blk')
  75. num_features = num_features // 2
  76. conv = fluid.layers.batch_norm(
  77. input=conv,
  78. act='relu',
  79. param_attr=ParamAttr(name='conv5_blk_bn_scale'),
  80. bias_attr=ParamAttr(name='conv5_blk_bn_offset'),
  81. moving_mean_name='conv5_blk_bn_mean',
  82. moving_variance_name='conv5_blk_bn_variance')
  83. if self.num_classes:
  84. conv = fluid.layers.pool2d(
  85. input=conv, pool_type='avg', global_pooling=True)
  86. stdv = 1.0 / math.sqrt(conv.shape[1] * 1.0)
  87. out = fluid.layers.fc(
  88. input=conv,
  89. size=self.num_classes,
  90. param_attr=fluid.param_attr.ParamAttr(
  91. initializer=fluid.initializer.Uniform(-stdv, stdv),
  92. name="fc_weights"),
  93. bias_attr=ParamAttr(name='fc_offset'))
  94. return out
  95. def make_transition(self, input, num_output_features, name=None):
  96. bn_ac = fluid.layers.batch_norm(
  97. input,
  98. act='relu',
  99. param_attr=ParamAttr(name=name + '_bn_scale'),
  100. bias_attr=ParamAttr(name + '_bn_offset'),
  101. moving_mean_name=name + '_bn_mean',
  102. moving_variance_name=name + '_bn_variance')
  103. bn_ac_conv = fluid.layers.conv2d(
  104. input=bn_ac,
  105. num_filters=num_output_features,
  106. filter_size=1,
  107. stride=1,
  108. act=None,
  109. bias_attr=False,
  110. param_attr=ParamAttr(name=name + "_weights"))
  111. pool = fluid.layers.pool2d(
  112. input=bn_ac_conv, pool_size=2, pool_stride=2, pool_type='avg')
  113. return pool
  114. def make_dense_block(self,
  115. input,
  116. num_layers,
  117. bn_size,
  118. growth_rate,
  119. dropout,
  120. name=None):
  121. conv = input
  122. for layer in range(num_layers):
  123. conv = self.make_dense_layer(
  124. conv,
  125. growth_rate,
  126. bn_size,
  127. dropout,
  128. name=name + '_' + str(layer + 1))
  129. return conv
  130. def make_dense_layer(self, input, growth_rate, bn_size, dropout,
  131. name=None):
  132. bn_ac = fluid.layers.batch_norm(
  133. input,
  134. act='relu',
  135. param_attr=ParamAttr(name=name + '_x1_bn_scale'),
  136. bias_attr=ParamAttr(name + '_x1_bn_offset'),
  137. moving_mean_name=name + '_x1_bn_mean',
  138. moving_variance_name=name + '_x1_bn_variance')
  139. bn_ac_conv = fluid.layers.conv2d(
  140. input=bn_ac,
  141. num_filters=bn_size * growth_rate,
  142. filter_size=1,
  143. stride=1,
  144. act=None,
  145. bias_attr=False,
  146. param_attr=ParamAttr(name=name + "_x1_weights"))
  147. bn_ac = fluid.layers.batch_norm(
  148. bn_ac_conv,
  149. act='relu',
  150. param_attr=ParamAttr(name=name + '_x2_bn_scale'),
  151. bias_attr=ParamAttr(name + '_x2_bn_offset'),
  152. moving_mean_name=name + '_x2_bn_mean',
  153. moving_variance_name=name + '_x2_bn_variance')
  154. bn_ac_conv = fluid.layers.conv2d(
  155. input=bn_ac,
  156. num_filters=growth_rate,
  157. filter_size=3,
  158. stride=1,
  159. padding=1,
  160. act=None,
  161. bias_attr=False,
  162. param_attr=ParamAttr(name=name + "_x2_weights"))
  163. if dropout:
  164. bn_ac_conv = fluid.layers.dropout(
  165. x=bn_ac_conv, dropout_prob=dropout)
  166. bn_ac_conv = fluid.layers.concat([input, bn_ac_conv], axis=1)
  167. return bn_ac_conv