CXR-LT 2026 Task 1 β€” ConvNeXtV2 + CSRA-style DB-CAS (πŸ† Top-1)

Top-1 submission for Task 1 (Long-tailed Multi-label Chest X-ray Classification) of the CXR-LT 2026 Challenge.


Pretrained Models

Task Model Recommended use Weights
Task 1 ConvNeXtV2-Base + CSRA-style (DB-CAS) Best score for single-model inference convnextv2_base_mimic-cxr_padchest_csra_dbcas.safetensors
Task 1 ConvNeXtV2-Base + standard MLP Reproducible baseline / ensemble candidate convnextv2_base_padchest_standard_mlp.safetensors

Recommendation: choose CSRA-style + DB-CAS when using a single model; it achieves a higher score than the standard MLP model.

Terminology: this implementation uses a CSRA-style class-specific residual attention head. It is inspired by, but not identical to, the original CSRA formulation.

Architectures

ConvNeXtV2-Base + CSRA-style (DB-CAS)

ConvNeXtV2-Base  (timm, global_pool="", drop_path_rate=0.2)
  └── spatial feature map  (B, 1024, H, W)
  └── BatchNorm2d(1024)
  └── CSRA-style head  (Ξ»=0.1)
       β”œβ”€β”€ GAP branch : Linear(1024 β†’ 30)               β†’ logit_gap
       └── Attention  : Conv2d(1024β†’30, 1Γ—1) β†’ Softmax
                        β†’ class-wise weighted pool       β†’ logit_csra
       └── output     : logit_gap + 0.1 Γ— logit_csra

ConvNeXtV2-Base + standard MLP

ConvNeXtV2-Base  (timm, global pooling, drop_path_rate=0.2)
  └── BatchNorm1d(1024)
  └── Dropout(0.3)
  └── Linear(1024 β†’ 512) β†’ ReLU
  └── BatchNorm1d(512) β†’ Dropout(0.3)
  └── Linear(512 β†’ 30)

Training Pipeline

Stage 1 β€” Pre-train on MIMIC-CXR (14 classes)  [FC/MLP head]
  ConvNeXtV2-Base (ImageNet-22k init)
  + head: BN β†’ Dropout β†’ Linear(1024β†’512) β†’ ReLU β†’ BN β†’ Dropout β†’ Linear(512β†’14)
  β”œβ”€β”€ Phase 1: head-only warm-up  (LR 1e-3, 3 epochs)
  └── Phase 2: full fine-tune    (backbone LR 1e-5 / head LR 1e-4)
      Loss: AsymmetricLoss + LogitAdjustment, EMA decay 0.9999

Stage 2 β€” DB-CAS fine-tune on PadChest (30 classes)  [FC head β†’ CSRA-style head]
  Backbone weights resumed from Stage 1; FC head discarded; new CSRA-style head initialized
  β”œβ”€β”€ Distribution-Balanced(DB) sampling: balances label frequency + co-occurrence
  └── Class-Aware Sampling (CAS): leverages CSRA-style spatial attention
      Loss: AsymmetricLoss, EMA decay 0.9999

Files

File Size Description
convnextv2_base_mimic-cxr_padchest_csra_dbcas.safetensors ~351 MB CSRA-style weights only (recommended for single-model inference)
convnextv2_base_mimic-cxr_padchest_csra_dbcas.pth ~1.05 GB Full CSRA-style checkpoint including training states
convnextv2_base_padchest_standard_mlp.safetensors ~353 MB Standard MLP weights only (baseline / ensemble candidate)
convnextv2_base_padchest_standard_mlp.pth ~1.06 GB Full standard MLP checkpoint including training states
model.py β€” timm-compatible CSRA-style model registration

Usage

Install the required packages:

pip install torch timm safetensors huggingface_hub

ConvNeXtV2-Base + CSRA-style (DB-CAS) β€” recommended

Use this model for the strongest single-model score.

from huggingface_hub import hf_hub_download
import importlib.util
import sys
import timm

# Download and register the custom CSRA-style architecture.
path = hf_hub_download("hieuphamha/cxrlt2026-task1-convnextv2", "model.py")
spec = importlib.util.spec_from_file_location("cxrlt", path)
module = importlib.util.module_from_spec(spec)
sys.modules["cxrlt"] = module
spec.loader.exec_module(module)

model = timm.create_model("cxrlt2026_task1_csra_dbcas", pretrained=True)
model.eval()

