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
« 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."""
18import tensorflow.compat.v2 as tf
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
27class DepthwiseConv(Conv):
28 """Depthwise convolution.
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.
35 It is implemented via the following steps:
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.
42 Unlike a regular convolution, depthwise convolution does not mix
43 information across different input channels.
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.
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`).
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'.
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.
110 Returns:
111 A tensor of rank 4 representing
112 `activation(depthwiseconv2d(inputs, kernel) + bias)`.
114 Raises:
115 ValueError: if `padding` is "causal".
116 ValueError: when both `strides` > 1 and `dilation_rate` > 1.
117 """
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)
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 )
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 )
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
207 def call(self, inputs):
208 raise NotImplementedError
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