fix for keras applications preprocessing with channels_first symbolic tensors

The scaling by std deviation was not taking into account the channel order
and caused an error when a symbolic tensor was provided with mode='torch'
(e.g. for tf.keras.applications.densenet.preprocess_input).
This commit corrects that, and runs the tests for all modes instead of
just the default.
This commit is contained in:
Paul Klinger 2021-02-13 19:27:49 +00:00
parent 796af3d216
commit 0376b33c9e
2 changed files with 22 additions and 9 deletions

View File

@ -289,7 +289,10 @@ def _preprocess_symbolic_input(x, data_format, mode):
else:
x = backend.bias_add(x, mean_tensor, data_format)
if std is not None:
x /= std
std_tensor = backend.constant(np.array(std))
if data_format == "channels_first":
std_tensor = backend.reshape(std_tensor, (-1, 1, 1))
x /= std_tensor
return x

View File

@ -79,19 +79,28 @@ class TestImageNetUtils(keras_parameterized.TestCase):
xint2 = utils.preprocess_input(xint)
self.assertAllClose(x, x2[..., ::-1])
self.assertNotEqual(xint.astype('float').max(), xint2.max())
def test_preprocess_input_symbolic(self):
@parameterized.named_parameters([
{'testcase_name': 'mode_torch',
'mode': 'torch'},
{'testcase_name': 'mode_tf',
'mode': 'tf'},
{'testcase_name': 'mode_caffe',
'mode': 'caffe'},
])
def test_preprocess_input_symbolic(self, mode):
# Test image batch
x = np.random.uniform(0, 255, (2, 10, 10, 3))
inputs = keras.layers.Input(shape=x.shape[1:])
outputs = keras.layers.Lambda(
utils.preprocess_input, output_shape=x.shape[1:])(
lambda x: utils.preprocess_input(x, mode=mode),
output_shape=x.shape[1:])(
inputs)
model = keras.Model(inputs, outputs)
self.assertEqual(model.predict(x).shape, x.shape)
outputs1 = keras.layers.Lambda(
lambda x: utils.preprocess_input(x, 'channels_last'),
lambda x: utils.preprocess_input(x, 'channels_last', mode=mode),
output_shape=x.shape[1:])(
inputs)
model1 = keras.Model(inputs, outputs1)
@ -99,7 +108,7 @@ class TestImageNetUtils(keras_parameterized.TestCase):
x2 = np.transpose(x, (0, 3, 1, 2))
inputs2 = keras.layers.Input(shape=x2.shape[1:])
outputs2 = keras.layers.Lambda(
lambda x: utils.preprocess_input(x, 'channels_first'),
lambda x: utils.preprocess_input(x, 'channels_first', mode=mode),
output_shape=x2.shape[1:])(
inputs2)
model2 = keras.Model(inputs2, outputs2)
@ -110,13 +119,14 @@ class TestImageNetUtils(keras_parameterized.TestCase):
x = np.random.uniform(0, 255, (10, 10, 3))
inputs = keras.layers.Input(shape=x.shape)
outputs = keras.layers.Lambda(
utils.preprocess_input, output_shape=x.shape)(
lambda x: utils.preprocess_input(x, mode=mode),
output_shape=x.shape)(
inputs)
model = keras.Model(inputs, outputs)
self.assertEqual(model.predict(x[np.newaxis])[0].shape, x.shape)
outputs1 = keras.layers.Lambda(
lambda x: utils.preprocess_input(x, 'channels_last'),
lambda x: utils.preprocess_input(x, 'channels_last', mode=mode),
output_shape=x.shape)(
inputs)
model1 = keras.Model(inputs, outputs1)
@ -124,7 +134,7 @@ class TestImageNetUtils(keras_parameterized.TestCase):
x2 = np.transpose(x, (2, 0, 1))
inputs2 = keras.layers.Input(shape=x2.shape)
outputs2 = keras.layers.Lambda(
lambda x: utils.preprocess_input(x, 'channels_first'),
lambda x: utils.preprocess_input(x, 'channels_first', mode=mode),
output_shape=x2.shape)(
inputs2)
model2 = keras.Model(inputs2, outputs2)