/ Модель

Характеристики

Лицензия
CC BY 4.0
Библиотека
keras
Опубликована
26 сен 2026

heart-disease-prediction

Классификация изображенийИзображение → label3 профессии

Модель на основе ResNet50V2 классифицирует изображения распечаток ЭКГ с 12 отведениями по четырём категориям сердечных состояний.

158скачиваний за 30 дней0лайковвеса обновлены26 сен 2026

Бенчмарки

Как модель справилась с задачами пользователей ailist и что о ней публикуют открытые лидерборды

Публичные оценки

Из открытых лидербордов. Сравнивайте результаты одного теста при одинаковых условиях — отсутствие оценки не значит, что модель хуже.

В подключённых источниках результатов для этой модели пока нет.

Что умеет модель

Описание составлено по карточке модели и метаданным Hugging Face

FarhanKO выпустил модель классификации изображений сканированных распечаток ЭКГ с 12 отведениями. Основная модель — дообученная на ImageNet ResNet50V2; в репозитории также представлены дообученные EfficientNetB0 и DenseNet121. Конвейер сначала проверяет, похож ли вход на распечатку ЭКГ, затем классифицирует её как Abnormal_Heartbeat, History_of_MI, Myocardial_Infarction или Normal и направляет случаи с низкой уверенностью на ручную проверку. В полном конвейере Grad-CAM показывает области, повлиявшие на результат.

Модель принимает RGB-изображение сетки ЭКГ, включая обрезанный фрагмент или распечатку исходного формата, и выдаёт вероятности четырёх классов. Она предназначена для исследовательских и учебных экспериментов с классификацией ЭКГ. В тестировании на 74 ЭКГ развёрнутая ResNet50V2 показала точность 0,878 и macro-F1 0,850, однако обучающие данные включают только 491 уникальную ЭКГ из одной больницы. Модель и обучающие данные распространяются по лицензии CC BY 4.0. README прямо указывает, что модель не является медицинским устройством и не должна использоваться для постановки диагноза или выбора лечения.

Сценарии применения

  • классификация сканированной ЭКГ как нормальной или аномальной
  • выявление изображений ЭКГ с признаками инфаркта миокарда
  • разделение ЭКГ с текущим инфарктом и перенесённым инфарктом
  • отбор изображений ЭКГ для исследовательского анализа
  • направление неуверенных классификаций на ручную проверку

Ограничения

Обучение выполнено на 491 уникальной ЭКГ из одной больницы; другие аппараты, шаблоны и типы изображений не проверялись, а класс инфаркта миокарда представлен лишь 30 уникальными ЭКГ. Модель не является медицинским устройством и не предназначена для диагностики или решений о лечении.

Для каких профессий подходит3

Разделы каталога профессий, в задачах которых используется эта модель

Все профессии

Карточка модели

README от автора на Hugging Face, как он его опубликовал

Открыть на Hugging Face

12-Lead ECG Classifier (ResNet50V2)

Classifies a scanned 12-lead ECG printout into one of four classes: Abnormal_Heartbeat, History_of_MI, Myocardial_Infarction, Normal.

The model runs as a cascade:

  1. An out-of-distribution (OOD) gate rejects images that are not ECG printouts.
  2. The classifier scores the four classes.
  3. A confidence check sends uncertain cases to manual review.
  4. In the full pipeline, Grad-CAM shows which part of the trace drove the answer.

These models are the image half of the heart module in Disease-Risk-Prediction.

Research and education only. This is not a medical device. It was trained on 491 ECGs from a single hospital and must not be used for diagnosis or treatment decisions.

Quick start

pip install -r requirements.txt     # keras 3, torch, numpy, pillow, huggingface_hub
from huggingface_hub import hf_hub_download
import importlib.util

REPO_ID = "<your-hf-username>/heart-ecg-classifier"
spec = importlib.util.spec_from_file_location("inference", hf_hub_download(REPO_ID, "inference.py"))
inference = importlib.util.module_from_spec(spec); spec.loader.exec_module(inference)

clf = inference.ECGClassifier(REPO_ID)          # downloads metadata, OOD gate and ResNet50V2_FT (~210 MB)
clf.predict("ecg.png")
# {'status': 'accepted', 'label': 'Normal', 'confidence': 0.985, 'p_abnormal': 0.015,
#  'probabilities': {'Abnormal_Heartbeat': 0.0003, 'History_of_MI': 0.014, 'Myocardial_Infarction': 0.001, 'Normal': 0.985}}

