densenet.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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. from collections import OrderedDict
  18. import paddle
  19. import paddle.fluid as fluid
  20. import math
  21. from paddle.fluid.param_attr import ParamAttr
  22. __all__ = ["DenseNet"]
  23. class DenseNet(object):
  24. def __init__(self, layers=121, bn_size=4, dropout=0, num_classes=None):
  25. assert layers in [121, 161, 169, 201, 264], \
  26. "supported layers are {} but input layer is {}".format(supported_layers, layers)
  27. self.layers = layers
  28. self.bn_size = bn_size
  29. self.dropout = dropout
  30. self.num_classes = num_classes
  31. def __call__(self, input):
  32. layers = self.layers
  33. densenet_spec = {
  34. 121: (64, 32, [6, 12, 24, 16]),
  35. 161: (96, 48, [6, 12, 36, 24]),
  36. 169: (64, 32, [6, 12, 32, 32]),
  37. 201: (64, 32, [6, 12, 48, 32]),
  38. 264: (64, 32, [6, 12, 64, 48])
  39. }
  40. num_init_features, growth_rate, block_config = densenet_spec[layers]
  41. conv = fluid.layers.conv2d(
  42. input=input,
  43. num_filters=num_init_features,
  44. filter_size=7,
  45. stride=2,
  46. padding=3,
  47. act=None,
  48. param_attr=ParamAttr(name="conv1_weights"),
  49. bias_attr=False)
  50. conv = fluid.layers.batch_norm(
  51. input=conv,
  52. act='relu',
  53. param_attr=ParamAttr(name='conv1_bn_scale'),
  54. bias_attr=ParamAttr(name='conv1_bn_offset'),
  55. moving_mean_name='conv1_bn_mean',
  56. moving_variance_name='conv1_bn_variance')
  57. conv = fluid.layers.pool2d(
  58. input=conv,
  59. pool_size=3,
  60. pool_stride=2,
  61. pool_padding=1,
  62. pool_type='max')
  63. num_features = num_init_features
  64. for i, num_layers in enumerate(block_config):
  65. conv = self.make_dense_block(
  66. conv,
  67. num_layers,
  68. self.bn_size,
  69. growth_rate,
  70. self.dropout,
  71. name='conv' + str(i + 2))
  72. num_features = num_features + num_layers * growth_rate
  73. if i != len(block_config) - 1:
  74. conv = self.make_transition(
  75. conv, num_features // 2, name='conv' + str(i + 2) + '_blk')
  76. num_features = num_features // 2
  77. conv = fluid.layers.batch_norm(
  78. input=conv,
  79. act='relu',
  80. param_attr=ParamAttr(name='conv5_blk_bn_scale'),
  81. bias_attr=ParamAttr(name='conv5_blk_bn_offset'),
  82. moving_mean_name='conv5_blk_bn_mean',
  83. moving_variance_name='conv5_blk_bn_variance')
  84. if self.num_classes:
  85. conv = fluid.layers.pool2d(
  86. input=conv, pool_type='avg', global_pooling=True)
  87. stdv = 1.0 / math.sqrt(conv.shape[1] * 1.0)
  88. out = fluid.layers.fc(
  89. input=conv,
  90. size=self.num_classes,
  91. param_attr=fluid.param_attr.ParamAttr(
  92. initializer=fluid.initializer.Uniform(-stdv, stdv),
  93. name="fc_weights"),
  94. bias_attr=ParamAttr(name='fc_offset'))
  95. return OrderedDict([('logits', out)])
  96. def make_transition(self, input, num_output_features, name=None):
  97. bn_ac = fluid.layers.batch_norm(
  98. input,
  99. act='relu',
  100. param_attr=ParamAttr(name=name + '_bn_scale'),
  101. bias_attr=ParamAttr(name + '_bn_offset'),
  102. moving_mean_name=name + '_bn_mean',
  103. moving_variance_name=name + '_bn_variance')
  104. bn_ac_conv = fluid.layers.conv2d(
  105. input=bn_ac,
  106. num_filters=num_output_features,
  107. filter_size=1,
  108. stride=1,
  109. act=None,
  110. bias_attr=False,
  111. param_attr=ParamAttr(name=name + "_weights"))
  112. pool = fluid.layers.pool2d(
  113. input=bn_ac_conv, pool_size=2, pool_stride=2, pool_type='avg')
  114. return pool
  115. def make_dense_block(self,
  116. input,
  117. num_layers,
  118. bn_size,
  119. growth_rate,
  120. dropout,
  121. name=None):
  122. conv = input
  123. for layer in range(num_layers):
  124. conv = self.make_dense_layer(
  125. conv,
  126. growth_rate,
  127. bn_size,
  128. dropout,
  129. name=name + '_' + str(layer + 1))
  130. return conv
  131. def make_dense_layer(self, input, growth_rate, bn_size, dropout,
  132. name=None):
  133. bn_ac = fluid.layers.batch_norm(
  134. input,
  135. act='relu',
  136. param_attr=ParamAttr(name=name + '_x1_bn_scale'),
  137. bias_attr=ParamAttr(name + '_x1_bn_offset'),
  138. moving_mean_name=name + '_x1_bn_mean',
  139. moving_variance_name=name + '_x1_bn_variance')
  140. bn_ac_conv = fluid.layers.conv2d(
  141. input=bn_ac,
  142. num_filters=bn_size * growth_rate,
  143. filter_size=1,
  144. stride=1,
  145. act=None,
  146. bias_attr=False,
  147. param_attr=ParamAttr(name=name + "_x1_weights"))
  148. bn_ac = fluid.layers.batch_norm(
  149. bn_ac_conv,
  150. act='relu',
  151. param_attr=ParamAttr(name=name + '_x2_bn_scale'),
  152. bias_attr=ParamAttr(name + '_x2_bn_offset'),
  153. moving_mean_name=name + '_x2_bn_mean',
  154. moving_variance_name=name + '_x2_bn_variance')
  155. bn_ac_conv = fluid.layers.conv2d(
  156. input=bn_ac,
  157. num_filters=growth_rate,
  158. filter_size=3,
  159. stride=1,
  160. padding=1,
  161. act=None,
  162. bias_attr=False,
  163. param_attr=ParamAttr(name=name + "_x2_weights"))
  164. if dropout:
  165. bn_ac_conv = fluid.layers.dropout(
  166. x=bn_ac_conv, dropout_prob=dropout)
  167. bn_ac_conv = fluid.layers.concat([input, bn_ac_conv], axis=1)
  168. return bn_ac_conv