keras-team/keras · error · ValueError

Expected the 2 dimensions of the `dilation_rate` argument to

Error message

Expected the 2 dimensions of the `dilation_rate` argument to be equal to each other. Received: dilation_rate={dilation_rate}

What it means

The atrous (dilated) path of the legacy conv2d_transpose() is implemented via tf.nn.atrous_conv2d_transpose, which takes a single scalar rate. Therefore dilation_rate must be square: dilation_rate[0] == dilation_rate[1]. Non-square dilation forces a slower transpose-based path, so Keras rejects it up front rather than silently changing performance semantics.

Source

Thrown at keras/src/legacy/backend.py:586

    padding = _preprocess_padding(padding)
    if tf_data_format == "NHWC":
        strides = (1,) + strides + (1,)
    else:
        strides = (1, 1) + strides

    if dilation_rate == (1, 1):
        x = tf.compat.v1.nn.conv2d_transpose(
            x,
            kernel,
            output_shape,
            strides,
            padding=padding,
            data_format=tf_data_format,
        )
    else:
        if dilation_rate[0] != dilation_rate[1]:
            raise ValueError(
                "Expected the 2 dimensions of the `dilation_rate` argument "
                "to be equal to each other. "
                f"Received: dilation_rate={dilation_rate}"
            )
        x = tf.nn.atrous_conv2d_transpose(
            x, kernel, output_shape, rate=dilation_rate[0], padding=padding
        )
    if data_format == "channels_first" and tf_data_format == "NHWC":
        x = tf.transpose(x, (0, 3, 1, 2))  # NHWC -> NCHW
    return x


@keras_export("keras._legacy.backend.conv3d")
def conv3d(
    x,
    kernel,
    strides=(1, 1, 1),
    padding="valid",

View on GitHub (pinned to 7a34a03db6)

Solutions

  1. Use a square dilation rate, e.g. dilation_rate=(2,2)
  2. If anisotropic dilation is genuinely required, decompose into two transposed convolutions with square rates or pad+conv manually
  3. Set dilation_rate=(1,1) if dilation was copied in accidentally and is not needed

Example fix

// before
out = K.conv2d_transpose(x, k, shape, dilation_rate=(1, 3))  # ValueError

// after
out = K.conv2d_transpose(x, k, shape, dilation_rate=(3, 3))
Defensive patterns

Strategy: validation

Validate before calling

if dilation_rate is not None:
    assert dilation_rate[0] == dilation_rate[1], f'dilation_rate must be square, got {dilation_rate}'

Type guard

def is_square_dilation(d) -> bool:
    return d[0] == d[1]

Try / catch

except ValueError as e:
    if 'dilation_rate' in str(e):
        out = K.conv2d_transpose(x, k, output_shape, dilation_rate=(d[0], d[0]))
    else:
        raise

Prevention

When it happens

Trigger: keras._legacy.backend.conv2d_transpose(x, kernel, output_shape, strides=(2,2), dilation_rate=(1,2)) — or any (r1, r2) with r1 != r2 — when the code takes the non-force_transpose branch (channels_last, or strides equal to dilation).

Common situations: Ported deconvolution layers with anisotropic dilation from other frameworks; config files specifying asymmetric dilation rates that worked elsewhere; defaults copied from a Conv2D layer whose dilation was then reused for the transpose.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of keras-team/keras@7a34a03db6 (2026-08-25). Data as JSON: /api/errors/a7dacc488ad1733b. Report an issue: GitHub.