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


_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 <cstdint>

constexpr int THREADS = 256;
constexpr int TILE = 65536;
constexpr int FINISH_THREADS = 128;

__device__ __forceinline__ float warp_sum(float x) {
    #pragma unroll
    for (int offset = 16; offset; offset >>= 1)
        x += __shfl_down_sync(0xffffffff, x, offset);
    return x;
}

__device__ __forceinline__ float warp_max(float x) {
    #pragma unroll
    for (int offset = 16; offset; offset >>= 1)
        x = fmaxf(x, __shfl_down_sync(0xffffffff, x, offset));
    return x;
}

__device__ __forceinline__ float4 streaming_load(const float4* p) {
    float4 v;
    asm volatile(
        "ld.global.cs.v4.f32 {%0, %1, %2, %3}, [%4];"
        : "=f"(v.x), "=f"(v.y), "=f"(v.z), "=f"(v.w)
        : "l"(p)
    );
    return v;
}

template<bool VECTORIZED, bool FULL_TILES>
__global__ __launch_bounds__(THREADS)
void prepare_kernel(
    const float* __restrict__ input,
    const float* __restrict__ weight,
    float* __restrict__ partials,
    float* __restrict__ weight_sums,
    int64_t spatial,
    int parts,
    int kernel_elements,
    int64_t input_blocks,
    int64_t weight_count,
    int64_t total_blocks
) {
    __shared__ float reduction[8];
    const int tid = threadIdx.x;

    for (int64_t block = blockIdx.x;
         block < total_blocks;
         block += gridDim.x) {
        if (block >= input_blocks) {
            const int64_t index = (block - input_blocks) * THREADS + tid;
            if (index < weight_count) {
                const float* w = weight + index * kernel_elements;
                float sum = 0.0f;
                if (kernel_elements == 9) {
                    #pragma unroll
                    for (int k = 0; k < 9; ++k)
                        sum += w[k];
                } else {
                    for (int k = 0; k < kernel_elements; ++k)
                        sum += w[k];
                }
                weight_sums[index] = sum;
            }
        } else {
            const int64_t plane = block / parts;
            const int part = block % parts;
            const int64_t start = int64_t(part) * TILE;
            float sum;

            if constexpr (VECTORIZED) {
                const float4* base = reinterpret_cast<const float4*>(
                    input + plane * spatial
                );
                float a0 = 0.0f, a1 = 0.0f;
                float a2 = 0.0f, a3 = 0.0f;
                float b0 = 0.0f, b1 = 0.0f;
                float b2 = 0.0f, b3 = 0.0f;

                #pragma unroll 4
                for (int j = 0; j < TILE / (8 * THREADS); ++j) {
                    const int64_t i = start / 4 + tid + j * 2 * THREADS;
                    if (FULL_TILES || i < spatial / 4) {
                        const float4 v = streaming_load(base + i);
                        a0 += v.x;
                        a1 += v.y;
                        a2 += v.z;
                        a3 += v.w;
                    }
                    if (FULL_TILES || i + THREADS < spatial / 4) {
                        const float4 v = streaming_load(base + i + THREADS);
                        b0 += v.x;
                        b1 += v.y;
                        b2 += v.z;
                        b3 += v.w;
                    }
                }
                sum = ((a0 + b0) + (a1 + b1))
                    + ((a2 + b2) + (a3 + b3));
            } else {
                float a = 0.0f, b = 0.0f;
                #pragma unroll 4
                for (int j = 0; j < TILE / (2 * THREADS); ++j) {
                    const int64_t i = start + tid + j * 2 * THREADS;
                    if (i < spatial)
                        a += input[plane * spatial + i];
                    if (i + THREADS < spatial)
                        b += input[plane * spatial + i + THREADS];
                }
                sum = a + b;
            }

            sum = warp_sum(sum);
            if ((tid & 31) == 0)
                reduction[tid >> 5] = sum;
            __syncthreads();

            if (tid < 32) {
                sum = warp_sum(tid < 8 ? reduction[tid] : 0.0f);
                if (tid == 0)
                    partials[block] = sum;
            }
            __syncthreads();
        }
    }
}

