GrayNet is a lightweight, purpose-built convolutional neural network designed exclusively for single-channel (grayscale) medical imaging. Unlike conventional architectures that repurpose RGB-pretrained backbones and discard two-thirds of their learned color representations, GrayNet treats grayscale as a first-class input modality — every module in the pipeline is engineered to extract the maximum signal from a single intensity channel.
This repository provides the complete research pipeline: data integrity auditing, dataset construction, model training with 5-fold cross-validation, knowledge distillation for edge deployment, ablation studies, explainability visualisations, and modular benchmarking tools for paper-ready metrics.
Run the Streamlit app locally:
pip install -r requirements_app.txt
streamlit run app.pyThe app runs a 5-fold ensemble of GrayNet Mini (110K params) with:
- ✅ Exact training preprocessing (InstanceNormalize — not
(x-0.5)/0.5) - ✅ Analytical Grad-CAM in a single forward pass (no backprop needed)
- ✅ 🔒 100% local inference — your MRI never leaves your machine
Related: GreyNet-Website — a companion Next.js app that runs GrayNet fully in the browser via ONNX Runtime Web (zero server, offline-capable, WebAssembly inference).
-
Exposing Data Leakage in Public Benchmarks. Using Perceptual Hashing (pHash), we discovered a 31.44% test-to-train leakage rate in one of the most widely cited brain tumor datasets on Kaggle, and 16.20% in the BRISC dataset. Published results trained and evaluated on these leaked splits are unreliable.
-
A Verified 0%-Leakage Dataset. We merged the two source datasets, deduplicated across all 13,200 images (removing 6,308 near-duplicates at a Hamming distance threshold ≤ 3), and produced a mathematically verified, 6,892-image clean dataset split into 5 stratified folds for rigorous cross-validation.
-
The GrayNet Architecture. An 813K-parameter model featuring six novel or adapted modules — ACE, TEB, MSDC, FAM, SFA, and CBAM++ — achieves 98.11% accuracy (98.13% with TTA) on the 0%-leakage benchmark, while remaining small enough for edge deployment.
-
Parametric Width Scaling. A single architecture with width multiplier
$w$ spans five deployment tiers from 813K (Master) to 24.7K (Femto) parameters, maintaining >97% accuracy at all scales.
All models are evaluated via 5-fold cross-validation on the verified 0%-leakage dataset. Latency is measured on a single NVIDIA GPU with batch size 1.
| Model | Params | Size (KB) | CPU 1T (ms) | CPU 4T (ms) | GPU (ms) | Std Acc (%) | TTA Acc (%) |
|---|---|---|---|---|---|---|---|
| GrayNet Master | 813.1K | 3,290 | 101.98 | 38.60 | 3.73 | 98.11 | 98.13 |
| GrayNet Lite | 249.5K | 1,066 | 48.79 | 22.32 | 3.98 | 97.87 | 97.98 |
| GrayNet Mini | 110.5K | 515 | 31.92 | 17.26 | 3.83 | 97.87 | 97.95 |
| GrayNet Pico | 52.9K | 282 | 23.59 | 14.78 | 3.80 | 97.66 | 97.75 |
| GrayNet Femto | 24.7K | 168 | 29.69 | 30.49 | 8.72 | 96.94 | 97.42 |
Key finding: GrayNet Pico (52.9K parameters) achieves 97.75% TTA accuracy while delivering a 4.3× CPU speedup (23.59 ms vs 101.98 ms), proving that depthwise-separable width scaling enables ultra-fast edge inference with minimal diagnostic accuracy loss.
GrayNet is a 10-stage pipeline with a width_mult parameter that uniformly scales all channel counts, enabling a family of models from 24.7K to 813K parameters using a single architecture definition.
graph TD
classDef stem fill:#2c3e50,stroke:#34495e,stroke-width:2px,color:#fff;
classDef contrast fill:#d35400,stroke:#e67e22,stroke-width:2px,color:#fff;
classDef texture fill:#f39c12,stroke:#f1c40f,stroke-width:2px,color:#fff;
classDef attention fill:#8e44ad,stroke:#9b59b6,stroke-width:2px,color:#fff;
classDef conv fill:#2980b9,stroke:#3498db,stroke-width:2px,color:#fff;
classDef stats fill:#27ae60,stroke:#2ecc71,stroke-width:2px,color:#fff;
classDef head fill:#c0392b,stroke:#e74c3c,stroke-width:2px,color:#fff;
Input["MRI Input (1ch, 256x256)"] --> Stem["GrayscaleStem (Stage 1)<br>1 → 24ch"]:::stem
Stem --> ACE["ACE Block (Stage 2)<br>Adaptive Contrast Maps"]:::contrast
ACE --> TEB["TEB Block (Stage 3)<br>Multi-scale Textures"]:::texture
TEB --> FAMFine["FAM-Fine (Stage 4)<br>FFT Spectral Attention"]:::attention
FAMFine --> MSDCA["MSDC-A x2 (Stage 5a)<br>Ghost 5x5 Conv (112 to 56)"]:::conv
MSDCA --> SFA["SFA Block (Stage 5b)<br>Statistical Entropy Proxy"]:::stats
SFA --> MSDCB["MSDC-B x2 (Stage 5c)<br>Ghost 5x5 Conv (56 to 28)"]:::conv
MSDCB --> CBAM["CBAM++ (Stage 5d)<br>VarPool Attention"]:::attention
CBAM --> MSDCC["MSDC-C x1 (Stage 5e)<br>Ghost 5x5 Conv (28 to 14)"]:::conv
MSDCC --> FAMCoarse["FAM-Coarse (Stage 5f)<br>FFT Spectral Attention"]:::attention
FAMCoarse --> Head["Dual-Pool Head (Stage 6)<br>AvgPool + MaxPool → Logits"]:::head
| Module | File | Purpose |
|---|---|---|
| ACE — Adaptive Contrast Enhancement | ace.py | Learns spatially-varying gain (0, 2) and bias maps via shared depthwise context. Enables both suppression and amplification of local contrast — critical for faint low-grade glioma borders. |
| TEB — Texture Extraction Block | teb.py | Four parallel depthwise paths (3×3, 5×5, 7×7, dilated-3×3) capture multi-scale texture, then project from 24 → 64 channels with a residual shortcut. |
| MSDC — Multi-Scale Depthwise Conv | msdc.py | Inverted bottleneck block with GhostNet-inspired 5×5 cheap operations for wider texture receptive fields at minimal parameter cost. Includes stochastic depth (DropPath). |
| FAM — Frequency Attention Module | fam.py | Performs FFT, applies a two-factor spectral mask (static learnable freq_mask × dynamic per-image MLP gate), then IFFT. Used at both fine (128×128) and coarse (16×16) resolutions. |
| SFA — Statistical Feature Aggregator | sfa.py | Computes local variance and log-variance (differential entropy proxy) at dual window sizes (3×3, 5×5), fuses with original features via learned sigmoid gate. |
| CBAM++ — Channel + Spatial Attention | cbam.py | Three-branch channel attention (AvgPool, MaxPool, VarPool) with a shared MLP, followed by spatial attention. VarPool adds sensitivity to heterogeneous tumor textures. |
| Focal Loss | loss.py | Class-imbalance-aware loss with configurable gamma, label smoothing, and per-class weights. |
| Edge Metrics | edge_metrics.py | Computes FLOPs, multi-device latency (CPU 1T/4T, GPU), throughput, peak memory, and model size for deployment profiling. |
graynet/
├── graynet/ # Core PyTorch architecture package
│ ├── model.py # Full GrayNet model assembly
│ ├── stem.py # Stage 1: Grayscale-native stem
│ ├── ace.py # Stage 2: Adaptive Contrast Enhancement
│ ├── teb.py # Stage 3: Texture Extraction Block
│ ├── msdc.py # MSDC blocks with Ghost convolutions
│ ├── fam.py # Frequency Attention Module (FFT-based)
│ ├── sfa.py # Statistical Feature Aggregator
│ ├── cbam.py # CBAM++ with VarPool
│ ├── head.py # Dual-pool classification head
│ ├── loss.py # Focal Loss implementation
│ └── edge_metrics.py # Deployment profiling (FLOPs, latency, memory)
│
├── data/ # PyTorch data loading module
│ └── dataset.py # GrayscaleImageFolder, augmentations, BrainCropTransform
│
├── dataset/ # Dataset construction pipeline
│ ├── 01_check_leakage.py # pHash-based train/test leakage detection
│ ├── 02_merge_datasets.py # Cross-dataset merging and class standardisation
│ ├── 03_clean_duplicates.py # Perceptual deduplication (Hamming ≤ 3)
│ ├── 04_create_folds.py # Stratified 5-fold split generation
│ ├── raw/ # Original source datasets (BRISC, BTD)
│ ├── intermediate/ # Merged intermediate datasets
│ ├── processed/ # Clean dataset and 5-fold splits
│ └── reports/ # Leakage and duplication audit reports (.xlsx)
│
├── configs/ # YAML training configurations
│ ├── master.yaml # GrayNet Master (width_mult=1.0, 813K params)
│ ├── 250k.yaml # GrayNet Lite (width_mult≈0.55, 249.5K params)
│ ├── 100k.yaml # GrayNet Mini (width_mult≈0.35, 110.5K params)
│ ├── 50k.yaml # GrayNet Pico (width_mult≈0.23, 52.9K params)
│ └── 25k.yaml # GrayNet Femto (width_mult≈0.15, 24.7K params)
│
├── runs/ # Training outputs (checkpoints, logs, reports)
│ ├── master/ # GrayNet Master (5 folds + master_teacher/)
│ ├── 250k_lite/ # Each run contains fold_1/ … fold_5/
│ ├── 100k_mini/ # └── best_model.pt, train.log,
│ ├── 50k_pico/ # classification_report_fold_*.txt
│ ├── 25k_femto/
│ ├── training_convergence_report.md
│ └── defence_training_convergence_report.md
│
├── ablation/ # Self-contained ablation study workspace
│ ├── run_all_ablations.py # One-click runner for all 7 experiments
│ ├── configs/ # Per-experiment YAML configs (no_ace, no_teb, etc.)
│ ├── graynet/ # Local copy of architecture with ablation flags
│ ├── results/ # Comprehensive ablation report (Markdown)
│ └── README.md # Ablation study documentation
│
├── scripts/ # Utility and analysis scripts
│ ├── research_metrics/ # Modular CLI tools for paper metrics
│ │ ├── compute_params.py # Parameter count
│ │ ├── compute_size.py # Model size (KB)
│ │ ├── compute_flops.py # FLOPs / MACs via thop
│ │ ├── compute_latency.py # CPU/GPU latency benchmarking
│ │ ├── compute_acc.py # 5-fold accuracy + TTA evaluation
│ │ └── orchestrate_all_metrics.py # Full benchmark across all 9 models
│ ├── evaluation/ # Model evaluation and error analysis
│ ├── explainability/ # GradCAM, GradCAM++, ScoreCAM, Occlusion maps
│ ├── architecture/ # Architecture validation, width search, ONNX export
│ ├── data_processing/ # Dataset download and preprocessing
│ └── publishing/ # Paper PDF generation (Springer LNCS format)
│
├── plots/ # Latency scaling visualisations
│
├── train.py # Single-run training script
├── train_kfold.py # 5-fold cross-validation training
├── requirements.txt # Python dependencies
└── LICENSE # MIT License
- Python ≥ 3.9
- CUDA-capable GPU (recommended; CPU training is supported but slow)
git clone https://github.com/yourusername/graynet.git
cd graynet
pip install -r requirements.txtThe raw MRI images are not included in the repository. To build the verified dataset from scratch, follow the step-by-step instructions in the Dataset README. The pipeline will:
- Audit the original train/test splits for leakage (01_check_leakage.py)
- Merge and standardise class names across datasets (02_merge_datasets.py)
- Deduplicate using perceptual hashing at Hamming distance ≤ 3 (03_clean_duplicates.py)
- Generate stratified 5-fold cross-validation splits (04_create_folds.py)
All training scripts accept a --config flag pointing to a YAML configuration file. Configs specify the model architecture (width multiplier, dropout, input size), data paths, optimiser settings, scheduler, and logging directory.
Trains GrayNet at full width (width_mult=1.0, 813K params) across all 5 folds.
python train_kfold.py --config configs/master.yamlTo train only specific folds:
python train_kfold.py --config configs/master.yaml --folds 1 3 5Training features include:
- Cosine annealing with linear warmup
- Mixed precision training (AMP)
- Focal Loss with class weights and label smoothing
- Exponential Moving Average (EMA) with decay warmup
- Stochastic Weight Averaging (SWA) over the final training window
- Test Time Augmentation (TTA) — 5-view MRI-appropriate ensemble
- Automatic best-method selection (Standard / EMA / SWA / TTA combinations)
- CutMix support (disabled by default — proven harmful on this dataset)
- Per-fold classification reports with edge deployment metrics
For quick prototyping or non-cross-validated experiments:
python train.py --config configs/master.yamlThe scripts/research_metrics/ directory provides modular CLI tools that can extract individual metrics for any model configuration:
# Parameter count
python scripts/research_metrics/compute_params.py --config configs/master.yaml
# FLOPs and MACs
python scripts/research_metrics/compute_flops.py --config configs/25k.yaml
# CPU/GPU latency benchmarking
python scripts/research_metrics/compute_latency.py --config configs/100k.yaml
# 5-fold accuracy with TTA
python scripts/research_metrics/compute_acc.py --config configs/100k.yaml --run runs/100k_miniTo regenerate the full metrics table across all models:
python scripts/research_metrics/orchestrate_all_metrics.pyThe ablation/ directory is a fully self-contained workspace that measures the contribution of each architectural module. Seven experiments systematically remove individual components (ACE, TEB, FAM, SFA, CBAM++, Ghost convolutions, dual-pool head) and retrain from scratch to quantify their impact.
cd ablation
python run_all_ablations.pyResults are documented in ablation/results/comprehensive_ablation_report.md. See the Ablation README for full details.
The scripts/explainability/ directory generates publication-quality visual interpretability maps to validate that GrayNet's predictions are grounded in clinically relevant features rather than spurious artefacts:
- GradCAM and GradCAM++ — gradient-weighted class activation maps
- ScoreCAM — gradient-free activation mapping
- Occlusion Sensitivity — systematic region masking
- Segmentation Overlay — CAM-derived tumor region segmentation on MRI scans
Outputs (including Monte Carlo Dropout uncertainty analysis) are stored in scripts/outputs/.
The data/dataset.py module provides the PyTorch data loading infrastructure:
- GrayscaleImageFolder — grayscale-native dataset loader with automatic class discovery
- InstanceNormalize — per-image zero-mean/unit-std normalisation that handles scanner variation (1.5T vs 3T MRI) without destroying inter-class intensity differences
- BrainCropTransform — Otsu-based skull stripping and ROI extraction, ensuring 100% of input resolution is dedicated to brain tissue
- Train augmentations — RandomResizedCrop, flips, rotation, affine, colour jitter, and RandomErasing
- Validation transforms — deterministic resize + centre crop with InstanceNormalize
Our dataset pipeline exposed severe integrity issues in popular public benchmarks:
| Dataset | Train Images | Test Images | Leaked Test Images | Leakage Rate |
|---|---|---|---|---|
| Brain Tumour Dataset (Kaggle) | 5,600 | 1,600 | 503 | 31.44% |
| BRISC | 5,000 | 1,000 | 162 | 16.20% |
After merging and deduplication, 6,308 duplicate images (47.79%) were removed from the combined 13,200-image pool, yielding a final clean dataset of 6,892 unique images distributed across 4 classes (Glioma, Meningioma, Pituitary, No Tumor).
Full methodology and per-class statistics are documented in the Dataset README.
Each YAML config controls the full training pipeline. Key parameters:
model:
width_mult: 1.0 # Channel scaling (1.0=813K, 0.55=250K, 0.35=110K, 0.23=53K, 0.15=25K)
dropout: 0.2 # Classifier dropout
drop_path_rate: 0.05 # Stochastic depth rate
input_size: 224 # Input resolution
training:
epochs: 400 # Maximum training epochs
lr: 1.0e-3 # Peak learning rate
patience: 80 # Early stopping patience
use_ema: true # Exponential Moving Average
swa_window: 25 # SWA rolling window size
fam_lr_scale: 0.1 # Reduced LR for FAM freq_mask parametersThis project is licensed under the MIT License — see LICENSE for details.
Copyright (c) 2026 Author A, Author B
If you use the GrayNet architecture or our cleaned dataset in your research, please cite:
@article{graynet2026,
title = {GrayNet: A Grayscale-Native CNN for Brain Tumor MRI Classification},
author = {Rama ,Hari krishna},
year = {2026}
}