ECG Signal Classification
The problem
Classify patients as healthy or as having one of two heart conditions from raw ECG signal data, with only 115 patients split unevenly across three classes, 26 healthy, 80 with myocardial infarction, 9 with cardiomyopathy. The real difficulty was not the classification itself, it was that even a 95% accurate model can still feel insufficient here: a false negative means telling a sick patient they are healthy, and the raw signal itself is noisy with baseline drift and inconsistent between individuals before any modeling can begin.
My approach
- Architecture: rather than feeding the raw 30,000-point signal per patient directly into a model, with only 115 patients that would be far too high-dimensional to learn from, R-peaks were detected per heartbeat and used to derive clinically meaningful features, RR interval, heart rate variability, QRS duration, PR and QT intervals, alongside frequency-domain features from FFT, wavelet transforms, and power spectral density.
- Iteration: three different preprocessing workflows were tried, each ordering normalization and Butterworth high-pass filtering differently, and compared by checking whether known problem patients showed correct R-peaks afterward, rather than assuming one ordering would work and moving on.
- Trade-off: a single global amplitude threshold for R-peak detection did not work across all patients. A handful of patients needed a manually adjusted threshold, either because the default missed real peaks entirely or picked up noise as if it were a heartbeat. Rather than force one threshold on every signal, thresholds were tuned per patient where the data required it.
- Handling scarcity and imbalance: outlier removal was applied per class separately using z-scores, since the three classes had very different sizes and treating them identically risked stripping the minority classes of already-scarce data.
- Model choice: instead of picking a single best-performing model, k-NN and XGBoost predictions were combined into a weighted blend, XGBoost weighted higher since it performed better individually, since a single held-out test result on a dataset this small is not a fully reliable signal of which model actually generalizes best.
Results
- Improved from a 42% k-NN baseline to 64% accuracy using the blended k-NN and XGBoost model, a 52% relative improvement.
- Ranked second among competing groups on this challenge.
- Derived interpretable, clinically grounded features, RR interval, QRS duration, heart rate variability, rather than relying on opaque features from the raw signal.
What I would do differently
The P, Q, S, and T wave distances from each R-peak were estimated from a single patient's reading and one reference diagram found online, then applied as fixed offsets to all 115 patients regardless of which class they belonged to or how their individual signal actually looked. That was a reasonable simplification given the time available, but real ECG morphology varies by individual and by condition. Next time, I would validate those offsets against a handful of patients from each class before applying them uniformly, rather than assuming one patient's anatomy generalizes to the full dataset.