template<int FIXED_IN_CHANNELS>
__global__ void finish_kernel(
    const float* __restrict__ partials,
    const float* __restrict__ weight_sums,
    const float* __restrict__ conv_bias,
    const float* __restrict__ extra_bias,
    float* __restrict__ output,
    int in_channels,
    int out_channels,
    int parts,
    float inverse_output_area
) {
    extern __shared__ float storage[];
    float* input_sums = storage;
    float* logits = input_sums + in_channels;
    float* reduction = logits + out_channels;

    const int batch = blockIdx.x;
    const int tid = threadIdx.x;
    const int lane = tid & 31;
    const int warp = tid >> 5;
    const float neg_inf = -CUDART_INF_F;
    const int channels = FIXED_IN_CHANNELS ? FIXED_IN_CHANNELS : in_channels;

    for (int i = tid; i < channels; i += FINISH_THREADS) {
        const int64_t base = (int64_t(batch) * channels + i) * parts;
        float sum = 0.0f;
        for (int p = 0; p < parts; ++p)
            sum += partials[base + p];
        input_sums[i] = sum * inverse_output_area;
    }
    __syncthreads();

    float local_max = neg_inf;
    for (int c = tid; c < out_channels; c += FINISH_THREADS) {
        float value = 0.0f;
        #pragma unroll 8
        for (int i = 0; i < channels; ++i)
            value = fmaf(
                input_sums[i],
                weight_sums[int64_t(i) * out_channels + c],
                value
            );
        value = (value + conv_bias[c]) + extra_bias[c];
        logits[c] = value;
        local_max = fmaxf(local_max, value);
    }

    local_max = warp_max(local_max);
    if (lane == 0)
        reduction[warp] = local_max;
    __syncthreads();

    if (warp == 0) {
        float value = warp_max(lane < 4 ? reduction[lane] : neg_inf);
        if (lane == 0)
            reduction[4] = value;
    }
    __syncthreads();

    const float maximum = reduction[4];
    const float shift = isinf(maximum) ? 0.0f : maximum;
    float local_sum = 0.0f;
    for (int c = tid; c < out_channels; c += FINISH_THREADS)
        local_sum += expf(logits[c] - shift);

    local_sum = warp_sum(local_sum);
    if (lane == 0)
        reduction[warp] = local_sum;
    __syncthreads();

    if (warp == 0) {
        float value = warp_sum(lane < 4 ? reduction[lane] : 0.0f);
        if (lane == 0)
            output[batch] = 10.0f * (shift + logf(value));
    }
}

torch::Tensor pooled_transpose_cuda(
    torch::Tensor x,
    torch::Tensor weight,
    torch::Tensor conv_bias,
    torch::Tensor extra_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 int kh = weight.size(2);
    const int kw = weight.size(3);
    const int64_t spatial = x.size(2) * x.size(3);
    const int parts = (spatial + TILE - 1) / TILE;

    auto output = torch::empty({batch, 1}, x.options());
    if (batch == 0)
        return output;

    const int64_t input_blocks = int64_t(batch) * in_channels * parts;
    const int64_t weight_count = int64_t(in_channels) * out_channels;
    const int64_t total_blocks =
        input_blocks + (weight_count + THREADS - 1) / THREADS;
    const int blocks = int(total_blocks < 65535 ? total_blocks : 65535);

    auto scratch = torch::empty({input_blocks + weight_count}, x.options());
    float* partials = scratch.data_ptr<float>();
    float* weight_sums = partials + input_blocks;
    const auto stream = at::cuda::getCurrentCUDAStream();

    const bool vectorized =
        spatial % 4 == 0 &&
        reinterpret_cast<uintptr_t>(x.data_ptr<float>()) % 16 == 0;

    #define LAUNCH_PREPARE(V, F) \
        prepare_kernel<V, F><<<blocks, THREADS, 0, stream>>>( \
            x.data_ptr<float>(), weight.data_ptr<float>(), \
            partials, weight_sums, spatial, parts, kh * kw, \
            input_blocks, weight_count, total_blocks)

    if (vectorized) {
        if (spatial % TILE == 0) {
            LAUNCH_PREPARE(true, true);
        } else {
            LAUNCH_PREPARE(true, false);
        }
    } else {
        LAUNCH_PREPARE(false, false);
    }
    #undef LAUNCH_PREPARE
    C10_CUDA_KERNEL_LAUNCH_CHECK();

    const int64_t output_area =
        (x.size(2) + kh - 1) * (x.size(3) + kw - 1);
    const size_t shared_bytes =
        size_t(in_channels + out_channels + 5) * sizeof(float);

    #define LAUNCH_FINISH(C) \
        finish_kernel<C><<<batch, FINISH_THREADS, shared_bytes, stream>>>( \
            partials, weight_sums, conv_bias.data_ptr<float>(), \
            extra_bias.data_ptr<float>(), output.data_ptr<float>(), \
            in_channels, out_channels, parts, 1.0f / float(output_area))

    if (in_channels == 64) {
        LAUNCH_FINISH(64);
    } else {
        LAUNCH_FINISH(0);
    }
    #undef LAUNCH_FINISH
    C10_CUDA_KERNEL_LAUNCH_CHECK();

    return output;
}
"""

_extension = load_inline(
    name="fused_transpose_global_pool_lse_v5",
    cpp_sources=r"""
#include <torch/extension.h>
torch::Tensor pooled_transpose_cuda(
    torch::Tensor x,
    torch::Tensor weight,
    torch::Tensor conv_bias,
    torch::Tensor extra_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
        use_custom = (
            x.is_cuda
            and x.dtype == torch.float32
            and conv.weight.dtype == torch.float32
            and conv.bias is not None
            and conv.bias.dtype == torch.float32
            and self.bias.dtype == torch.float32
            and x.device == conv.weight.device == conv.bias.device == self.bias.device
            and x.ndim == 4
            and x.shape[1] == conv.in_channels
            and x.shape[2] > 0
            and x.shape[3] > 0
            and conv.groups == 1
            and conv.stride == (1, 1)
            and conv.padding == (0, 0)
            and conv.output_padding == (0, 0)
            and conv.dilation == (1, 1)
            and tuple(self.bias.shape) == (conv.out_channels, 1, 1)
            and conv.in_channels + conv.out_channels + 5 <= 12000
            and not torch.is_autocast_enabled()
        )

        if use_custom:
            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
```