The command line works too, either from a clone of this repo or with --repo:

python inference.py ecg1.png ecg2.jpg
python inference.py ecg.png --repo <your-hf-username>/heart-ecg-classifier --ensemble
MI(12).png: review | Normal (51.5%)
   Normal                    51.5%
   Myocardial_Infarction     48.3%
   Abnormal_Heartbeat         0.1%
   History_of_MI              0.1%
Normal(104).png: accepted | Normal (98.5%)
   Normal                    98.5%
   History_of_MI              1.4%
   Myocardial_Infarction      0.1%
   Abnormal_Heartbeat         0.0%

The first ECG above is a real infarction that the model is unsure about. It is sent to review rather than being reported as Normal, which is the job of the confidence check.

status is one of:

StatusMeaning
acceptedTop-class probability ≥ 0.75
reviewTop-class probability < 0.75: flag for a clinician
rejectedThe OOD gate says this is not a 12-lead ECG printout; it is not classified

Input

  • Accepted formats: an RGB image of the ECG grid. That can be a crop like the training data (about 1.7 : 1), or a full 2213 × 1572 printout from the source dataset, which is cropped to the grid automatically.
  • Preprocessing: RGB → crop (full printouts only) → resize to 448 × 256 (width × height) with PIL BOX resampling → float32 in 0–255.
  • Do not divide by 255. Each model has its own rescaling layer built in.

If you load a .keras file directly instead of using inference.py:

import os; os.environ["KERAS_BACKEND"] = "torch"   # before importing keras
import keras
model = keras.models.load_model("ResNet50V2_FT_best.keras", compile=False)
probs = model.predict(x)   # x: (N, 256, 448, 3) float32, 0-255; classes in metadata.json order

Files

FileSizeWhat it is
ResNet50V2_FT_best.keras207 MBDeployed model. ImageNet ResNet50V2, fine-tuned
EfficientNetB0_FT_best.keras31 MBEfficientNetB0, fine-tuned (ensemble member)
DenseNet121_FT_best.keras36 MBDenseNet121, fine-tuned (ensemble member)
ResNet50V2_best.keras · EfficientNetB0_best.keras · DenseNet121_best.keras97 / 20 / 31 MBPhase-1 checkpoints (frozen backbone, head only), for comparison
Custom_CNN_best.keras5 MB4-block CNN trained from scratch (baseline)
ood_gate.npz1.2 MBOOD gate: unit-normalised ResNet50V2_FT embeddings of the 343 training ECGs, k = 5, threshold
metadata.json–Class order, input size, crop box, confidence threshold, deployed model, ensemble members, test metrics
inference.py–Stand-alone cascade (stages 1–3)
requirements.txt–Dependencies for inference.py

Every .keras file takes a (N, 256, 448, 3) input and outputs softmax probabilities for the 4 classes, in the order listed in metadata.json.

Training data

ECG Images dataset of Cardiac Patients, by Ali Haider Khan and Muzammil Hussain (Mendeley Data v2, 2021, doi:10.17632/gwbz3fsgp8.2, CC BY 4.0). The ECGs were collected at the Ch. Pervaiz Elahi Institute of Cardiology, Multan, Pakistan.

The published dataset has 928 files, but only 491 distinct ECGs. The Myocardial Infarction class has 239 files covering just 30 ECGs, and every Normal and History-of-MI ECG appears twice. Exact duplicates were removed by MD5 hash before splitting. Each printout was then cropped to the ECG grid, which removes the patient ID, date and heart-rate text a CNN could use as a shortcut. The data was split with stratification, seed 42:

ClassUnique ECGsTrainValTest
Abnormal_Heartbeat2331633535
History_of_MI86601313
Myocardial_Infarction302154
Normal142992122
Total4913437474

The build script and a manifest (every file, its split and the duplicates dropped) are in the GitHub repo under heart/image_based/data/.

