def _get_output_shape(self, inputs):
    input_shape = inputs.shape if inputs.shape.is_fully_defined() else tf.shape(
        inputs)

    if self._channel_index == 1:
      input_size = input_shape[2:]
    else:
      input_size = input_shape[1:-1]
    stride = utils.replicate(self._stride, self._num_spatial_dims, "stride")

    output_shape = smart_lambda(lambda x, y: x * y, input_size, stride)

    if self._padding == "VALID":
      kernel_shape = utils.replicate(self._kernel_shape, self._num_spatial_dims,
                                     "kernel_shape")
      rate = utils.replicate(self._rate, self._num_spatial_dims, "rate")
      effective_kernel_shape = [
          (shape - 1) * rate + 1 for (shape, rate) in zip(kernel_shape, rate)
      ]
      output_shape = smart_lambda(lambda x, y: x + y - 1, output_shape,
                                  effective_kernel_shape)

    return output_shape