You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

depthwise_conv.py 6.5 kB

4 years ago
4 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. #! /usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. import tensorlayer as tl
  4. from tensorlayer import logging
  5. from tensorlayer.layers.core import Module
  6. from tensorlayer.backend import BACKEND
  7. __all__ = [
  8. 'DepthwiseConv2d',
  9. ]
  10. class DepthwiseConv2d(Module):
  11. """Separable/Depthwise Convolutional 2D layer, see `tf.nn.depthwise_conv2d <https://tensorflow.google.cn/versions/r2.0/api_docs/python/tf/nn/depthwise_conv2d>`__.
  12. Input:
  13. 4-D Tensor (batch, height, width, in_channels).
  14. Output:
  15. 4-D Tensor (batch, new height, new width, in_channels * depth_multiplier).
  16. Parameters
  17. ------------
  18. filter_size : tuple of 2 int
  19. The filter size (height, width).
  20. strides : tuple of 2 int
  21. The stride step (height, width).
  22. act : activation function
  23. The activation function of this layer.
  24. padding : str
  25. The padding algorithm type: "SAME" or "VALID".
  26. data_format : str
  27. "channels_last" (NHWC, default) or "channels_first" (NCHW).
  28. dilation_rate: tuple of 2 int
  29. The dilation rate in which we sample input values across the height and width dimensions in atrous convolution. If it is greater than 1, then all values of strides must be 1.
  30. depth_multiplier : int
  31. The number of channels to expand to.
  32. W_init : initializer
  33. The initializer for the weight matrix.
  34. b_init : initializer or None
  35. The initializer for the bias vector. If None, skip bias.
  36. in_channels : int
  37. The number of in channels.
  38. name : str
  39. A unique layer name.
  40. Examples
  41. ---------
  42. With TensorLayer
  43. >>> net = tl.layers.Input([8, 200, 200, 32], name='input')
  44. >>> depthwiseconv2d = tl.layers.DepthwiseConv2d(
  45. ... filter_size=(3, 3), strides=(1, 1), dilation_rate=(2, 2), act=tl.ReLU, depth_multiplier=2, name='depthwise'
  46. ... )(net)
  47. >>> print(depthwiseconv2d)
  48. >>> output shape : (8, 200, 200, 64)
  49. References
  50. -----------
  51. - tflearn's `grouped_conv_2d <https://github.com/tflearn/tflearn/blob/3e0c3298ff508394f3ef191bcd7d732eb8860b2e/tflearn/layers/conv.py>`__
  52. - keras's `separableconv2d <https://keras.io/layers/convolutional/#separableconv2d>`__
  53. """
  54. # https://zhuanlan.zhihu.com/p/31551004 https://github.com/xiaohu2015/DeepLearning_tutorials/blob/master/CNNs/MobileNet.py
  55. def __init__(
  56. self,
  57. filter_size=(3, 3),
  58. strides=(1, 1),
  59. act=None,
  60. padding='SAME',
  61. data_format='channels_last',
  62. dilation_rate=(1, 1),
  63. depth_multiplier=1,
  64. W_init=tl.initializers.truncated_normal(stddev=0.02),
  65. b_init=tl.initializers.constant(value=0.0),
  66. in_channels=None,
  67. name=None # 'depthwise_conv2d'
  68. ):
  69. super().__init__(name, act=act)
  70. self.filter_size = filter_size
  71. self.strides = self._strides = strides
  72. self.padding = padding
  73. self.dilation_rate = self._dilation_rate = dilation_rate
  74. self.data_format = data_format
  75. self.depth_multiplier = depth_multiplier
  76. self.W_init = W_init
  77. self.b_init = b_init
  78. self.in_channels = in_channels
  79. if self.in_channels:
  80. self.build(None)
  81. self._built = True
  82. logging.info(
  83. "DepthwiseConv2d %s: filter_size: %s strides: %s pad: %s act: %s" % (
  84. self.name, str(filter_size), str(strides), padding,
  85. self.act.__class__.__name__ if self.act is not None else 'No Activation'
  86. )
  87. )
  88. def __repr__(self):
  89. actstr = self.act.__class__.__name__ if self.act is not None else 'No Activation'
  90. s = (
  91. '{classname}(in_channels={in_channels}, out_channels={n_filter}, kernel_size={filter_size}'
  92. ', strides={strides}, padding={padding}'
  93. )
  94. if self.dilation_rate != (1, ) * len(self.dilation_rate):
  95. s += ', dilation={dilation_rate}'
  96. if self.b_init is None:
  97. s += ', bias=False'
  98. s += (', ' + actstr)
  99. if self.name is not None:
  100. s += ', name=\'{name}\''
  101. s += ')'
  102. return s.format(
  103. classname=self.__class__.__name__, n_filter=self.in_channels * self.depth_multiplier, **self.__dict__
  104. )
  105. def build(self, inputs_shape):
  106. if self.data_format == 'channels_last':
  107. self.data_format = 'NHWC'
  108. if self.in_channels is None:
  109. self.in_channels = inputs_shape[-1]
  110. self._strides = [1, self._strides[0], self._strides[1], 1]
  111. elif self.data_format == 'channels_first':
  112. self.data_format = 'NCHW'
  113. if self.in_channels is None:
  114. self.in_channels = inputs_shape[1]
  115. self._strides = [1, 1, self._strides[0], self._strides[1]]
  116. else:
  117. raise Exception("data_format should be either channels_last or channels_first")
  118. self.filter_shape = (self.filter_size[0], self.filter_size[1], self.in_channels, self.depth_multiplier)
  119. # Set the size of kernel as (K1,K2), then the shape is (K,Cin,K1,K2), K must be 1.
  120. if BACKEND == 'mindspore':
  121. self.filter_shape = (self.filter_size[0], self.filter_size[1], self.in_channels, 1)
  122. self.W = self._get_weights("filters", shape=self.filter_shape, init=self.W_init, transposed=True)
  123. self.depthwise_conv2d = tl.ops.DepthwiseConv2d(
  124. strides=self._strides, padding=self.padding, data_format=self.data_format, dilations=self._dilation_rate,
  125. ksize=self.filter_size, channel_multiplier=self.depth_multiplier
  126. )
  127. self.b_init_flag = False
  128. if self.b_init:
  129. self.b = self._get_weights("biases", shape=(self.in_channels * self.depth_multiplier, ), init=self.b_init)
  130. self.bias_add = tl.ops.BiasAdd(self.data_format)
  131. self.b_init_flag = True
  132. self.act_init_flag = False
  133. if self.act:
  134. self.act_init_flag = True
  135. def forward(self, inputs):
  136. if self._forward_state == False:
  137. if self._built == False:
  138. self.build(tl.get_tensor_shape(inputs))
  139. self._built = True
  140. self._forward_state = True
  141. outputs = self.depthwise_conv2d(input=inputs, filter=self.W)
  142. if self.b_init_flag:
  143. outputs = self.bias_add(outputs, self.b)
  144. if self.act_init_flag:
  145. outputs = self.act(outputs)
  146. return outputs

TensorLayer3.0 是一款兼容多种深度学习框架为计算后端的深度学习库。计划兼容TensorFlow, Pytorch, MindSpore, Paddle.