|
|
--- |
|
|
license: mit |
|
|
tags: |
|
|
- ecg |
|
|
- medical |
|
|
- pytorch |
|
|
datasets: |
|
|
- custom |
|
|
language: |
|
|
- en |
|
|
pipeline_tag: other |
|
|
--- |
|
|
|
|
|
# ECG Over-Read: Pre-trained Models for ECG Diagnosis |
|
|
|
|
|
Pre-trained model weights for the paper **"Beyond Machine Interpretation: Learning from Expert Over-Reads Improves ECG Diagnosis"** (Under Review of MIDL 2026). |
|
|
|
|
|
## Models |
|
|
|
|
|
This repository contains 4 pre-trained models: |
|
|
|
|
|
| Model | File | Description | |
|
|
|-------|------|-------------| |
|
|
| **Supervised** | `supervised/best.pt` | Baseline ResNet-50 multi-label classifier | |
|
|
| **CLIP** | `clip/best_cliponly.ckpt` | ECG-Text contrastive learning model | |
|
|
| **NegCLIP** | `negclip/best_detail.ckpt` | CLIP with hard negative mining | |
|
|
| **Self-Training** | `selftraining/best.pt` | Semi-supervised learning with FixMatch | |
|
|
|
|
|
## Model Architecture |
|
|
|
|
|
### ECG Encoder (All Models) |
|
|
- **Architecture**: 1D ResNet-50 with bottleneck blocks (3-4-6-3) |
|
|
- **Input**: 12-lead ECG signal `(batch, 12, 2500)` at 250 Hz |
|
|
- **Output**: 512-dimensional embedding |
|
|
- **Preprocessing**: High-pass filter (0.5 Hz), Notch filter (60 Hz), Per-lead z-score |
|
|
|
|
|
### Text Encoder (CLIP/NegCLIP) |
|
|
- **Architecture**: CLIP text encoder |
|
|
- **Output**: 512-dimensional embedding (projected) |
|
|
|
|
|
## Usage |
|
|
|
|
|
### Download Weights |
|
|
|
|
|
```python |
|
|
from huggingface_hub import hf_hub_download |
|
|
|
|
|
# Download supervised model |
|
|
model_path = hf_hub_download( |
|
|
repo_id="tyoung089/ECG_overread", |
|
|
filename="supervised/best.pt" |
|
|
) |
|
|
|
|
|
# Load model |
|
|
import torch |
|
|
checkpoint = torch.load(model_path, map_location="cpu") |
|
|
``` |
|
|
|
|
|
### Using with Our Code |
|
|
|
|
|
```bash |
|
|
# Clone the code repository |
|
|
git clone https://github.com/YOUR_USERNAME/ecg-overread.git |
|
|
cd ecg-overread |
|
|
|
|
|
# Download all weights |
|
|
pip install huggingface_hub |
|
|
python download_weights.py --outdir ./weights |
|
|
|
|
|
# Run evaluation |
|
|
python Supervised/ecg_eval_cls.py \ |
|
|
--csv /path/to/test.csv \ |
|
|
--ckpt ./weights/supervised/best.pt \ |
|
|
--label-prefix "label_diag__" |
|
|
``` |
|
|
|
|
|
## Input Data Format |
|
|
|
|
|
### ECG Signal |
|
|
- **Sampling rate**: 250 Hz |
|
|
- **Duration**: 10 seconds |
|
|
- **Leads**: 12-lead standard ECG |
|
|
- **Shape**: `(2500, 12)` or `(12, 2500)` |
|
|
- **Format**: NumPy `.npy` files |
|
|
|
|
|
### Checkpoint Format |
|
|
|
|
|
**Supervised / Self-Training (`best.pt`)**: |
|
|
```python |
|
|
{ |
|
|
"model": state_dict, # Model weights |
|
|
"opt": optimizer_state, # Optimizer state |
|
|
"sched": scheduler_state, # Scheduler state |
|
|
"epoch": int, # Training epoch |
|
|
"best": float, # Best validation metric |
|
|
"classes": list, # Class names |
|
|
} |
|
|
``` |
|
|
|
|
|
**CLIP / NegCLIP (`.ckpt`)**: |
|
|
```python |
|
|
{ |
|
|
"model": state_dict, # Full model (ECG + Text encoder) |
|
|
"epoch": int, |
|
|
"args": training_args, |
|
|
} |
|
|
``` |
|
|
|
|
|
## Training Details |
|
|
|
|
|
| Model | Training Data | Method | |
|
|
|-------|--------------|--------| |
|
|
| Supervised | Labeled ECGs | Multi-label BCE loss | |
|
|
| CLIP | ECG + Text pairs | Symmetric contrastive loss | |
|
|
| NegCLIP | ECG + Text pairs | Contrastive loss with hard negatives | |
|
|
| Self-Training | Labeled + Unlabeled | FixMatch with pseudo-labels | |
|
|
|
|
|
## License |
|
|
|
|
|
MIT License |
|
|
|
|
|
## Citation |
|
|
|
|
|
```bibtex |
|
|
@inproceedings{overread2026midl, |
|
|
title={Beyond Machine Interpretation: Learning from Expert Over-Reads Improves ECG Diagnosis}, |
|
|
author={Kwak et al.}, |
|
|
booktitle={Under Review for Medical Imaging with Deep Learning (MIDL)}, |
|
|
year={2026} |
|
|
} |
|
|
``` |
|
|
|
|
|
## Links |
|
|
|
|
|
- **Code Repository**: [GitHub](https://github.com/tyoung089/ecg-overread) |
|
|
- **Paper**: Coming soon |
|
|
|