Skip to content

Commit 6b8501d

Browse files
docs: Add markdown explanations for key notebook cells
Added brief markdown descriptions above major code blocks to improve readability.
1 parent 52ceb92 commit 6b8501d

2 files changed

Lines changed: 135 additions & 14 deletions

File tree

ecg_preprocessing.ipynb

Lines changed: 77 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
{
22
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# ECG Signal Preprocessing\n",
8+
"\n",
9+
"This notebook performs preprocessing of ECG signals from the MIT-BIH Arrhythmia Database, including signal filtering, R-peak detection, and beat segmentation."
10+
]
11+
},
312
{
413
"cell_type": "code",
514
"execution_count": 2,
@@ -56,6 +65,14 @@
5665
"!pip install wfdb"
5766
]
5867
},
68+
{
69+
"cell_type": "markdown",
70+
"metadata": {},
71+
"source": [
72+
"### Setup\n",
73+
"Installing and importing required libraries for ECG signal processing"
74+
]
75+
},
5976
{
6077
"cell_type": "code",
6178
"execution_count": 3,
@@ -199,6 +216,14 @@
199216
"print(f\"Download complete! Files saved to: {download_path}\")"
200217
]
201218
},
219+
{
220+
"cell_type": "markdown",
221+
"metadata": {},
222+
"source": [
223+
"### Data Download\n",
224+
"Downloading the MIT-BIH Arrhythmia Database, a standard dataset for ECG analysis"
225+
]
226+
},
202227
{
203228
"cell_type": "code",
204229
"execution_count": 6,
@@ -220,6 +245,14 @@
220245
" return y"
221246
]
222247
},
248+
{
249+
"cell_type": "markdown",
250+
"metadata": {},
251+
"source": [
252+
"### Signal Filtering Functions\n",
253+
"Implementing bandpass filter for noise removal from ECG signals (0.5-40 Hz)"
254+
]
255+
},
223256
{
224257
"cell_type": "code",
225258
"execution_count": 7,
@@ -242,9 +275,17 @@
242275
" return 'Q' # Other/Unknown"
243276
]
244277
},
278+
{
279+
"cell_type": "markdown",
280+
"metadata": {},
281+
"source": [
282+
"### Beat Classification\n",
283+
"Function to group different beat annotations into main categories (Normal, Supraventricular, Ventricular, Fusion, Unknown)"
284+
]
285+
},
245286
{
246287
"cell_type": "code",
247-
"execution_count": 8,
288+
"execution_count": null,
248289
"metadata": {
249290
"colab": {
250291
"base_uri": "https://localhost:8080/"
@@ -277,25 +318,20 @@
277318
"all_X = []\n",
278319
"all_y = []\n",
279320
"\n",
280-
"# Get list of record files\n",
281321
"record_files = [f.split('.')[0] for f in os.listdir(download_path) if f.endswith('.dat')]\n",
282322
"print(f\"\\nFound {len(record_files)} records to process\")\n",
283323
"\n",
284-
"# Process each record\n",
285324
"for rec_name in tqdm(sorted(record_files), desc=\"Processing records\"):\n",
286325
" try:\n",
287-
" # Read record and annotations\n",
288326
" record = wfdb.rdrecord(os.path.join(download_path, rec_name))\n",
289327
" annotation = wfdb.rdann(os.path.join(download_path, rec_name), 'atr')\n",
290328
"\n",
291-
" # Get signal from first channel and apply filtering\n",
292329
" signal = record.p_signal[:, 0]\n",
293330
" filtered_signal = bandpass_filter(signal, fs=record.fs)\n",
294331
"\n",
295332
" ann_samples = annotation.sample\n",
296333
" ann_symbols = annotation.symbol\n",
297334
"\n",
298-
" # Extract segments around R-peaks\n",
299335
" segments = []\n",
300336
" labels = []\n",
301337
"\n",
@@ -324,6 +360,14 @@
324360
" continue"
325361
]
326362
},
363+
{
364+
"cell_type": "markdown",
365+
"metadata": {},
366+
"source": [
367+
"### Data Processing\n",
368+
"Processing ECG records: filtering signals, segmenting beats around R-peaks, and extracting features"
369+
]
370+
},
327371
{
328372
"cell_type": "code",
329373
"execution_count": 9,
@@ -379,6 +423,14 @@
379423
" print(f\" {label}: {count} samples ({count/len(y_all)*100:.2f}%)\")\n"
380424
]
381425
},
426+
{
427+
"cell_type": "markdown",
428+
"metadata": {},
429+
"source": [
430+
"### Data Preparation\n",
431+
"Combining processed data, adding channel dimension, and encoding labels for model training"
432+
]
433+
},
382434
{
383435
"cell_type": "code",
384436
"execution_count": 10,
@@ -407,7 +459,7 @@
407459
},
408460
{
409461
"cell_type": "code",
410-
"execution_count": 16,
462+
"execution_count": null,
411463
"metadata": {
412464
"colab": {
413465
"base_uri": "https://localhost:8080/",
@@ -449,7 +501,6 @@
449501
" length: Number of samples to plot\n",
450502
" channel: Channel index (0 or 1 for MIT-BIH)\n",
451503
" \"\"\"\n",
452-
" # Load record\n",
453504
" record = wfdb.rdrecord(os.path.join(download_path, str(record_name)))\n",
454505
" annotation = wfdb.rdann(os.path.join(download_path, str(record_name)), 'atr')\n",
455506
"\n",
@@ -487,9 +538,17 @@
487538
"visualize_signal('200', start=5000, length=1800) # Different record"
488539
]
489540
},
541+
{
542+
"cell_type": "markdown",
543+
"metadata": {},
544+
"source": [
545+
"### Visualization Functions\n",
546+
"Helper function to visualize raw and filtered ECG signals with R-peak annotations"
547+
]
548+
},
490549
{
491550
"cell_type": "code",
492-
"execution_count": 18,
551+
"execution_count": null,
493552
"metadata": {
494553
"colab": {
495554
"base_uri": "https://localhost:8080/",
@@ -520,8 +579,7 @@
520579
"source": [
521580
"plt.figure(figsize=(15, 8))\n",
522581
"for i, label in enumerate(le.classes_):\n",
523-
" idx = np.where(y_all == label)[0][0] # Get first occurrence\n",
524-
" plt.subplot(len(le.classes_), 1, i+1)\n",
582+
" idx = np.where(y_all == label)[0][0] \n",
525583
" plt.plot(X_all[idx, :, 0])\n",
526584
" plt.title(f'Beat Type: {label}')\n",
527585
" plt.ylabel('Amplitude')\n",
@@ -533,6 +591,14 @@
533591
"plt.show()"
534592
]
535593
},
594+
{
595+
"cell_type": "markdown",
596+
"metadata": {},
597+
"source": [
598+
"### Beat Type Visualization\n",
599+
"Plotting sample beats from each category to visualize differences between classes"
600+
]
601+
},
536602
{
537603
"cell_type": "code",
538604
"execution_count": 19,

lstm_model.ipynb

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
{
22
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# LSTM Model for ECG Arrhythmia Classification\n",
8+
"\n",
9+
"This notebook implements a LSTM-based deep learning model to classify ECG signals into different arrhythmia types."
10+
]
11+
},
312
{
413
"cell_type": "markdown",
514
"metadata": {
@@ -9,6 +18,14 @@
918
"#### Import Required Libraries"
1019
]
1120
},
21+
{
22+
"cell_type": "markdown",
23+
"metadata": {},
24+
"source": [
25+
"### Data Processing and Model Libraries\n",
26+
"Importing required libraries for data manipulation, visualization, machine learning, and deep learning:"
27+
]
28+
},
1229
{
1330
"cell_type": "code",
1431
"execution_count": 1,
@@ -33,6 +50,14 @@
3350
"tf.random.set_seed(42)"
3451
]
3552
},
53+
{
54+
"cell_type": "markdown",
55+
"metadata": {},
56+
"source": [
57+
"### Data Loading\n",
58+
"Loading preprocessed ECG data from NPZ file, containing features (X) and labels (y)"
59+
]
60+
},
3661
{
3762
"cell_type": "code",
3863
"execution_count": 2,
@@ -65,6 +90,14 @@
6590
"print(f\"Classes: {label_names}\")\n"
6691
]
6792
},
93+
{
94+
"cell_type": "markdown",
95+
"metadata": {},
96+
"source": [
97+
"### Data Splitting\n",
98+
"Splitting data into training, validation, and test sets using a stratified approach to maintain class distribution"
99+
]
100+
},
68101
{
69102
"cell_type": "code",
70103
"execution_count": 3,
@@ -105,6 +138,14 @@
105138
"print(f\"Test set: {X_test.shape[0]} samples\")\n"
106139
]
107140
},
141+
{
142+
"cell_type": "markdown",
143+
"metadata": {},
144+
"source": [
145+
"### Model Architecture\n",
146+
"Defining a LSTM-based neural network model with dropout layers for regularization"
147+
]
148+
},
108149
{
109150
"cell_type": "code",
110151
"execution_count": 4,
@@ -168,8 +209,7 @@
168209
"\n",
169210
" return model\n",
170211
"\n",
171-
"# Create model\n",
172-
"input_shape = (X_train.shape[1], X_train.shape[2]) # (250, 1)\n",
212+
"input_shape = (X_train.shape[1], X_train.shape[2])\n",
173213
"num_classes = y_train.shape[1]\n",
174214
"\n",
175215
"model = create_lstm_model(input_shape, num_classes)\n"
@@ -403,11 +443,18 @@
403443
" validation_data=(X_val, y_val),\n",
404444
" epochs=50,\n",
405445
" batch_size=128,\n",
406-
" # callbacks=[early_stop, reduce_lr, checkpoint],\n",
407446
" verbose=1\n",
408447
")\n"
409448
]
410449
},
450+
{
451+
"cell_type": "markdown",
452+
"metadata": {},
453+
"source": [
454+
"### Model Training\n",
455+
"Training the LSTM model with Adam optimizer and monitoring multiple metrics"
456+
]
457+
},
411458
{
412459
"cell_type": "code",
413460
"execution_count": null,
@@ -486,6 +533,14 @@
486533
"plt.show()\n"
487534
]
488535
},
536+
{
537+
"cell_type": "markdown",
538+
"metadata": {},
539+
"source": [
540+
"### Training Visualization\n",
541+
"Plotting training metrics (accuracy, loss, precision) to evaluate model performance"
542+
]
543+
},
489544
{
490545
"cell_type": "code",
491546
"execution_count": null,

0 commit comments

Comments
 (0)