Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/keras/src/layers/convolutional/base_depthwise_conv.py: 28%

43 statements  

« prev     ^ index     » next       coverage.py v7.4.0, created at 2024-01-03 07:57 +0000

1# Copyright 2015 The TensorFlow Authors. All Rights Reserved. 

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# ============================================================================== 

15"""Keras abstract base for depthwise convolutions.""" 

16 

17 

18import tensorflow.compat.v2 as tf 

19 

20from keras.src import constraints 

21from keras.src import initializers 

22from keras.src import regularizers 

23from keras.src.engine.input_spec import InputSpec 

24from keras.src.layers.convolutional.base_conv import Conv 

25 

26 

27class DepthwiseConv(Conv): 

28 """Depthwise convolution. 

29 

30 Depthwise convolution is a type of convolution in which each input channel 

31 is convolved with a different kernel (called a depthwise kernel). You can 

32 understand depthwise convolution as the first step in a depthwise separable 

33 convolution. 

34 

35 It is implemented via the following steps: 

36 

37 - Split the input into individual channels. 

38 - Convolve each channel with an individual depthwise kernel with 

39 `depth_multiplier` output channels. 

40 - Concatenate the convolved outputs along the channels axis. 

41 

42 Unlike a regular convolution, depthwise convolution does not mix 

43 information across different input channels. 

44 

45 The `depth_multiplier` argument determines how many filter are applied to 

46 one input channel. As such, it controls the amount of output channels that 

47 are generated per input channel in the depthwise step. 

48 

49 Args: 

50 kernel_size: A tuple or list of integers specifying the spatial dimensions 

51 of the filters. Can be a single integer to specify the same value for 

52 all spatial dimensions. 

53 strides: A tuple or list of integers specifying the strides of the 

54 convolution. Can be a single integer to specify the same value for all 

55 spatial dimensions. Specifying any `stride` value != 1 is incompatible 

56 with specifying any `dilation_rate` value != 1. 

57 padding: One of `"valid"` or `"same"` (case-insensitive). `"valid"` means 

58 no padding. `"same"` results in padding with zeros evenly to the 

59 left/right or up/down of the input such that output has the same 

60 height/width dimension as the input. 

61 depth_multiplier: The number of depthwise convolution output channels for 

62 each input channel. The total number of depthwise convolution output 

63 channels will be equal to `filters_in * depth_multiplier`. 

64 data_format: A string, one of `channels_last` (default) or 

65 `channels_first`. The ordering of the dimensions in the inputs. 

66 `channels_last` corresponds to inputs with shape `(batch_size, height, 

67 width, channels)` while `channels_first` corresponds to inputs with 

68 shape `(batch_size, channels, height, width)`. It defaults to the 

69 `image_data_format` value found in your Keras config file at 

70 `~/.keras/keras.json`. If you never set it, then it will be 

71 'channels_last'. 

72 dilation_rate: An integer or tuple/list of 2 integers, specifying the 

73 dilation rate to use for dilated convolution. Currently, specifying any 

74 `dilation_rate` value != 1 is incompatible with specifying any `strides` 

75 value != 1. 

76 activation: Activation function to use. If you don't specify anything, no 

77 activation is applied (see `keras.activations`). 

78 use_bias: Boolean, whether the layer uses a bias vector. 

79 depthwise_initializer: Initializer for the depthwise kernel matrix (see 

80 `keras.initializers`). If None, the default initializer 

81 ('glorot_uniform') will be used. 

82 bias_initializer: Initializer for the bias vector (see 

83 `keras.initializers`). If None, the default initializer ('zeros') will 

84 be used. 

85 depthwise_regularizer: Regularizer function applied to the depthwise 

86 kernel matrix (see `keras.regularizers`). 

87 bias_regularizer: Regularizer function applied to the bias vector (see 

88 `keras.regularizers`). 

89 activity_regularizer: Regularizer function applied to the output of the 

90 layer (its 'activation') (see `keras.regularizers`). 

91 depthwise_constraint: Constraint function applied to the depthwise kernel 

92 matrix (see `keras.constraints`). 

93 bias_constraint: Constraint function applied to the bias vector (see 

94 `keras.constraints`). 

95 

96 Input shape: 

97 4D tensor with shape: `[batch_size, channels, rows, cols]` if 

98 data_format='channels_first' 

99 or 4D tensor with shape: `[batch_size, rows, cols, channels]` if 

100 data_format='channels_last'. 

101 

102 Output shape: 

103 4D tensor with shape: `[batch_size, channels * depth_multiplier, new_rows, 

104 new_cols]` if `data_format='channels_first'` 

105 or 4D tensor with shape: `[batch_size, 

106 new_rows, new_cols, channels * depth_multiplier]` if 

107 `data_format='channels_last'`. `rows` and `cols` values might have 

108 changed due to padding. 

109 

110 Returns: 

111 A tensor of rank 4 representing 

112 `activation(depthwiseconv2d(inputs, kernel) + bias)`. 

113 

114 Raises: 

115 ValueError: if `padding` is "causal". 

116 ValueError: when both `strides` > 1 and `dilation_rate` > 1. 

117 """ 