ConvNeXtV2-Base + standard MLP

Use this model as a reproducible baseline or an ensemble candidate.

import torch
import torch.nn as nn
import timm
from huggingface_hub import hf_hub_download
from safetensors.torch import load_file


class ConvNeXtV2MLP(nn.Module):
    def __init__(self, num_classes=30, drop_path_rate=0.2):
        super().__init__()
        self.backbone = timm.create_model(
            "convnextv2_base",
            pretrained=False,
            num_classes=0,
            drop_path_rate=drop_path_rate,
        )
        nf = self.backbone.num_features
        self.classifier = nn.Sequential(
            nn.BatchNorm1d(nf),
            nn.Dropout(0.3),
            nn.Linear(nf, 512),
            nn.ReLU(inplace=True),
            nn.BatchNorm1d(512),
            nn.Dropout(0.3),
            nn.Linear(512, num_classes),
        )

    def forward(self, x):
        return self.classifier(self.backbone(x))


weights_path = hf_hub_download(
    "hieuphamha/cxrlt2026-task1-convnextv2",
    "convnextv2_base_padchest_standard_mlp.safetensors",
)
model = ConvNeXtV2MLP(num_classes=30)
model.load_state_dict(load_file(weights_path), strict=True)
model.eval()

Inference

import cv2, numpy as np, torch
import torchvision.transforms as T

CLASS_NAMES = ['Normal', 'aortic elongation', 'cardiomegaly', 'pleural effusion', 'Nodule', 'atelectasis', 'pleural thickening', 'aortic atheromatosis', 'Support Devices', 'alveolar pattern', 'fracture', 'Hernia', 'Emphysema', 'azygos lobe', 'Hydropneumothorax', 'Kyphosis', 'Mass', 'Pneumothorax', 'Subcutaneous Emphysema', 'pneumoperitoneo', 'vascular hilar enlargement', 'vertebral degenerative changes', 'hyperinflated lung', 'interstitial pattern', 'central venous catheter', 'hypoexpansion', 'bronchiectasis', 'hemidiaphragm elevation', 'sternotomy', 'calcified densities']

transform = T.Compose([
    T.ToTensor(),
    T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])

def predict(image_path):
    img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
    img = cv2.resize(img, (512, 512))
    x   = transform(np.stack([img] * 3, axis=-1).astype(np.float32) / 255.0)
    x   = x.unsqueeze(0).to(device)
    with torch.no_grad():
        probs = torch.sigmoid(model(x)).squeeze(0).cpu().numpy()
    return dict(zip(CLASS_NAMES, probs.tolist()))

results = predict("chest_xray.png")
for cls, p in sorted(results.items(), key=lambda x: -x[1])[:5]:
    print(f"{p:.3f}  {cls}")

Classes (30 chest X-ray findings)

  1. Normal
  2. aortic elongation
  3. cardiomegaly
  4. pleural effusion
  5. Nodule
  6. atelectasis
  7. pleural thickening
  8. aortic atheromatosis
  9. Support Devices
  10. alveolar pattern
  11. fracture
  12. Hernia
  13. Emphysema
  14. azygos lobe
  15. Hydropneumothorax
  16. Kyphosis
  17. Mass
  18. Pneumothorax
  19. Subcutaneous Emphysema
  20. pneumoperitoneo
  21. vascular hilar enlargement
  22. vertebral degenerative changes
  23. hyperinflated lung
  24. interstitial pattern
  25. central venous catheter
  26. hypoexpansion
  27. bronchiectasis
  28. hemidiaphragm elevation
  29. sternotomy
  30. calcified densities

Input Specification

  • Image size: 512 Γ— 512 (grayscale chest X-ray β†’ 3-channel repeat)
  • Normalization: mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]

Citation

@article{Pham2026HandlingSS,
  title   = {Handling Supervision Scarcity in Chest X-ray Classification:
             Long-Tailed and Zero-Shot Learning},
  author  = {Ha-Hieu Pham and Hai-Dang Nguyen and Thanh-Huy Nguyen and
             Min Xu and Ulas Bagci and Trung-Nghia Le and Huy-Hieu Pham},
  journal = {ArXiv},
  year    = {2026},
  volume  = {abs/2602.13430},
  url     = {https://arxiv.org/abs/2602.13430}
}
Downloads last month
-
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support

Paper for hieuphamha/cxrlt2026-task1-convnextv2