Training

  • Framework: Keras 3.14 on the PyTorch 2.11 backend, trained on an RTX 5060 (8 GB). Seed 42.
  • Head: GlobalAveragePooling → Dense(256, ReLU) → Dropout(0.4) → Dense(4, softmax). The backbones are ImageNet-pretrained ResNet50V2, EfficientNetB0 and DenseNet121 from Keras Applications.
  • Phase 1: the backbone is frozen. Adam at 1e-3, up to 40 epochs.
  • Phase 2 (_FT): the last 30 backbone layers are unfrozen, with BatchNorm kept frozen. Adam at 1e-4, up to 25 epochs.
  • Common to both phases:
    • Batch size 8, categorical cross-entropy, balanced class weights.
    • EarlyStopping on val loss (patience 10, restores the best weights).
    • ReduceLROnPlateau (factor 0.3, patience 4).
    • The checkpoint with the best val loss is kept.
  • Augmentation: rotation ±0.005 turns (about ±2°), zoom ±5 %, translation ±3 %, contrast ±0.2, with white fill. No flips, because a mirrored ECG is physiologically impossible.
  • Model selection: the deployed model has the highest validation macro-F1, with the lowest validation loss as a tie-breaker. The test set was not used for selection.
  • Confidence threshold: 0.75.
  • OOD gate threshold: each training ECG is scored by its mean distance to its 5 nearest other training ECGs (leave-one-out). The threshold is the 99th percentile of those scores.

Results

The held-out test set has 74 ECGs.

ModelVal macro-F1Test acc.Test macro-F1Test macro ROC-AUCTest log-loss
Custom CNN0.3950.6890.3880.8530.843
ResNet50V2 (phase 1)0.5860.6220.5890.9380.878
ResNet50V2 (fine-tuned) — deployed0.8050.8780.8500.9750.373
EfficientNetB0 (phase 1)0.4420.7570.5510.8690.883
EfficientNetB0 (fine-tuned)0.6840.8380.7490.9200.601
DenseNet121 (phase 1)0.5110.6620.5280.9310.843
DenseNet121 (fine-tuned)0.5410.6490.5970.9270.961
Soft-voting ensemble (3 × FT)0.7950.8920.8900.9710.527

The 95 % bootstrap confidence intervals for the deployed model are 0.80–0.95 for accuracy and 0.66–0.95 for macro-F1.

The ensemble scores higher on test but lower on validation, and its probabilities are less well calibrated. It is therefore available through --ensemble but is not the default. Choosing it for its test score would mean selecting on the test set.

Per-class results for the deployed model on the test set:

ClassPrecisionRecallF1Support
Abnormal_Heartbeat0.940.860.9035
History_of_MI0.920.850.8813
Myocardial_Infarction0.750.750.754
Normal0.810.950.8822

Confidence check (threshold 0.75):

  • 72 % of test ECGs are accepted, and 96.2 % of those are correct.
  • The 28 % flagged for review are 66.7 % correct.
  • 7 of the 9 test errors are flagged.

OOD gate:

  • Rejects 0 % of the validation and test ECGs.
  • Rejects 100 % of random noise, blank pages, grey speckle, 60 chest X-rays and line-chart images.

inference.py reproduces the test accuracy exactly: 0.8784 for the single model and 0.8919 for the ensemble.

Limitations

  • Tiny MI class. There are only 30 distinct Myocardial Infarction ECGs, and 4 of them are in the test set. Per-class MI numbers are only indicative.
  • One source. All ECGs come from one hospital, one ECG machine and one print template. Other machines, lead layouts, paper speeds, phone photos or digital ECG exports are untested, and the OOD gate may reject them.
  • Split by ECG, not by patient. The dataset does not publish patient IDs, so different ECGs from the same patient may appear in both train and test. Only exact duplicates were removed.
  • Coarse labels. The dataset does not give the arrhythmia type, the location of the infarct, or how long ago a past MI happened.
  • Possible shortcut. For some Normal and Abnormal Heartbeat ECGs, the Grad-CAM heat sits on the right edge of the printout rather than on the waveform. For MI, it sits on the ST-elevated chest leads, as expected.

The model weights are released under CC BY 4.0, the same licence as the training data.

Как запустить

На своей GPU в ailist. Цена — по текущим предложениям провайдеров

GPU в ailist

Универсальный рантайм · keras

Нельзя запустить

Keras/TensorFlow-модели рантайм не загружает.

Ревизия весов
f1d3524

0 моделей