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


_cpp_source = r"""
#include <torch/extension.h>

torch::Tensor pooled_transpose_cuda(
    torch::Tensor x,
    torch::Tensor weight,
    torch::Tensor conv_bias,
    torch::Tensor bias);
"""

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

constexpr int THREADS = 256;
constexpr int TILE = 4096;

template<bool MAXIMUM>
__device__ __forceinline__ float block_reduce(float value) {
    __shared__ float warp_values[8];
    const int lane = threadIdx.x & 31;
    const int warp = threadIdx.x >> 5;

    #pragma unroll
    for (int offset = 16; offset > 0; offset >>= 1) {
        float other = __shfl_down_sync(0xffffffff, value, offset);
        if (MAXIMUM)
            value = fmaxf(value, other);
        else
            value += other;
    }

    if (lane == 0)
        warp_values[warp] = value;
    __syncthreads();

    if (warp == 0) {
        value = lane < 8 ? warp_values[lane]
                        : (MAXIMUM ? -INFINITY : 0.0f);
        #pragma unroll
        for (int offset = 16; offset > 0; offset >>= 1) {
            float other = __shfl_down_sync(0xffffffff, value, offset);
            if (MAXIMUM)
                value = fmaxf(value, other);
            else
                value += other;
        }
        if (lane == 0)
            warp_values[0] = value;
    }

    __syncthreads();
    float result = warp_values[0];
    __syncthreads();
    return result;
}

template<bool VECTORIZED>
__global__ void spatial_partial_kernel(
    const float* __restrict__ x,
    float* __restrict__ partial,
    int spatial,
    int tiles)
{
    const int channel = blockIdx.x;
    const int tile = blockIdx.y;
    const int start = tile * TILE;
    const float* input = x + static_cast<int64_t>(channel) * spatial;

    float a = 0.0f;
    float b = 0.0f;
    float c = 0.0f;
    float d = 0.0f;

    if (VECTORIZED) {
        const float4* input4 = reinterpret_cast<const float4*>(input);
        const int end4 = min(start + TILE, spatial) / 4;
        for (int i = start / 4 + threadIdx.x;
             i < end4; i += THREADS) {
            float4 v = input4[i];
            a += v.x;
            b += v.y;
            c += v.z;
            d += v.w;
        }
    } else {
        const int end = min(start + TILE, spatial);
        for (int i = start + threadIdx.x; i < end; i += THREADS)
            a += input[i];
    }

    float total = block_reduce<false>((a + b) + (c + d));
    if (threadIdx.x == 0)
        partial[static_cast<int64_t>(channel) * tiles + tile] = total;
}

__global__ void finish_spatial_kernel(
    const float* __restrict__ partial,
    float* __restrict__ pooled,
    int tiles,
    float inverse_output_area)
{
    const int channel = blockIdx.x;
    float value = 0.0f;

    for (int i = threadIdx.x; i < tiles; i += THREADS)
        value += partial[static_cast<int64_t>(channel) * tiles + i];

    value = block_reduce<false>(value);
    if (threadIdx.x == 0)
        pooled[channel] = value * inverse_output_area;
}

__global__ void sum_weights_kernel(
    const float* __restrict__ weight,
    float* __restrict__ summed_weight,
    int pairs,
    int kernel_area)
{
    const int pair = blockIdx.x * THREADS + threadIdx.x;
    if (pair >= pairs)
        return;

    const float* w = weight + static_cast<int64_t>(pair) * kernel_area;
    float value = 0.0f;
    for (int k = 0; k < kernel_area; ++k)
        value += w[k];

    summed_weight[pair] = value;
}

__global__ void output_kernel(
    const float* __restrict__ pooled,
    const float* __restrict__ summed_weight,
    const float* __restrict__ conv_bias,
    const float* __restrict__ bias,
    float* __restrict__ output,
    int in_channels,
    int out_channels)
{
    extern __shared__ float logits[];
    const int batch = blockIdx.x;
    const float* input = pooled + static_cast<int64_t>(batch) * in_channels;

    float local_max = -INFINITY;

    for (int oc = threadIdx.x; oc < out_channels; oc += THREADS) {
        float value = 0.0f;
        for (int ic = 0; ic < in_channels; ++ic)
            value = fmaf(input[ic],
                         summed_weight[static_cast<int64_t>(ic) *
                                       out_channels + oc],
                         value);

        value = (value + conv_bias[oc]) + bias[oc];
        logits[oc] = value;
        local_max = fmaxf(local_max, value);
    }

    float maximum = block_reduce<true>(local_max);
    float local_sum = 0.0f;

    for (int oc = threadIdx.x; oc < out_channels; oc += THREADS)
        local_sum += expf(logits[oc] - maximum);

    float total = block_reduce<false>(local_sum);
    if (threadIdx.x == 0)
        output[batch] = 10.0f * (maximum + logf(total));
}

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

    const int batch = x.size(0);
    const int in_channels = x.size(1);
    const int height = x.size(2);
    const int width = x.size(3);
    const int out_channels = weight.size(1);
    const int kh = weight.size(2);
    const int kw = weight.size(3);
    const int spatial = height * width;
    const int tiles = (spatial + TILE - 1) / TILE;

    auto partial = torch::empty({batch * in_channels, tiles}, x.options());
    auto pooled = torch::empty({batch, in_channels}, x.options());
    auto summed_weight = torch::empty(
        {in_channels, out_channels}, x.options());
    auto output = torch::empty({batch, 1}, x.options());

    if (batch == 0)
        return output;

    auto stream = at::cuda::getCurrentCUDAStream();
    dim3 grid(batch * in_channels, tiles);

    if ((spatial & 3) == 0) {
        spatial_partial_kernel<true><<<grid, THREADS, 0, stream>>>(
            x.data_ptr<float>(), partial.data_ptr<float>(), spatial, tiles);
    } else {
        spatial_partial_kernel<false><<<grid, THREADS, 0, stream>>>(
            x.data_ptr<float>(), partial.data_ptr<float>(), spatial, tiles);
    }
    C10_CUDA_KERNEL_LAUNCH_CHECK();

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

    finish_spatial_kernel<<<batch * in_channels, THREADS, 0, stream>>>(
        partial.data_ptr<float>(), pooled.data_ptr<float>(),
        tiles, inverse_output_area);
    C10_CUDA_KERNEL_LAUNCH_CHECK();

    const int pairs = in_channels * out_channels;
    sum_weights_kernel<<<(pairs + THREADS - 1) / THREADS,
                         THREADS, 0, stream>>>(
        weight.data_ptr<float>(), summed_weight.data_ptr<float>(),
        pairs, kh * kw);
    C10_CUDA_KERNEL_LAUNCH_CHECK();

    output_kernel<<<batch, THREADS, out_channels * sizeof(float), stream>>>(
        pooled.data_ptr<float>(),
        summed_weight.data_ptr<float>(),
        conv_bias.data_ptr<float>(),
        bias.data_ptr<float>(),
        output.data_ptr<float>(),
        in_channels,
        out_channels);
    C10_CUDA_KERNEL_LAUNCH_CHECK();

    return output;
}
"""

_extension = load_inline(
    name="pooled_transpose_analytic_cuda",
    cpp_sources=_cpp_source,
    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 conv.weight.dtype == torch.float32
            and conv.bias.dtype == torch.float32
            and self.bias.dtype == torch.float32
            and tuple(self.bias.shape) == (conv.out_channels, 1, 1)
            and conv.out_channels <= 4096
        ):
            # For this stride-1, unpadded transposed convolution, every
            # input contributes every kernel coefficient to the 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
```