AIOmarRehan commited on
Commit
9c92b8b
·
verified ·
1 Parent(s): 174e627

Upload 2 files

Browse files
Files changed (2) hide show
  1. InceptionV3_Brain_Tumor_MRI.h5 +3 -0
  2. README.md +361 -3
InceptionV3_Brain_Tumor_MRI.h5 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:bf2329f8276083fe7883defc1e647555c6dee8a161b83698ca53dbe379a2c271
3
+ size 100823584
README.md CHANGED
@@ -1,3 +1,361 @@
1
- ---
2
- license: mit
3
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # **Brain Tumor Classification Using InceptionV3 and Grad-CAM**
2
+
3
+ A complete deep learning pipeline for **brain tumor classification** using MRI scans.
4
+ This project demonstrates:
5
+
6
+ * **End-to-end data preprocessing**
7
+ * **Augmentation & dataset balancing**
8
+ * **Efficient tf.data pipelines**
9
+ * **Transfer learning with InceptionV3**
10
+ * **Deep model evaluation**
11
+ * **Grad-CAM interpretability**
12
+ * **LaTeX mathematical explanations**
13
+
14
+ ---
15
+
16
+ ## **1. Dataset Exploration & Inspection**
17
+
18
+ We begin by recursively scanning all MRI images and creating a structured DataFrame:
19
+
20
+ ```python
21
+ from pathlib import Path
22
+ import pandas as pd
23
+
24
+ image_extensions = {'.jpg', '.jpeg', '.png'}
25
+ paths = [
26
+ (path.parts[-2], path.name, str(path))
27
+ for path in Path("/content/my_data").rglob('*.*')
28
+ if path.suffix.lower() in image_extensions
29
+ ]
30
+
31
+ df = pd.DataFrame(paths, columns=['class', 'image', 'full_path'])
32
+ df = df.sort_values('class').reset_index(drop=True)
33
+ df.head()
34
+ ```
35
+
36
+ Count images per class:
37
+
38
+ ```python
39
+ class_count = df['class'].value_counts()
40
+ print(class_count)
41
+ ```
42
+
43
+ ### **Visualizations**
44
+
45
+ ```python
46
+ import matplotlib.pyplot as plt
47
+
48
+ plt.figure(figsize=(32,16))
49
+ class_count.plot(kind='bar', edgecolor='black')
50
+ plt.title('Number of Images per Class')
51
+ plt.show()
52
+ ```
53
+
54
+ ### **Insights**
55
+
56
+ * Classes are **imbalanced**
57
+ * Images have **variable resolution**
58
+ * Some outliers require **cleaning**
59
+
60
+ ---
61
+
62
+ ## **2. Data Cleaning & Quality Checks**
63
+
64
+ ### **Duplicate removal using MD5 hashes**
65
+
66
+ ```python
67
+ import hashlib
68
+
69
+ def get_hash(file_path):
70
+ with open(file_path, 'rb') as f:
71
+ return hashlib.md5(f.read()).hexdigest()
72
+
73
+ df['file_hash'] = df['full_path'].apply(get_hash)
74
+ df_unique = df.drop_duplicates(subset='file_hash', keep='first')
75
+ ```
76
+
77
+ ### **Additional checks**
78
+
79
+ * Corrupted image detection
80
+ * Resolution anomalies
81
+ * Brightness/contrast outliers
82
+
83
+ Cleaning ensures a **robust dataset** with minimal noise.
84
+
85
+ ---
86
+
87
+ ## **3. Data Augmentation & Class Balancing**
88
+
89
+ Target ~2,000 images per class using heavy augmentation:
90
+
91
+ ```python
92
+ from tensorflow.keras.preprocessing.image import ImageDataGenerator
93
+
94
+ datagen = ImageDataGenerator(
95
+ rotation_range=20,
96
+ width_shift_range=0.1,
97
+ height_shift_range=0.1,
98
+ shear_range=0.1,
99
+ zoom_range=0.1,
100
+ horizontal_flip=True,
101
+ fill_mode='nearest'
102
+ )
103
+ ```
104
+
105
+ Used for minority class upsampling and preventing overfitting.
106
+
107
+ ---
108
+
109
+ ## **4. Image Preprocessing Pipeline**
110
+
111
+ ```python
112
+ import tensorflow as tf
113
+
114
+ def preprocess_image(path, target_size=(512, 512), augment=True):
115
+ img = tf.io.read_file(path)
116
+ img = tf.image.decode_image(img, channels=3)
117
+ img = tf.image.resize(img, target_size)
118
+ img = tf.cast(img, tf.float32) / 255.0
119
+
120
+ if augment:
121
+ img = tf.image.random_flip_left_right(img)
122
+ img = tf.image.random_flip_up_down(img)
123
+ img = tf.image.random_brightness(img, max_delta=0.1)
124
+ img = tf.image.random_contrast(img, 0.9, 1.1)
125
+
126
+ return tf.clip_by_value(img, 0.0, 1.0)
127
+ ```
128
+
129
+ * **Train set:** augmentation enabled
130
+ * **Validation/Test sets:** kept clean
131
+
132
+ ---
133
+
134
+ ## **5. Dataset Preparation with `tf.data`**
135
+
136
+ ```python
137
+ AUTOTUNE = tf.data.AUTOTUNE
138
+ batch_size = 32
139
+
140
+ train_ds = tf.data.Dataset.from_tensor_slices((train_paths, train_labels))
141
+ train_ds = train_ds.shuffle(len(train_paths))
142
+ train_ds = train_ds.map(
143
+ lambda x, y: (preprocess_image(x, augment=True), y),
144
+ num_parallel_calls=AUTOTUNE
145
+ )
146
+ train_ds = train_ds.batch(batch_size).prefetch(AUTOTUNE)
147
+ ```
148
+
149
+ Benefits:
150
+
151
+ * Parallel loading
152
+ * Smart prefetching
153
+ * GPU utilization maximized
154
+
155
+ ---
156
+
157
+ ## **6. Model Architecture: InceptionV3**
158
+
159
+ Transfer learning from ImageNet:
160
+
161
+ ```python
162
+ from tensorflow.keras.applications.inception_v3 import InceptionV3
163
+ from tensorflow.keras.layers import GlobalAveragePooling2D, Dense, Dropout
164
+ from tensorflow.keras.models import Model
165
+
166
+ inception = InceptionV3(input_shape=input_shape, weights='imagenet', include_top=False)
167
+
168
+ for layer in inception.layers:
169
+ layer.trainable = False
170
+
171
+ x = GlobalAveragePooling2D()(inception.output)
172
+ x = Dense(512, activation='relu')(x)
173
+ x = Dropout(0.5)(x)
174
+ prediction = Dense(len(le.classes_), activation='softmax')(x)
175
+
176
+ model = Model(inputs=inception.input, outputs=prediction)
177
+ ```
178
+
179
+ ### Why InceptionV3?
180
+
181
+ * Factorized convolutions
182
+ * Multi-scale feature extraction
183
+ * Lightweight and fast
184
+ * Strong performance in medical imaging
185
+
186
+ ---
187
+
188
+ ## **7. Training & Callbacks**
189
+
190
+ ```python
191
+ from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint, ReduceLROnPlateau
192
+
193
+ model.compile(
194
+ loss='sparse_categorical_crossentropy',
195
+ optimizer='adam',
196
+ metrics=['accuracy']
197
+ )
198
+
199
+ callbacks = [
200
+ EarlyStopping(monitor='val_loss', patience=40, restore_best_weights=True),
201
+ ModelCheckpoint("best_model.h5", save_best_only=True, monitor='val_loss'),
202
+ ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=10, min_lr=1e-5)
203
+ ]
204
+ ```
205
+
206
+ Training:
207
+
208
+ ```python
209
+ history = model.fit(train_ds, validation_data=val_ds, epochs=50, callbacks=callbacks)
210
+ ```
211
+
212
+ ---
213
+
214
+ ## **8. Training Curves**
215
+
216
+ ```python
217
+ import matplotlib.pyplot as plt
218
+
219
+ plt.plot(history.history['accuracy'], label='Train Accuracy')
220
+ plt.plot(history.history['val_accuracy'], label='Val Accuracy')
221
+ plt.title('Training vs Validation Accuracy')
222
+ plt.legend()
223
+ plt.show()
224
+ ```
225
+
226
+ * Curves indicate **smooth convergence**
227
+ * Small train/val gap → **limited overfitting**
228
+
229
+ ---
230
+
231
+ ## **9. Performance Metrics**
232
+
233
+ ### Confusion Matrix
234
+
235
+ ```python
236
+ from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
237
+
238
+ cm = confusion_matrix(y_true, y_pred)
239
+ ConfusionMatrixDisplay(cm, display_labels=le.classes_).plot(cmap='Blues')
240
+ ```
241
+ <p align="center">
242
+ <img src="https://files.catbox.moe/wuynop.png" width="100%">
243
+ </p>
244
+
245
+ ### Multi-class AUC (One-vs-Rest)
246
+
247
+ **Macro AUC formula:**
248
+
249
+ <img src="https://latex.codecogs.com/svg.image?\text{AUC}_{macro}=\frac{1}{K}\sum_{i=1}^{K}\text{AUC}_i"/>
250
+
251
+ ```python
252
+ from sklearn.preprocessing import label_binarize
253
+ from sklearn.metrics import roc_curve, auc
254
+
255
+ y_true_bin = label_binarize(y_true, classes=np.arange(len(le.classes_)))
256
+ ```
257
+ <p align="center">
258
+ <img src="https://files.catbox.moe/w3fazk.png" width="100%">
259
+ </p>
260
+
261
+ ---
262
+
263
+ ## **10. Grad-CAM: Interpretability**
264
+
265
+ Grad-CAM highlights regions the model uses for classification.
266
+
267
+ ### Grad-CAM heatmap:
268
+
269
+ <img src="https://latex.codecogs.com/svg.image?L^c_{\text{Grad-CAM}}=\text{ReLU}\left(\sum_k\alpha_k^cA^k\right)" />
270
+
271
+ Where:
272
+
273
+ <img src="https://latex.codecogs.com/svg.image?\alpha_k^c=\frac{1}{Z}\sum_{i}\sum_{j}\frac{\partial y^c}{\partial A_{ij}^k}" />
274
+
275
+
276
+ Python implementation:
277
+
278
+ ```python
279
+ def gradcam(model, img, cls=None):
280
+ # last conv
281
+ lc = next(l for l in reversed(model.layers) if "conv" in l.name.lower())
282
+ gm = tf.keras.Model(model.input, [lc.output, model.output])
283
+
284
+ with tf.GradientTape() as t:
285
+ conv, pred = gm(img[None])
286
+ cls = tf.argmax(pred[0]) if cls is None else cls
287
+ loss = pred[:, cls]
288
+
289
+ g = t.gradient(loss, conv)
290
+ w = tf.reduce_mean(g, axis=(0,1,2))
291
+ cam = tf.reduce_sum(w * conv[0], -1)
292
+
293
+ cam = tf.nn.relu(cam)
294
+ cam /= tf.reduce_max(cam) + 1e-8
295
+ return cam.numpy()
296
+ ```
297
+
298
+ Visualization example:
299
+
300
+ ```python
301
+ plt.figure(figsize=(20,10))
302
+ for i, img in enumerate(sample_images):
303
+ overlay, info = VizGradCAM(model, img)
304
+ plt.subplot(2, 5, i+1)
305
+ plt.imshow(overlay)
306
+ plt.axis("off")
307
+ plt.title(f"True Label: {le.classes_[sample_labels[i]]}")
308
+ plt.show()
309
+ ```
310
+
311
+ <p align="center">
312
+ <img src="https://files.catbox.moe/ysg2yc.png" width="100%">
313
+ </p>
314
+
315
+ > **Note:** When the model is highly confident in a prediction, the Grad-CAM gradients become near-zero, producing little to no heatmap activation.
316
+
317
+ ---
318
+
319
+ ## **11. Technical LaTeX Notes**
320
+
321
+ ### Sparse Categorical Crossentropy
322
+
323
+ <img src="https://latex.codecogs.com/svg.image?L=-\frac{1}{N}\sum_{i=1}^{N}\log(p_{i,y_i})" />
324
+
325
+
326
+ ### Global Average Pooling
327
+
328
+ <img src="https://latex.codecogs.com/svg.image?f_c=\frac{1}{h \cdot \omega}\sum_{i=1}^{h}\sum_{j=1}^{\omega}F_{i,j,c}" />
329
+
330
+
331
+ ---
332
+
333
+ ## **12. Model Saving**
334
+
335
+ ```python
336
+ model.save("InceptionV3_Brain_Tumor_MRI.h5")
337
+ ```
338
+
339
+ ---
340
+
341
+ ## **13. Results**
342
+ > **Note:** Click the image below to view the video showcasing the project’s results.
343
+ <a href="https://files.catbox.moe/27ct3j.mp4">
344
+ <img src="https://images.unsplash.com/photo-1611162616475-46b635cb6868?q=80&w=1974&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" width="400">
345
+ </a>
346
+
347
+ <hr style="border-bottom: 5px solid gray; margin-top: 10px;">
348
+
349
+ > **Note:** If the video above is not working, you can access it directly via the link below.
350
+
351
+ [Watch Demo Video](Results/InceptionV3_Brain_Tumor_MRI.mp4)
352
+
353
+ ---
354
+
355
+ ## **Key Takeaways**
356
+
357
+ * Strong data cleaning = reliable model
358
+ * Heavy augmentation reduces bias
359
+ * InceptionV3 provides excellent feature extraction
360
+ * Evaluation metrics reveal clinical reliability
361
+ * Grad-CAM adds essential interpretability