From 04931e95c68157e2553f315775d281be70541986 Mon Sep 17 00:00:00 2001 From: Malyala Karthik Date: Sat, 15 Nov 2025 12:03:31 +0530 Subject: [PATCH 1/2] Fix Conv3DTranspose padding conversion for torch backend --- keras/src/backend/common/backend_utils.py | 28 +++++++++++++++---- .../src/backend/common/backend_utils_test.py | 19 +++++++++++++ 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/keras/src/backend/common/backend_utils.py b/keras/src/backend/common/backend_utils.py index fb809c2cc7b2..fc700b3e33be 100644 --- a/keras/src/backend/common/backend_utils.py +++ b/keras/src/backend/common/backend_utils.py @@ -96,13 +96,13 @@ def _convert_conv_transpose_padding_args_from_keras_to_torch( ) if torch_output_padding >= stride: - raise ValueError( - f"The padding arguments (padding={padding}) and " - f"output_padding={output_padding}) lead to a Torch " - f"output_padding ({torch_output_padding}) that is greater than " - f"strides ({stride}). This is not supported. You can change the " - f"padding arguments, kernel or stride, or run on another backend. " + warnings.warn( + f"Torch backend requires output_padding < stride. " + f"Clamping output_padding {torch_output_padding} -> {stride - 1} " + f"for stride {stride}.", + UserWarning, ) + torch_output_padding = stride - 1 return torch_padding, torch_output_padding @@ -184,6 +184,22 @@ def compute_conv_transpose_padding_args_for_torch( torch_paddings.append(torch_padding) torch_output_paddings.append(torch_output_padding) + # --- FIX FOR TORCH CONSTRAINT: output_padding < stride --- + corrected_output_paddings = [] + for s, op in zip( + strides + if isinstance(strides, (list, tuple)) + else [strides] * num_spatial_dims, + torch_output_paddings, + ): + max_allowed = max(0, s - 1) + if op > max_allowed: + corrected_output_paddings.append(max_allowed) + else: + corrected_output_paddings.append(op) + + torch_output_paddings = corrected_output_paddings + return torch_paddings, torch_output_paddings diff --git a/keras/src/backend/common/backend_utils_test.py b/keras/src/backend/common/backend_utils_test.py index deea5fc17267..80a1ff813d50 100644 --- a/keras/src/backend/common/backend_utils_test.py +++ b/keras/src/backend/common/backend_utils_test.py @@ -170,6 +170,25 @@ def test_valid_padding_with_output_padding(self): self.assertEqual(torch_padding, 0) self.assertEqual(torch_output_padding, 1) + def test_output_padding_clamped_for_torch_constraint(self): + """Test that output_padding is clamped + when >= stride (Torch constraint). + """ + ( + torch_paddings, + torch_output_paddings, + ) = compute_conv_transpose_padding_args_for_torch( + input_shape=(1, 8, 8, 8, 16), # any shape + kernel_shape=(2, 2, 2, 16, 32), # Keras kernel shape + strides=1, + padding="same", + output_padding=1, # Keras wants this + dilation_rate=1, + ) + # Torch expects output_padding < stride (1) + # so output_padding should be clamped to 0 + self.assertEqual(torch_output_paddings, [0, 0, 0]) + class GetOutputShapeGivenTFPaddingTest(test_case.TestCase): def test_valid_padding_without_output_padding(self): From 0f9fd4df46c2bd66fc29b5f3b5b36369376cbc16 Mon Sep 17 00:00:00 2001 From: Malyala Karthik Date: Sat, 15 Nov 2025 20:11:05 +0530 Subject: [PATCH 2/2] Fix Conv3DTranspose padding conversion for torch backend --- .../convolutional/conv_transpose_test.py | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/keras/src/layers/convolutional/conv_transpose_test.py b/keras/src/layers/convolutional/conv_transpose_test.py index 89c5bd65e782..307a9bed9d17 100644 --- a/keras/src/layers/convolutional/conv_transpose_test.py +++ b/keras/src/layers/convolutional/conv_transpose_test.py @@ -825,21 +825,30 @@ def test_conv1d_transpose_consistency( # Special cases for Torch if backend.backend() == "torch": - # The following set of arguments lead to Torch output padding to be - # greater than strides, which is not supported by Torch. - # An error is raised. + # Args that cause output_padding >= strides + # are clamped with a warning. if (kernel_size, strides, padding, output_padding) in [ (2, 1, "same", None), (4, 1, "same", None), ]: - with pytest.raises(ValueError): + clamped_output_padding = strides - 1 # usually 0 when stride=1 + expected_res = np_conv1d_transpose( + x=input, + kernel_weights=kernel_weights, + bias_weights=np.zeros(shape=(1,)), + strides=strides, + padding=padding, + output_padding=clamped_output_padding, + data_format=backend.config.image_data_format(), + dilation_rate=1, + ) + with pytest.warns(UserWarning): kc_res = kc_layer(input) + self.assertAllClose(expected_res, kc_res, atol=1e-5) return - # When both torch_padding and torch_output_padding are greater - # than 0, Torch outputs are inconsistent with the ones from - # Tensorflow. A warning is raised, and we expect the results to be - # different. + # torch_padding > 0 and torch_output_padding > 0 case + # Torch output differs from TF. ( torch_padding, torch_output_padding,