From 83ed5aad57de972ffc0708fae63772e5e62df69c Mon Sep 17 00:00:00 2001 From: Francois Chollet Date: Mon, 25 May 2020 14:02:01 -0700 Subject: [PATCH] Add `offset` argument to `Rescaling`. PiperOrigin-RevId: 313101675 Change-Id: Id59e6dcbe4f038d627c7d71fdf4dfeb58e8e05cd --- .../preprocessing/image_preprocessing.py | 18 ++++++++++++++---- .../preprocessing/image_preprocessing_test.py | 10 +++++----- ...experimental.preprocessing.-rescaling.pbtxt | 2 +- ...experimental.preprocessing.-rescaling.pbtxt | 2 +- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/tensorflow/python/keras/layers/preprocessing/image_preprocessing.py b/tensorflow/python/keras/layers/preprocessing/image_preprocessing.py index 832915dac68..e4b92e44e69 100644 --- a/tensorflow/python/keras/layers/preprocessing/image_preprocessing.py +++ b/tensorflow/python/keras/layers/preprocessing/image_preprocessing.py @@ -292,11 +292,16 @@ class RandomCrop(Layer): @keras_export('keras.layers.experimental.preprocessing.Rescaling') class Rescaling(Layer): - """Multiply inputs by `scale`. + """Multiply inputs by `scale` and adds `offset`. - For instance, to rescale an input in the `[0, 255]` range + For instance: + + 1. To rescale an input in the `[0, 255]` range to be in the `[0, 1]` range, you would pass `scale=1./255`. + 2. To rescale an input in the `[0, 255]` range to be in the `[-1, 1]` range, + you would pass `scale=1./127.5, offset=-1`. + The rescaling is applied both during training and inference. Input shape: @@ -307,16 +312,20 @@ class Rescaling(Layer): Arguments: scale: Float, the scale to apply to the inputs. + offset: Float, the offset to apply to the inputs. name: A string, the name of the layer. """ - def __init__(self, scale, name=None, **kwargs): + def __init__(self, scale, offset=0., name=None, **kwargs): self.scale = scale + self.offset = offset super(Rescaling, self).__init__(name=name, **kwargs) def call(self, inputs): dtype = self._compute_dtype - return math_ops.cast(inputs, dtype) * math_ops.cast(self.scale, dtype) + scale = math_ops.cast(self.scale, dtype) + offset = math_ops.cast(self.offset, dtype) + return math_ops.cast(inputs, dtype) * scale + offset def compute_output_shape(self, input_shape): return input_shape @@ -324,6 +333,7 @@ class Rescaling(Layer): def get_config(self): config = { 'scale': self.scale, + 'offset': self.offset, } base_config = super(Rescaling, self).get_config() return dict(list(base_config.items()) + list(config.items())) diff --git a/tensorflow/python/keras/layers/preprocessing/image_preprocessing_test.py b/tensorflow/python/keras/layers/preprocessing/image_preprocessing_test.py index 38d2d25916a..14720d3541d 100644 --- a/tensorflow/python/keras/layers/preprocessing/image_preprocessing_test.py +++ b/tensorflow/python/keras/layers/preprocessing/image_preprocessing_test.py @@ -306,7 +306,7 @@ class RescalingTest(keras_parameterized.TestCase): @keras_parameterized.run_all_keras_modes(always_skip_v1=True) def test_rescaling_base(self): - kwargs = {'scale': 0.004} + kwargs = {'scale': 1./127.5, 'offset': -1.} testing_utils.layer_test( image_preprocessing.Rescaling, kwargs=kwargs, @@ -315,18 +315,18 @@ class RescalingTest(keras_parameterized.TestCase): @tf_test_util.run_v2_only def test_rescaling_correctness_float(self): - layer = image_preprocessing.Rescaling(0.004) + layer = image_preprocessing.Rescaling(scale=1./127.5, offset=-1.) inputs = random_ops.random_uniform((2, 4, 5, 3)) outputs = layer(inputs) - self.assertAllClose(outputs.numpy(), inputs.numpy() * 0.004) + self.assertAllClose(outputs.numpy(), inputs.numpy() * (1./127.5) - 1) @tf_test_util.run_v2_only def test_rescaling_correctness_int(self): - layer = image_preprocessing.Rescaling(0.004) + layer = image_preprocessing.Rescaling(scale=1./127.5, offset=-1) inputs = random_ops.random_uniform((2, 4, 5, 3), 0, 100, dtype='int32') outputs = layer(inputs) self.assertEqual(outputs.dtype.name, 'float32') - self.assertAllClose(outputs.numpy(), inputs.numpy() * 0.004) + self.assertAllClose(outputs.numpy(), inputs.numpy() * (1./127.5) - 1) def test_config_with_custom_name(self): layer = image_preprocessing.Rescaling(0.5, name='rescaling') diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.experimental.preprocessing.-rescaling.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.experimental.preprocessing.-rescaling.pbtxt index 7036fb926a8..60c0bc92f81 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.experimental.preprocessing.-rescaling.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.experimental.preprocessing.-rescaling.pbtxt @@ -113,7 +113,7 @@ tf_class { } member_method { name: "__init__" - argspec: "args=[\'self\', \'scale\', \'name\'], varargs=None, keywords=kwargs, defaults=[\'None\'], " + argspec: "args=[\'self\', \'scale\', \'offset\', \'name\'], varargs=None, keywords=kwargs, defaults=[\'0.0\', \'None\'], " } member_method { name: "add_loss" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.experimental.preprocessing.-rescaling.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.experimental.preprocessing.-rescaling.pbtxt index 7036fb926a8..60c0bc92f81 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.experimental.preprocessing.-rescaling.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.experimental.preprocessing.-rescaling.pbtxt @@ -113,7 +113,7 @@ tf_class { } member_method { name: "__init__" - argspec: "args=[\'self\', \'scale\', \'name\'], varargs=None, keywords=kwargs, defaults=[\'None\'], " + argspec: "args=[\'self\', \'scale\', \'offset\', \'name\'], varargs=None, keywords=kwargs, defaults=[\'0.0\', \'None\'], " } member_method { name: "add_loss"