118 

119 def __init__( 

120 self, 

121 rank, 

122 kernel_size, 

123 strides=1, 

124 padding="valid", 

125 depth_multiplier=1, 

126 data_format=None, 

127 dilation_rate=1, 

128 activation=None, 

129 use_bias=True, 

130 depthwise_initializer="glorot_uniform", 

131 bias_initializer="zeros", 

132 depthwise_regularizer=None, 

133 bias_regularizer=None, 

134 activity_regularizer=None, 

135 depthwise_constraint=None, 

136 bias_constraint=None, 

137 **kwargs, 

138 ): 

139 super().__init__( 

140 rank, 

141 filters=None, 

142 kernel_size=kernel_size, 

143 strides=strides, 

144 padding=padding, 

145 data_format=data_format, 

146 dilation_rate=dilation_rate, 

147 activation=activation, 

148 use_bias=use_bias, 

149 bias_regularizer=bias_regularizer, 

150 activity_regularizer=activity_regularizer, 

151 bias_constraint=bias_constraint, 

152 **kwargs, 

153 ) 

154 self.depth_multiplier = depth_multiplier 

155 self.depthwise_initializer = initializers.get(depthwise_initializer) 

156 self.depthwise_regularizer = regularizers.get(depthwise_regularizer) 

157 self.depthwise_constraint = constraints.get(depthwise_constraint) 

158 self.bias_initializer = initializers.get(bias_initializer) 

159 

160 def build(self, input_shape): 

161 if len(input_shape) != self.rank + 2: 

162 raise ValueError( 

163 "Inputs to `DepthwiseConv` should have " 

164 f"rank {self.rank + 2}. " 

165 f"Received input_shape={input_shape}." 

166 ) 

167 input_shape = tf.TensorShape(input_shape) 

168 channel_axis = self._get_channel_axis() 

169 if input_shape.dims[channel_axis].value is None: 

170 raise ValueError( 

171 "The channel dimension of the inputs to `DepthwiseConv` " 

172 "should be defined. " 

173 f"The input_shape received is {input_shape}, " 

174 f"where axis {channel_axis} (0-based) " 

175 "is the channel dimension, which found to be `None`." 

176 ) 

177 input_dim = int(input_shape[channel_axis]) 

178 depthwise_kernel_shape = self.kernel_size + ( 

179 input_dim, 

180 self.depth_multiplier, 

181 ) 

182 

183 self.depthwise_kernel = self.add_weight( 

184 shape=depthwise_kernel_shape, 

185 initializer=self.depthwise_initializer, 

186 name="depthwise_kernel", 

187 regularizer=self.depthwise_regularizer, 

188 constraint=self.depthwise_constraint, 

189 ) 

190 

191 if self.use_bias: 

192 self.bias = self.add_weight( 

193 shape=(input_dim * self.depth_multiplier,), 

194 initializer=self.bias_initializer, 

195 name="bias", 

196 regularizer=self.bias_regularizer, 

197 constraint=self.bias_constraint, 

198 ) 

199 else: 

200 self.bias = None 

201 # Set input spec. 

202 self.input_spec = InputSpec( 

203 min_ndim=self.rank + 2, axes={channel_axis: input_dim} 

204 ) 

205 self.built = True 

206 

207 def call(self, inputs): 

208 raise NotImplementedError 

209 

210 def get_config(self): 

211 config = super().get_config() 

212 config.pop("filters") 

213 config.pop("kernel_initializer") 

214 config.pop("kernel_regularizer") 

215 config.pop("kernel_constraint") 

216 config["depth_multiplier"] = self.depth_multiplier 

217 config["depthwise_initializer"] = initializers.serialize( 

218 self.depthwise_initializer 

219 ) 

220 config["depthwise_regularizer"] = regularizers.serialize( 

221 self.depthwise_regularizer 

222 ) 

223 config["depthwise_constraint"] = constraints.serialize( 

224 self.depthwise_constraint 

225 ) 

226 return config 

227