Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removes caching of the convolution tf.nn.convolution op. While this provided some performance benefits, it also produced some surprising behavior for users in eager mode. #14855

Merged
merged 1 commit into from
Jul 2, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 23 additions & 29 deletions keras/layers/convolutional.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,16 @@
# limitations under the License.
# ==============================================================================
"""Keras convolution layers and image transformation layers."""

# pylint:disable=g-bad-import-order
import tensorflow.compat.v2 as tf

import functools
from keras import activations
from keras import backend
from keras import constraints
from keras import initializers
from keras import regularizers
from keras.engine.base_layer import Layer
from keras.engine.input_spec import InputSpec
# imports for backwards namespace compatibility
# pylint: disable=unused-import
from keras.layers.pooling import AveragePooling1D
from keras.layers.pooling import AveragePooling2D
Expand All @@ -35,6 +33,7 @@
# pylint: enable=unused-import
from keras.utils import conv_utils
from keras.utils import tf_utils

from tensorflow.python.util.tf_export import keras_export
# pylint: disable=g-classes-have-attributes

Expand Down Expand Up @@ -84,8 +83,8 @@ class Conv(Layer):
activation: Activation function to use.
If you don't specify anything, no activation is applied.
use_bias: Boolean, whether the layer uses a bias.
kernel_initializer: An initializer for the convolution kernel. If None, the
default initializer (glorot_uniform) will be used.
kernel_initializer: An initializer for the convolution kernel. If None, the
default initializer (glorot_uniform) will be used.
bias_initializer: An initializer for the bias vector. If None, the default
initializer (zeros) will be used.
kernel_regularizer: Optional regularizer for the convolution kernel.
Expand Down Expand Up @@ -157,7 +156,6 @@ def __init__(self,
self.input_spec = InputSpec(min_ndim=self.rank + 2)

self._validate_init()
self._is_causal = self.padding == 'causal'
self._channels_first = self.data_format == 'channels_first'
self._tf_data_format = conv_utils.convert_data_format(
self.data_format, self.rank + 2)
Expand Down Expand Up @@ -214,39 +212,35 @@ def build(self, input_shape):
else:
self.bias = None
channel_axis = self._get_channel_axis()
self.input_spec = InputSpec(min_ndim=self.rank + 2,
axes={channel_axis: input_channel})
self.input_spec = InputSpec(
min_ndim=self.rank + 2, axes={channel_axis: input_channel})
self.built = True

def call(self, inputs):
input_shape = inputs.shape

# Convert Keras formats to TF native formats.
if self.padding == 'causal':
# Apply causal padding to inputs for Conv1D.
inputs = tf.pad(inputs, self._compute_causal_padding(inputs))
tf_padding = 'VALID' # Causal padding handled in `call`.
elif isinstance(self.padding, str):
tf_padding = self.padding.upper()
else:
tf_padding = self.padding
tf_dilations = list(self.dilation_rate)
tf_strides = list(self.strides)

tf_op_name = self.__class__.__name__
if tf_op_name == 'Conv1D':
tf_op_name = 'conv1d' # Backwards compat.

self._convolution_op = functools.partial(
tf.nn.convolution,
strides=tf_strides,
outputs = tf.nn.convolution(
inputs,
self.kernel,
padding=tf_padding,
dilations=tf_dilations,
strides=list(self.strides),
dilations=list(self.dilation_rate),
data_format=self._tf_data_format,
name=tf_op_name)
self.built = True

def call(self, inputs):
input_shape = inputs.shape

if self._is_causal: # Apply causal padding to inputs for Conv1D.
inputs = tf.pad(inputs, self._compute_causal_padding(inputs))

outputs = self._convolution_op(inputs, self.kernel)

if self.use_bias:
output_rank = outputs.shape.rank
Expand Down Expand Up @@ -610,9 +604,9 @@ class Conv2D(Conv):
bias_initializer: Initializer for the bias vector (see
`keras.initializers`). Defaults to 'zeros'.
kernel_regularizer: Regularizer function applied to the `kernel` weights
matrix (see `keras.regularizers`).
matrix (see `keras.regularizers`).
bias_regularizer: Regularizer function applied to the bias vector (see
`keras.regularizers`).
`keras.regularizers`).
activity_regularizer: Regularizer function applied to the output of the
layer (its "activation") (see `keras.regularizers`).
kernel_constraint: Constraint function applied to the kernel matrix (see
Expand Down Expand Up @@ -1735,7 +1729,7 @@ class SeparableConv(Conv):
see `keras.initializers`). If None, then the default initializer (
'glorot_uniform') will be used.
pointwise_initializer: An initializer for the pointwise convolution kernel (
see `keras.initializers`). If None, then the default initializer
see `keras.initializers`). If None, then the default initializer
('glorot_uniform') will be used.
bias_initializer: An initializer for the bias vector. If None, the default
initializer ('zeros') will be used (see `keras.initializers`).
Expand Down Expand Up @@ -1944,7 +1938,7 @@ class SeparableConv1D(SeparableConv):
see `keras.initializers`). If None, then the default initializer (
'glorot_uniform') will be used.
pointwise_initializer: An initializer for the pointwise convolution kernel (
see `keras.initializers`). If None, then the default initializer
see `keras.initializers`). If None, then the default initializer
('glorot_uniform') will be used.
bias_initializer: An initializer for the bias vector. If None, the default
initializer ('zeros') will be used (see `keras.initializers`).
Expand Down Expand Up @@ -2106,7 +2100,7 @@ class SeparableConv2D(SeparableConv):
strides: An integer or tuple/list of 2 integers,
specifying the strides of the convolution along the height and width.
Can be a single integer to specify the same value for
all spatial dimensions. Current implementation only supports equal
all spatial dimensions. Current implementation only supports equal
length strides in the row and column dimensions.
Specifying any stride value != 1 is incompatible with specifying
any `dilation_rate` value != 1.
Expand Down Expand Up @@ -2140,7 +2134,7 @@ class SeparableConv2D(SeparableConv):
see `keras.initializers`). If None, then the default initializer (
'glorot_uniform') will be used.
pointwise_initializer: An initializer for the pointwise convolution kernel (
see `keras.initializers`). If None, then the default initializer
see `keras.initializers`). If None, then the default initializer
('glorot_uniform') will be used.
bias_initializer: An initializer for the bias vector. If None, the default
initializer ('zeros') will be used (see `keras.initializers`).
Expand Down