```python
import torch
import torch.nn as nn
from torch.utils.cpp_extension import load_inline


_cuda_source = r"""
#include <torch/extension.h>
#include <c10/cuda/CUDAGuard.h>
#include <c10/cuda/CUDAStream.h>
#include <c10/cuda/CUDAException.h>
#include <cuda_runtime.h>
#include <cmath>
#include <cstdint>

constexpr int THREADS = 256;
constexpr int CHUNK = 4096;

__global__ void spatial_sum_kernel(
    const float* __restrict__ x,
    float* __restrict__ partial,
    int64_t spatial,
    int parts)
{
    const int64_t row = static_cast<int64_t>(blockIdx.x) / parts;
    const int part = blockIdx.x % parts;
    const int64_t start = static_cast<int64_t>(part) * CHUNK;
    const int64_t end = min(start + CHUNK, spatial);

    float value = 0.0f;
    for (int64_t i = start + threadIdx.x; i < end; i += THREADS)
        value += x[row * spatial + i];

    __shared__ float scratch[THREADS];
    scratch[threadIdx.x] = value;
    __syncthreads();

    for (int offset = THREADS / 2; offset > 0; offset >>= 1) {
        if (threadIdx.x < offset)
            scratch[threadIdx.x] += scratch[threadIdx.x + offset];
        __syncthreads();
    }

    if (threadIdx.x == 0)
        partial[blockIdx.x] = scratch[0];
}

__global__ void finish_kernel(
    const float* __restrict__ partial,
    const float* __restrict__ weight,
    const float* __restrict__ conv_bias,
    const float* __restrict__ bias,
    float* __restrict__ output,
    int in_channels,
    int out_channels,
    int kernel_area,
    int parts,
    float inverse_output_area)
{
    extern __shared__ float input_sums[];
    __shared__ float scratch[THREADS];

    const int tid = threadIdx.x;
    const int batch = blockIdx.x;

    for (int ic = tid; ic < in_channels; ic += THREADS) {
        const float* p = partial +
            (static_cast<int64_t>(batch) * in_channels + ic) * parts;
        float sum = 0.0f;
        for (int j = 0; j < parts; ++j)
            sum += p[j];
        input_sums[ic] = sum * inverse_output_area;
    }
    __syncthreads();

    float local_max = -INFINITY;
    float local_sum = 0.0f;

    for (int oc = tid; oc < out_channels; oc += THREADS) {
        float value = 0.0f;

        for (int ic = 0; ic < in_channels; ++ic) {
            const float* w = weight +
                (static_cast<int64_t>(ic) * out_channels + oc) * kernel_area;

            float weight_sum = 0.0f;
            for (int k = 0; k < kernel_area; ++k)
                weight_sum += w[k];

            value = fmaf(input_sums[ic], weight_sum, value);
        }

        value += conv_bias[oc];
        value += bias[oc];

        const float next_max = fmaxf(local_max, value);
        local_sum = local_sum * expf(local_max - next_max)
                  + expf(value - next_max);
        local_max = next_max;
    }

    scratch[tid] = local_max;
    __syncthreads();

    for (int offset = THREADS / 2; offset > 0; offset >>= 1) {
        if (tid < offset)
            scratch[tid] = fmaxf(scratch[tid], scratch[tid + offset]);
        __syncthreads();
    }

    const float maximum = scratch[0];
    const float scaled_sum =
        local_sum == 0.0f ? 0.0f : local_sum * expf(local_max - maximum);
    __syncthreads();

    scratch[tid] = scaled_sum;
    __syncthreads();

    for (int offset = THREADS / 2; offset > 0; offset >>= 1) {
        if (tid < offset)
            scratch[tid] += scratch[tid + offset];
        __syncthreads();
    }

    if (tid == 0)
        output[batch] = (maximum + logf(scratch[0])) * 10.0f;
}

torch::Tensor pooled_transpose_cuda(
    torch::Tensor x,
    torch::Tensor weight,
    torch::Tensor conv_bias,
    torch::Tensor bias)
{
    const c10::cuda::CUDAGuard guard(x.device());

    const int batch = x.size(0);
    const int in_channels = x.size(1);
    const int out_channels = weight.size(1);
    const int64_t height = x.size(2);
    const int64_t width = x.size(3);
    const int64_t spatial = height * width;
    const int kernel_height = weight.size(2);
    const int kernel_width = weight.size(3);
    const int kernel_area = kernel_height * kernel_width;
    const int parts = (spatial + CHUNK - 1) / CHUNK;

    auto partial = torch::empty({batch, in_channels, parts}, x.options());
    auto output = torch::empty({batch, 1}, x.options());

    if (batch == 0)
        return output;

    const float inverse_output_area = 1.0f /
        static_cast<float>(
            (height + kernel_height - 1) * (width + kernel_width - 1));

    const auto stream = c10::cuda::getCurrentCUDAStream();

    spatial_sum_kernel<<<batch * in_channels * parts, THREADS, 0, stream>>>(
        x.data_ptr<float>(),
        partial.data_ptr<float>(),
        spatial,
        parts);
    C10_CUDA_KERNEL_LAUNCH_CHECK();

    finish_kernel<<<batch, THREADS, in_channels * sizeof(float), stream>>>(
        partial.data_ptr<float>(),
        weight.data_ptr<float>(),
        conv_bias.data_ptr<float>(),
        bias.data_ptr<float>(),
        output.data_ptr<float>(),
        in_channels,
        out_channels,
        kernel_area,
        parts,
        inverse_output_area);
    C10_CUDA_KERNEL_LAUNCH_CHECK();

    return output;
}
"""

_extension = load_inline(
    name="pooled_transpose_lse_fused",
    cpp_sources="""
        torch::Tensor pooled_transpose_cuda(
            torch::Tensor x,
            torch::Tensor weight,
            torch::Tensor conv_bias,
            torch::Tensor bias);
    """,
    cuda_sources=_cuda_source,
    functions=["pooled_transpose_cuda"],
    extra_cflags=["-O3"],
    extra_cuda_cflags=["-O3"],
    verbose=False,
)


class ModelNew(nn.Module):
    def __init__(self, in_channels, out_channels, kernel_size, bias_shape):
        super().__init__()
        self.conv_transpose = nn.ConvTranspose2d(
            in_channels, out_channels, kernel_size
        )
        self.bias = nn.Parameter(torch.randn(bias_shape))

    def forward(self, x):
        conv = self.conv_transpose

        if (
            x.is_cuda
            and x.dtype == torch.float32
            and x.ndim == 4
            and x.shape[1] == conv.in_channels
            and 0 < conv.in_channels <= 8192
            and x.shape[2] > 0
            and x.shape[3] > 0
            and conv.weight.dtype == torch.float32
            and conv.bias.dtype == torch.float32
            and self.bias.dtype == torch.float32
            and conv.weight.device == x.device
            and conv.bias.device == x.device
            and self.bias.device == x.device
            and tuple(self.bias.shape) == (conv.out_channels, 1, 1)
            and not torch.is_autocast_enabled()
        ):
            # With stride 1 and no padding, every input pixel contributes
            # every kernel coefficient to the full spatial output sum.
            return _extension.pooled_transpose_cuda(
                x.contiguous(),
                conv.weight.contiguous(),
                conv.bias.contiguous(),
                self.bias.contiguous(),
            )

        x = conv(x)
        x = x.mean(dim=(2, 3), keepdim=True)
        x = x + self.bias
        x = torch.logsumexp(x, dim=1, keepdim=True)
        return x.sum(dim=(2, 3)) * 10.0
```