OSCR

Brain Tumor Classification in MRI Images Using Combined Transfer Learning and Convolutional Neural Networks.

Code ↔ Paper

8 matches between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 8 matches
  1. [1] § 3. Materials and Methods ↔ custom_cnn.ipynb.ipynb, lines 1–55 · score 0.74 · EfficientNetV2L, MobileNetV2, ResNet152V2, Custom CNN, InceptionV3, pre
  2. [2] § 4. Experimental Results and Analysis ↔ custom_cnn.ipynb.ipynb, lines 1–55 · score 0.73 · Custom CNN model, MobileNetV2, ResNet152V2, InceptionV3, meningioma, pituitary
  3. [3] § 4. Experimental Results and Analysis › 4.1. Evaluation Metrics and Strategy ↔ pretrained_ensemble.ipynb.ipynb, lines 501–538 · score 0.67 · Squared Error, Absolute Error, F1 score, Recall, MAE, RMSE
  4. [4] § 3. Materials and Methods › 3.6. Design and Implementation of the Proposed Ensemble Model ↔ pretrained_ensemble.ipynb.ipynb, lines 554–572 · score 0.65 · EfficientNetV2L, MobileNetV2, ResNet152V2, InceptionV3, trained models, Xception
  5. [5] § 4. Experimental Results and Analysis › 4.4. Classification Results › 4.4.4. Training and Validation Accuracy and Loss Comparison ↔ pretrained_ensemble.ipynb.ipynb, lines 705–757 · score 0.62 · EfficientNetV2L, MobileNetV2, ResNet152V2, InceptionV3, validation, VGG16
  6. [6] § 3. Materials and Methods › 3.6. Design and Implementation of the Proposed Ensemble Model ↔ pretrained_ensemble.ipynb.ipynb, lines 612–648 · score 0.57 · MobileNetV2, ResNet152V2, InceptionV3, EfficientNetV2, trained models, Xception
  7. [7] § 3. Materials and Methods ↔ pretrained_ensemble.ipynb.ipynb, lines 157–185 · score 0.57 · dense layers, convolutional layers, softmax, class, models
  8. [8] § 3. Materials and Methods › 3.3. Customized CNN and Base Models for Feature Extraction ↔ pretrained_ensemble.ipynb.ipynb, lines 157–185 · score 0.54 · convolutional layers, flattened, ReLU, softmax, activated, ensemble

Paper

Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

Jupyter notebook · 1,078 lines · 37 KB · no license · 6 matches

  1. # %%
  2. import sys
  3. import os
  4. import math
  5. import time
  6. import pathlib
  7. import pickle
  8. import numpy as np
  9. import pandas as pd
  10. import seaborn as sns
  11. import tensorflow as tf
  12. import matplotlib.pyplot as plt
  13. from tensorflow.keras import layers
  14. from tensorflow.keras.models import Model
  15. from tensorflow.keras.optimizers import Adam
  16. from tensorflow.keras.callbacks import ModelCheckpoint, ReduceLROnPlateau
  17. from tensorflow.keras.applications import InceptionV3
  18. from tensorflow.keras.applications import EfficientNetV2L
  19. from tensorflow.keras.applications import ResNet152V2
  20. from tensorflow.keras.applications import Xception
  21. from tensorflow.keras.applications import VGG16
  22. from tensorflow.keras.applications import MobileNetV2
  23. from sklearn.utils.class_weight import compute_class_weight
  24. from tensorflow.keras.models import load_model
  25. from sklearn.metrics import accuracy_score, f1_score, precision_score, recall_score, confusion_matrix, mean_absolute_error, mean_squared_error
  26. # %% [markdown]
  27. # # Dataset paths
  28. # %%
  29. # Dataset paths
  30. train_dir = pathlib.Path('/kaggle/input/brain-tumor-mri-dataset/Training')
  31. test_dir = pathlib.Path('/kaggle/input/brain-tumor-mri-dataset/Testing')
  32. img_height = 224
  33. img_width = 224
  34. batch_size = 32
  35. epochs = 50
  36. # %% [markdown]
  37. # # Data augmentation
  38. # %%
  39. # Dataset loading
  40. train_ds = tf.keras.utils.image_dataset_from_directory(
  41. train_dir,
  42. validation_split=0.2,
  43. subset="training",
  44. seed=123,
  45. image_size=(224, 224),
  46. batch_size=batch_size,
  47. shuffle=True,
  48. interpolation="bilinear",
  49. label_mode="int",
  50. )
  51. # Get class names
  52. class_names = train_ds.class_names
  53. print("Classes in the dataset:", class_names)
  54. # Normalize and apply data augmentation
  55. normalization_layer = tf.keras.layers.Rescaling(1./255)
  56. data_augmentation = tf.keras.Sequential([
  57. tf.keras.layers.RandomFlip("horizontal"),
  58. tf.keras.layers.RandomRotation(0.2),
  59. tf.keras.layers.RandomZoom(0.2),
  60. tf.keras.layers.RandomContrast(0.2),
  61. tf.keras.layers.RandomTranslation(0.1, 0.1),
  62. ])
  63. train_ds = train_ds.map(lambda x, y: (normalization_layer(x), y))
  64. train_ds = train_ds.map(lambda x, y: (data_augmentation(x, training=True), y))
  65. # Validation dataset
  66. val_ds = tf.keras.utils.image_dataset_from_directory(
  67. train_dir,
  68. validation_split=0.2,
  69. subset="validation",
  70. seed=123,
  71. image_size=(224, 224),
  72. batch_size=batch_size,
  73. )
  74. val_ds = val_ds.map(lambda x, y: (normalization_layer(x), y))
  75. # Test dataset
  76. test_ds = tf.keras.utils.image_dataset_from_directory(
  77. test_dir,
  78. image_size=(224, 224),
  79. batch_size=batch_size,
  80. )
  81. test_ds = test_ds.map(lambda x, y: (normalization_layer(x), y))
  82. # %%
  83. def get_class_weights(train_ds, class_names):
  84. print("Calculating class weights...")
  85. labels = []
  86. for image_batch, label_batch in train_ds:
  87. labels.append(label_batch.numpy())
  88. labels = np.concatenate(labels)
  89. class_weights = compute_class_weight('balanced', classes=np.unique(labels), y=labels)
  90. class_weight_dict = {i: class_weights[i] for i in range(len(class_names))}
  91. print("Class weights calculated.")
  92. return class_weight_dict
  93. class_weight_dict = get_class_weights(train_ds, class_names)
  94. # %%
  95. # General Imports
  96. import matplotlib.pyplot as plt
  97. import seaborn as sns
  98. import numpy as np
  99. import os
  100. from sklearn.metrics import confusion_matrix
  101. # Neural Network imports
  102. import tensorflow as tf
  103. from tensorflow.keras.models import Sequential
  104. from tensorflow.keras.models import load_model
  105. from tensorflow.keras.layers import MaxPooling2D
  106. from tensorflow.keras.layers import Conv2D
  107. from tensorflow.keras.layers import Dense
  108. from tensorflow.keras.layers import Dropout
  109. from tensorflow.keras.layers import Flatten
  110. from tensorflow.keras.layers import Input
  111. from tensorflow.keras.optimizers import Adam
  112. # Image augmentation importrs
  113. from tensorflow.keras.utils import load_img
  114. from tensorflow.keras.preprocessing import image
  115. from tensorflow.keras.layers import RandomRotation
  116. from tensorflow.keras.layers import RandomContrast
  117. from tensorflow.keras.layers import RandomZoom
  118. from tensorflow.keras.layers import RandomFlip
  119. from tensorflow.keras.layers import RandomTranslation
  120. # Training Model callbacks
  121. from tensorflow.keras.callbacks import ReduceLROnPlateau
  122. from tensorflow.keras.callbacks import ModelCheckpoint
  123. # Check if GPU is available
  124. print(f'Tensorflow Version: {tf.__version__}')
  125. print("GPU Available:", tf.config.list_physical_devices('GPU')[0])
  126. # %%
  127. for image, label in train_ds.take(1):
  128. print("Label shape:", label.shape)
  129. print("Label:", label)
  130. # %%
  131. # # Building model
  132. image_size=(224, 224,3)
  133. model = Sequential([
  134. # Input tensor shape
  135. Input(image_size),
  136. # Convolutional layer 1
  137. Conv2D(64, (5, 5), activation="relu"),
  138. MaxPooling2D(pool_size=(3, 3)),
  139. # Convolutional layer 2
  140. Conv2D(64, (5, 5), activation="relu"),
  141. MaxPooling2D(pool_size=(3, 3)),
  142. # Convolutional layer 3
  143. Conv2D(128, (4, 4), activation="relu"),
  144. MaxPooling2D(pool_size=(2, 2)),
  145. # Convolutional layer 4
  146. Conv2D(128, (4, 4), activation="relu"),
  147. MaxPooling2D(pool_size=(2, 2)),
  148. Flatten(),
  149. # Dense layers
  150. Dense(512, activation="relu"),
  151. Dense(len(class_names), activation="softmax")
  152. ])
  153. # Model summary
  154. model.summary()
  155. # COompilng model with Adam optimizer
  156. optimizer = Adam(learning_rate=0.001, beta_1=0.85, beta_2=0.9925)
  157. model.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics= ['accuracy'])
  158. import os
  159. import json
  160. import time
  161. import tensorflow as tf
  162. from tensorflow.keras.callbacks import ModelCheckpoint, ReduceLROnPlateau
  163. def train_custom_model(model, model_name, train_ds, val_ds, test_ds,
  164. learning_rate=0.001, epochs=50, class_weight=None,
  165. extra_callbacks=None):
  166. # Create save directory
  167. save_dir = '/kaggle/working/'
  168. os.makedirs(save_dir, exist_ok=True)
  169. # Compile model (if not compiled already)
  170. optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate, beta_1=0.85, beta_2=0.9925)
  171. # model.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics=['accuracy'])
  172. model.compile(optimizer=optimizer, loss='sparse_categorical_crossentropy', metrics=['accuracy'])
  173. print(f"\nSummary of {model_name}:")
  174. model.summary()
  175. # File paths
  176. model_path = os.path.join(save_dir, f'{model_name}.keras')
  177. best_model_path = os.path.join(save_dir, f'{model_name}_best.keras')
  178. history_path = os.path.join(save_dir, f'{model_name}_history.json')
  179. eval_path = os.path.join(save_dir, f'{model_name}_evaluation.json')
  180. time_path = os.path.join(save_dir, f'{model_name}_computation_time.txt')
  181. # Default callbacks
  182. model_checkpoint = ModelCheckpoint(best_model_path, monitor='val_loss', save_best_only=True, verbose=False)
  183. reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.8, patience=4, min_lr=1e-4, verbose=False)
  184. # Merge with extra callbacks if any
  185. callbacks = [model_checkpoint, reduce_lr]
  186. if extra_callbacks:
  187. callbacks.extend(extra_callbacks)
  188. # Train model with timing
  189. start_time = time.time()
  190. history = model.fit(
  191. train_ds,
  192. validation_data=val_ds,
  193. epochs=epochs,
  194. class_weight=class_weight,
  195. callbacks=callbacks,
  196. shuffle=True,
  197. verbose=True
  198. )
  199. end_time = time.time()
  200. computation_time = end_time - start_time
  201. print(f"Model training took {computation_time:.2f} seconds.")
  202. print(f"\nEvaluating {model_name}...")
  203. print(f"\nClass Weights used in training {model_name}: {class_weight}")
  204. # Evaluate model
  205. evaluation = model.evaluate(test_ds)
  206. loss, accuracy = evaluation
  207. print('Loss:', loss)
  208. print(f'Test Accuracy: {accuracy * 100:.2f}%')
  209. # Save final model
  210. model.save(model_path)
  211. print(f"Model saved to {model_path}")
  212. # Save training history
  213. with open(history_path, 'w') as f:
  214. history_dict = {key: [float(val) for val in values] for key, values in history.history.items()}
  215. json.dump(history_dict, f, indent=4)
  216. print(f"Training history saved to {history_path}")
  217. # Save evaluation
  218. eval_dict = {
  219. 'loss': float(loss),
  220. 'accuracy': float(accuracy),
  221. 'metrics': {
  222. 'loss': float(loss),
  223. 'accuracy': float(accuracy)
  224. }
  225. }
  226. with open(eval_path, 'w') as f:
  227. json.dump(eval_dict, f, indent=4)
  228. print(f"Evaluation results saved to {eval_path}")
  229. # Save computation time
  230. with open(time_path, 'w') as f:
  231. f.write(f"Training time: {computation_time:.2f} seconds\n")
  232. f.write(f"Training time: {computation_time / 60:.2f} minutes\n")
  233. f.write(f"Training time: {computation_time / 3600:.2f} hours\n")
  234. print(f"Computation time saved to {time_path}")
  235. return model, history, evaluation, computation_time
  236. # Custom callback for reducing learning rate at accuracy values
  237. class ReduceLROnMultipleAccuracies(tf.keras.callbacks.Callback):
  238. def __init__(self, thresholds, factor, monitor='val_accuracy', verbose=1):
  239. super(ReduceLROnMultipleAccuracies, self).__init__()
  240. self.thresholds = thresholds # List of accuracy thresholds
  241. self.factor = factor # Factor to reduce the learning rate
  242. self.monitor = monitor
  243. self.verbose = verbose
  244. self.thresholds_reached = [False] * len(thresholds) # Track each threshold
  245. def on_epoch_end(self, epoch, logs=None):
  246. current_accuracy = logs.get(self.monitor)
  247. for i, threshold in enumerate(self.thresholds):
  248. if current_accuracy >= threshold and not self.thresholds_reached[i]:
  249. optimizer = self.model.optimizer
  250. old_lr = optimizer.learning_rate.numpy()
  251. new_lr = old_lr * self.factor
  252. optimizer.learning_rate.assign(new_lr)
  253. self.thresholds_reached[i] = True # Mark this threshold as reached
  254. if self.verbose > 0:
  255. print(f"\nEpoch {epoch+1}: {self.monitor} reached {threshold}. Reducing learning rate from {old_lr} to {new_lr}.")
  256. # Try a custom callback
  257. thresholds = [0.96, 0.99, 0.9935]
  258. lr_callback = ReduceLROnMultipleAccuracies(thresholds=thresholds, factor=0.75, monitor='val_accuracy', verbose=False)
  259. model_name = "custom_cnn_model"
  260. model_rlr = ReduceLROnPlateau(monitor='val_loss', factor=0.8, min_lr=1e-4, patience=4, verbose=False)
  261. model_mc = ModelCheckpoint('custom_cnn_model_updated.keras', monitor='val_accuracy', mode='max', save_best_only=True, verbose=False)
  262. # Include your custom callback if needed
  263. model, history, evaluation, computation_time = train_custom_model(
  264. model=model,
  265. model_name=model_name,
  266. train_ds=train_ds,
  267. val_ds=test_ds,
  268. test_ds=test_ds,
  269. learning_rate=0.001,
  270. epochs=epochs,
  271. extra_callbacks=[model_rlr, model_mc],
  272. )
  273. # %% [markdown]
  274. # # Balancing using class weights
  275. # %%
  276. # %% [markdown]
  277. # # Create and train model
  278. # %%
  279. # def create_and_train_model(base_model, model_name, train_ds, val_ds, test_ds, num_classes=4, learning_rate=0.0001, epochs=epochs, class_weight=None):
  280. # for layer in base_model.layers[:10]:
  281. # layer.trainable = False
  282. # x = layers.GlobalAveragePooling2D()(base_model.output)
  283. # x = layers.Dense(512, activation='relu', kernel_regularizer=tf.keras.regularizers.l2(0.01))(x)
  284. # x = layers.Dropout(0.4)(x)
  285. # predictions = layers.Dense(num_classes, activation='softmax')(x)
  286. # model = Model(inputs=base_model.inputs, outputs=predictions)
  287. # model.compile(
  288. # optimizer=Adam(learning_rate=learning_rate, beta_1=0.9, beta_2=0.999),
  289. # loss=tf.losses.SparseCategoricalCrossentropy(),
  290. # metrics=['accuracy']
  291. # )
  292. # print(f"\nSummary of {model_name}:")
  293. # model.summary()
  294. # model_checkpoint = ModelCheckpoint(f'{model_name}.keras', monitor='val_loss', save_best_only=True)
  295. # reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=5, min_lr=1e-6)
  296. # start_time = time.time()
  297. # history = model.fit(
  298. # train_ds,
  299. # shuffle=True,
  300. # validation_data=val_ds,
  301. # epochs=epochs,
  302. # class_weight=class_weight,
  303. # callbacks=[model_checkpoint, reduce_lr]
  304. # )
  305. # # End time tracking
  306. # end_time = time.time()
  307. # # Calculate computation time
  308. # computation_time = end_time - start_time
  309. # print(f"Model training took {computation_time:.2f} seconds.")
  310. # print(f"\nEvaluating {model_name}...")
  311. # print(f"\nClass Weights used in training {model_name}: {class_weight}")
  312. # loss, accuracy = model.evaluate(test_ds)
  313. # print('Loss:', loss)
  314. # print(f'Test Accuracy: {accuracy * 100:.2f}%')
  315. # model.save(f'{model_name}.keras')
  316. # evaluation = model.evaluate(test_ds)
  317. # return model, history, evaluation, computation_time
  318. import os
  319. import json
  320. import time
  321. import tensorflow as tf
  322. from tensorflow.keras.layers import Dense, Dropout, GlobalAveragePooling2D
  323. from tensorflow.keras.models import Model
  324. from tensorflow.keras.optimizers import Adam
  325. from tensorflow.keras.callbacks import ModelCheckpoint, ReduceLROnPlateau
  326. def create_and_train_model(base_model, model_name, train_ds, val_ds, test_ds, num_classes=4,
  327. learning_rate=0.0001, epochs=50, class_weight=None):
  328. # Create save directory if it doesn't exist
  329. save_dir = '/kaggle/working/'
  330. os.makedirs(save_dir, exist_ok=True)
  331. # Freeze early layers
  332. for layer in base_model.layers[:10]:
  333. layer.trainable = False
  334. # Build model architecture
  335. x = GlobalAveragePooling2D()(base_model.output)
  336. x = Dense(512, activation='relu', kernel_regularizer=tf.keras.regularizers.l2(0.01))(x)
  337. x = Dropout(0.4)(x)
  338. predictions = Dense(num_classes, activation='softmax')(x)
  339. model = Model(inputs=base_model.inputs, outputs=predictions)
  340. # Compile model
  341. model.compile(
  342. optimizer=Adam(learning_rate=learning_rate, beta_1=0.9, beta_2=0.999),
  343. loss=tf.losses.SparseCategoricalCrossentropy(),
  344. metrics=['accuracy']
  345. )
  346. print(f"\nSummary of {model_name}:")
  347. model.summary()
  348. # Create file paths for saving
  349. model_path = os.path.join(save_dir, f'{model_name}.keras')
  350. best_model_path = os.path.join(save_dir, f'{model_name}_best.keras')
  351. history_path = os.path.join(save_dir, f'{model_name}_history.json')
  352. eval_path = os.path.join(save_dir, f'{model_name}_evaluation.json')
  353. time_path = os.path.join(save_dir, f'{model_name}_computation_time.txt')
  354. # Set up callbacks
  355. model_checkpoint = ModelCheckpoint(best_model_path, monitor='val_loss', save_best_only=True)
  356. reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=5, min_lr=1e-6)
  357. # Train model with time tracking
  358. start_time = time.time()
  359. history = model.fit(
  360. train_ds,
  361. shuffle=True,
  362. validation_data=val_ds,
  363. epochs=epochs,
  364. class_weight=class_weight,
  365. callbacks=[model_checkpoint, reduce_lr]
  366. )
  367. end_time = time.time()
  368. computation_time = end_time - start_time
  369. print(f"Model training took {computation_time:.2f} seconds.")
  370. print(f"\nEvaluating {model_name}...")
  371. print(f"\nClass Weights used in training {model_name}: {class_weight}")
  372. # Evaluate the model
  373. evaluation = model.evaluate(test_ds)
  374. loss, accuracy = evaluation
  375. print('Loss:', loss)
  376. print(f'Test Accuracy: {accuracy * 100:.2f}%')
  377. # Save model
  378. model.save(model_path)
  379. print(f"Model saved to {model_path}")
  380. # Save history
  381. with open(history_path, 'w') as f:
  382. history_dict = {key: [float(val) for val in values] for key, values in history.history.items()}
  383. json.dump(history_dict, f, indent=4)
  384. print(f"Training history saved to {history_path}")
  385. # Save evaluation
  386. eval_dict = {
  387. 'loss': float(loss),
  388. 'accuracy': float(accuracy),
  389. 'metrics': {
  390. 'loss': float(evaluation[0]),
  391. 'accuracy': float(evaluation[1])
  392. }
  393. }
  394. with open(eval_path, 'w') as f:
  395. json.dump(eval_dict, f, indent=4)
  396. print(f"Evaluation results saved to {eval_path}")
  397. # Save computation time
  398. with open(time_path, 'w') as f:
  399. f.write(f"Training time: {computation_time:.2f} seconds\n")
  400. f.write(f"Training time: {computation_time/60:.2f} minutes\n")
  401. f.write(f"Training time: {computation_time/3600:.2f} hours\n")
  402. print(f"Computation time saved to {time_path}")
  403. return model, history, evaluation, computation_time
  404. # %%
  405. def evaluate_model(model, test_ds, model_name):
  406. y_true = []
  407. y_pred = []
  408. for images, labels in test_ds:
  409. predictions = model.predict(images)
  410. y_pred.extend(np.argmax(predictions, axis=1))
  411. y_true.extend(labels.numpy())
  412. y_true = np.array(y_true)
  413. y_pred = np.array(y_pred)
  414. accuracy = accuracy_score(y_true, y_pred)
  415. precision = precision_score(y_true, y_pred, average='weighted')
  416. recall = recall_score(y_true, y_pred, average='weighted')
  417. f1 = f1_score(y_true, y_pred, average='weighted')
  418. mae = mean_absolute_error(y_true, y_pred)
  419. rmse = mean_squared_error(y_true, y_pred, squared=False)
  420. cm = confusion_matrix(y_true, y_pred)
  421. print(f"\nModel Evaluation Metrics for {model_name}:")
  422. print(f"Accuracy: {accuracy:.4f}")
  423. print(f"Precision: {precision:.4f}")
  424. print(f"Recall: {recall:.4f}")
  425. print(f"F1 Score: {f1:.4f}")
  426. print(f"MAE: {mae:.4f}")
  427. print(f"RMSE: {rmse:.4f}")
  428. plt.figure(figsize=(6, 6))
  429. sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=range(4), yticklabels=range(4))
  430. plt.xlabel('Predicted Label')
  431. plt.ylabel('True Label')
  432. plt.title(f'Confusion Matrix - {model_name}')
  433. plt.show()
  434. return accuracy, precision, recall, f1, mae, rmse, cm
  435. # %%
  436. from tensorflow.keras.applications import InceptionV3
  437. # Path to your uploaded weights file
  438. weights_path = '/kaggle/input/inception_v3/tensorflow2/default/1/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5'
  439. # Initialize the model without downloading weights
  440. base_model1 = InceptionV3(weights=None, include_top=False, input_shape=(224, 224, 3))
  441. # Load the weights from your uploaded file
  442. base_model1.load_weights(weights_path)
  443. print("InceptionV3 model loaded successfully with local weights!")
  444. # %% [markdown]
  445. # # Train all models with 30 epochs
  446. # %%
  447. # # Define the base models
  448. # base_model1 = InceptionV3(weights='imagenet', include_top=False, input_shape=(224, 224, 3))
  449. # # base_model2 = EfficientNetV2L(weights='imagenet', include_top=False, input_shape=(224, 224, 3))
  450. # # base_model3 = ResNet152V2(weights='imagenet', include_top=False, input_shape=(224, 224, 3))
  451. # # base_model4 = Xception(weights='imagenet', include_top=False, input_shape=(224, 224, 3))
  452. # # base_model5 = VGG16(weights='imagenet', include_top=False, input_shape=(224, 224, 3))
  453. # # base_model6 = MobileNetV2(weights='imagenet', include_top=False, input_shape=(224, 224, 3))
  454. # %%
  455. model1, history1, evaluation1, time1 = create_and_train_model(base_model1, 'model1_inceptionv3_class_weights', train_ds, val_ds, test_ds, epochs=epochs, class_weight=class_weight_dict)
  456. # # model2, history2, evaluation2, time2 = create_and_train_model(base_model2, 'model2_efficientnetv2l_class_weights', train_ds, val_ds, test_ds, epochs=epochs, class_weight=class_weight_dict)
  457. # # model3, history3, evaluation3, time3 = create_and_train_model(base_model3, 'model3_resnet152v2_class_weights', train_ds, val_ds, test_ds, epochs=epochs, class_weight=class_weight_dict)
  458. # # model4, history4, evaluation4, time4 = create_and_train_model(base_model4, 'model4_xception_class_weights', train_ds, val_ds, test_ds, epochs=epochs, class_weight=class_weight_dict)
  459. # # model5, history5, evaluation5, time5 = create_and_train_model(base_model5, 'model5_vgg16_class_weights', train_ds, val_ds, test_ds, epochs=epochs, class_weight=class_weight_dict)
  460. # # model6, history6, evaluation6, time6 = create_and_train_model(base_model6, 'model6_mobilenetv2_class_weights', train_ds, val_ds, test_ds, epochs=epochs, class_weight=class_weight_dict)
  461. # %%
  462. # from tensorflow.keras.applications import (
  463. # InceptionV3, EfficientNetV2L, ResNet152V2,
  464. # Xception, VGG16, MobileNetV2
  465. # )
  466. # # InceptionV3 (which you already have)
  467. # base_model1 = InceptionV3(weights=None, include_top=False, input_shape=(224, 224, 3))
  468. # base_model1.load_weights('/kaggle/input/inception_v3/tensorflow2/default/1/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5')
  469. # # For EfficientNetV2L
  470. # base_model2 = EfficientNetV2L(weights=None, include_top=False, input_shape=(224, 224, 3))
  471. # base_model2.load_weights('/kaggle/input/efficientnet/tensorflow2/default/1/efficientnetv2-l_notop.h5')
  472. # # For ResNet152V2
  473. # base_model3 = ResNet152V2(weights=None, include_top=False, input_shape=(224, 224, 3))
  474. # base_model3.load_weights('/kaggle/input/resnet/tensorflow2/default/1/resnet152v2_weights_tf_dim_ordering_tf_kernels_notop.h5')
  475. # # For Xception
  476. # base_model4 = Xception(weights=None, include_top=False, input_shape=(224, 224, 3))
  477. # base_model4.load_weights('/kaggle/input/xception/tensorflow2/default/1/xception_weights_tf_dim_ordering_tf_kernels_notop.h5')
  478. # # For VGG16
  479. # base_model5 = VGG16(weights=None, include_top=False, input_shape=(224, 224, 3))
  480. # base_model5.load_weights('/kaggle/input/vgg16/tensorflow2/default/1/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5')
  481. # # For MobileNetV2
  482. # base_model6 = MobileNetV2(weights=None, include_top=False, input_shape=(224, 224, 3))
  483. # base_model6.load_weights('/kaggle/input/mobilenet/tensorflow2/default/1/mobilenet_v2_weights_tf_dim_ordering_tf_kernels_1.0_224_no_top.h5')
  484. # # Now you can train your models
  485. # model1, history1, evaluation1, time1 = create_and_train_model(base_model1, 'model1_inceptionv3_class_weights', train_ds, val_ds, test_ds, epochs=epochs, class_weight=class_weight_dict)
  486. # model2, history2, evaluation2, time2 = create_and_train_model(base_model2, 'model2_efficientnetv2l_class_weights', train_ds, val_ds, test_ds, epochs=epochs, class_weight=class_weight_dict)
  487. # model3, history3, evaluation3, time3 = create_and_train_model(base_model3, 'model3_resnet152v2_class_weights', train_ds, val_ds, test_ds, epochs=epochs, class_weight=class_weight_dict)
  488. # model4, history4, evaluation4, time4 = create_and_train_model(base_model4, 'model4_xception_class_weights', train_ds, val_ds, test_ds, epochs=epochs, class_weight=class_weight_dict)
  489. # model5, history5, evaluation5, time5 = create_and_train_model(base_model5, 'model5_vgg16_class_weights', train_ds, val_ds, test_ds, epochs=epochs, class_weight=class_weight_dict)
  490. # model6, history6, evaluation6, time6 = create_and_train_model(base_model6, 'model6_mobilenetv2_class_weights', train_ds, val_ds, test_ds, epochs=epochs, class_weight=class_weight_dict)
  491. # %%
  492. from tensorflow.keras.applications import (
  493. InceptionV3, EfficientNetV2L, ResNet152V2,
  494. Xception, VGG16, MobileNetV2
  495. )
  496. # InceptionV3 (which you already have)
  497. base_model1 = InceptionV3(weights=None, include_top=False, input_shape=(224, 224, 3))
  498. base_model1.load_weights('/kaggle/input/inception_v3/tensorflow2/default/1/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5')
  499. # For EfficientNetV2L
  500. base_model2 = EfficientNetV2L(weights=None, include_top=False, input_shape=(224, 224, 3))
  501. base_model2.load_weights('/kaggle/input/efficientnet/tensorflow2/default/1/efficientnetv2-l_notop.h5')
  502. # For ResNet152V2
  503. base_model3 = ResNet152V2(weights=None, include_top=False, input_shape=(224, 224, 3))
  504. base_model3.load_weights('/kaggle/input/resnet/tensorflow2/default/1/resnet152v2_weights_tf_dim_ordering_tf_kernels_notop.h5')
  505. # For Xception
  506. base_model4 = Xception(weights=None, include_top=False, input_shape=(224, 224, 3))
  507. base_model4.load_weights('/kaggle/input/xception/tensorflow2/default/1/xception_weights_tf_dim_ordering_tf_kernels_notop.h5')
  508. # For VGG16
  509. base_model5 = VGG16(weights=None, include_top=False, input_shape=(224, 224, 3))
  510. base_model5.load_weights('/kaggle/input/vgg16/tensorflow2/default/1/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5')
  511. # For MobileNetV2
  512. base_model6 = MobileNetV2(weights=None, include_top=False, input_shape=(224, 224, 3))
  513. base_model6.load_weights('/kaggle/input/mobilenet/tensorflow2/default/1/mobilenet_v2_weights_tf_dim_ordering_tf_kernels_1.0_224_no_top.h5')
  514. # Now you can train your models
  515. # model1, history1, evaluation1, time1 = create_and_train_model(base_model1, 'model1_inceptionv3_class_weights', train_ds, val_ds, test_ds, epochs=epochs, class_weight=class_weight_dict)
  516. model2, history2, evaluation2, time2 = create_and_train_model(base_model2, 'model2_efficientnetv2l_class_weights', train_ds, val_ds, test_ds, epochs=epochs, class_weight=class_weight_dict)
  517. model3, history3, evaluation3, time3 = create_and_train_model(base_model3, 'model3_resnet152v2_class_weights', train_ds, val_ds, test_ds, epochs=epochs, class_weight=class_weight_dict)
  518. model4, history4, evaluation4, time4 = create_and_train_model(base_model4, 'model4_xception_class_weights', train_ds, val_ds, test_ds, epochs=epochs, class_weight=class_weight_dict)
  519. model5, history5, evaluation5, time5 = create_and_train_model(base_model5, 'model5_vgg16_class_weights', train_ds, val_ds, test_ds, epochs=epochs, class_weight=class_weight_dict)
  520. model6, history6, evaluation6, time6 = create_and_train_model(base_model6, 'model6_mobilenetv2_class_weights', train_ds, val_ds, test_ds, epochs=epochs, class_weight=class_weight_dict)
  521. # %%
  522. # # Define model names
  523. # model_names = [
  524. # "InceptionV3"
  525. # ]
  526. # # Store histories in a list
  527. # histories = [history1]
  528. # # Plot Training Accuracy
  529. # plt.figure(figsize=(12, 6))
  530. # for i, history in enumerate(histories):
  531. # plt.plot(history.history['accuracy'], label=f'{model_names[i]} Training')
  532. # plt.title('Training Accuracy over Epochs')
  533. # plt.xlabel('Epochs')
  534. # plt.ylabel('Accuracy')
  535. # plt.legend()
  536. # plt.grid()
  537. # plt.show()
  538. # # Plot Validation Accuracy
  539. # plt.figure(figsize=(12, 6))
  540. # for i, history in enumerate(histories):
  541. # plt.plot(history.history['val_accuracy'], label=f'{model_names[i]} Validation')
  542. # plt.title('Validation Accuracy over Epochs')
  543. # plt.xlabel('Epochs')
  544. # plt.ylabel('Accuracy')
  545. # plt.legend()
  546. # plt.grid()
  547. # plt.show()
  548. # # Plot Training Loss
  549. # plt.figure(figsize=(12, 6))
  550. # for i, history in enumerate(histories):
  551. # plt.plot(history.history['loss'], label=f'{model_names[i]} Training Loss')
  552. # plt.title('Training Loss over Epochs')
  553. # plt.xlabel('Epochs')
  554. # plt.ylabel('Loss')
  555. # plt.legend()
  556. # plt.grid()
  557. # plt.show()
  558. # # Plot Validation Loss
  559. # plt.figure(figsize=(12, 6))
  560. # for i, history in enumerate(histories):
  561. # plt.plot(history.history['val_loss'], label=f'{model_names[i]} Validation Loss')
  562. # plt.title('Validation Loss over Epochs')
  563. # plt.xlabel('Epochs')
  564. # plt.ylabel('Loss')
  565. # plt.legend()
  566. # plt.grid()
  567. # plt.show()
  568. # %%
  569. # Define model names
  570. model_names = [
  571. "InceptionV3", "EfficientNetV2L", "ResNet152V2",
  572. "Xception", "VGG16", "MobileNetV2"
  573. ]
  574. # Store histories in a list
  575. histories = [history1, history2, history3, history4, history5, history6]
  576. # Plot Training Accuracy
  577. plt.figure(figsize=(12, 6))
  578. for i, history in enumerate(histories):
  579. plt.plot(history.history['accuracy'], label=f'{model_names[i]} Training')
  580. plt.title('Training Accuracy over Epochs')
  581. plt.xlabel('Epochs')
  582. plt.ylabel('Accuracy')
  583. plt.legend()
  584. plt.grid()
  585. plt.show()
  586. # Plot Validation Accuracy
  587. plt.figure(figsize=(12, 6))
  588. for i, history in enumerate(histories):
  589. plt.plot(history.history['val_accuracy'], label=f'{model_names[i]} Validation')
  590. plt.title('Validation Accuracy over Epochs')
  591. plt.xlabel('Epochs')
  592. plt.ylabel('Accuracy')
  593. plt.legend()
  594. plt.grid()
  595. plt.show()
  596. # Plot Training Loss
  597. plt.figure(figsize=(12, 6))
  598. for i, history in enumerate(histories):
  599. plt.plot(history.history['loss'], label=f'{model_names[i]} Training Loss')
  600. plt.title('Training Loss over Epochs')
  601. plt.xlabel('Epochs')
  602. plt.ylabel('Loss')
  603. plt.legend()
  604. plt.grid()
  605. plt.show()
  606. # Plot Validation Loss
  607. plt.figure(figsize=(12, 6))
  608. for i, history in enumerate(histories):
  609. plt.plot(history.history['val_loss'], label=f'{model_names[i]} Validation Loss')
  610. plt.title('Validation Loss over Epochs')
  611. plt.xlabel('Epochs')
  612. plt.ylabel('Loss')
  613. plt.legend()
  614. plt.grid()
  615. plt.show()
  616. # %%
  617. # %%
  618. # %%
  619. # %%
  620. # After training models
  621. evaluate_model(model1, test_ds, 'model1_inceptionv3_class_weights')
  622. evaluate_model(model2, test_ds, 'model2_efficientnetv2l_class_weights')
  623. evaluate_model(model3, test_ds, 'model3_resnet152v2_class_weights')
  624. evaluate_model(model4, test_ds, 'model4_xception_class_weights')
  625. evaluate_model(model5, test_ds, 'model5_vgg16_class_weights')
  626. evaluate_model(model6, test_ds, 'model6_mobilenetv2_class_weights')
  627. # %% [markdown]
  628. # # Load models
  629. # %%
  630. from tensorflow.keras.models import load_model
  631. import os
  632. base_path = "/kaggle/input/custom_models/tensorflow2/default/1"
  633. print("Files in directory:")
  634. print(os.listdir(base_path))
  635. # %%
  636. model1 = load_model('/kaggle/input/custom_models/tensorflow2/default/1/model1_inceptionv3_class_weights_best.keras')
  637. model3 = load_model('/kaggle/input/custom_models/tensorflow2/default/1/model3_resnet152v2_class_weights.keras')
  638. model4 = load_model('/kaggle/input/custom_models/tensorflow2/default/1/model4_xception_class_weights.keras')
  639. model5 = load_model('/kaggle/input/custom_models/tensorflow2/default/1/model5_vgg16_class_weights_best.keras')
  640. model6 = load_model('/kaggle/input/custom_models/tensorflow2/default/1/model6_mobilenetv2_class_weights_best.keras')
  641. model7 = load_model('/kaggle/input/custom_cnn_updated/tensorflow2/default/1/custom_cnn_model_best.keras')
  642. # model2 = load_model('/kaggle/input/custom_models/tensorflow2/default/1/model2_efficientnetv2l_class_weights_best.keras')
  643. # %%
  644. # Define ensembles
  645. # ensemble1 = [model2, model4, model3]
  646. # ensemble2 = [model1, model2, model4]
  647. # ensemble3 = [model2, model3, model6]
  648. ensemble1 = [model7, model4, model3]
  649. ensemble2 = [model1, model7, model4]
  650. ensemble3 = [model7, model3, model6]
  651. # %%
  652. def ensemble_predict(models, test_ds):
  653. all_predictions = []
  654. y_true = []
  655. for images, labels in test_ds:
  656. y_true.extend(labels.numpy())
  657. preds = [model.predict(images, verbose=0) for model in models]
  658. all_predictions.append(np.mean(preds, axis=0))
  659. avg_predictions = np.vstack(all_predictions)
  660. final_predictions = np.argmax(avg_predictions, axis=1)
  661. return np.array(y_true), final_predictions, avg_predictions
  662. # %%
  663. # Function to evaluate ensemble and save results
  664. def evaluate_and_save_ensemble(models, test_ds, model_name):
  665. y_true, y_pred, avg_probs = ensemble_predict(models, test_ds)
  666. # Calculate metrics
  667. accuracy = accuracy_score(y_true, y_pred)
  668. precision = precision_score(y_true, y_pred, average='macro')
  669. recall = recall_score(y_true, y_pred, average='macro')
  670. f1 = f1_score(y_true, y_pred, average='macro')
  671. # Confusion Matrix
  672. cm = confusion_matrix(y_true, y_pred)
  673. sensitivity = np.mean(np.diag(cm) / np.sum(cm, axis=1))
  674. specificity = np.mean(np.diag(cm) / np.sum(cm, axis=0))
  675. # Additional metrics
  676. mae = mean_absolute_error(y_true, y_pred)
  677. rmse = np.sqrt(np.mean((y_true - y_pred) ** 2))
  678. # Print evaluation metrics
  679. print(f"\n=== Model Evaluation Metrics for {model_name} ===")
  680. print(f"Accuracy: {accuracy:.4f}")
  681. print(f"Precision: {precision:.4f}")
  682. print(f"Recall: {recall:.4f}")
  683. print(f"F1 Score: {f1:.4f}")
  684. print(f"Sensitivity: {sensitivity:.4f}")
  685. print(f"Specificity: {specificity:.4f}")
  686. print(f"MAE: {mae:.4f}")
  687. print(f"RMSE: {rmse:.4f}")
  688. # Save results
  689. with open(f'{model_name}_results.pkl', 'wb') as f:
  690. pickle.dump({'y_true': y_true, 'y_pred': y_pred, 'avg_probs': avg_probs}, f)
  691. print(f"Ensemble '{model_name}' results saved successfully!")
  692. # Plot confusion matrix
  693. plt.figure(figsize=(6, 6))
  694. sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=range(4), yticklabels=range(4))
  695. plt.xlabel('Predicted Label')
  696. plt.ylabel('True Label')
  697. plt.title(f'Confusion Matrix - {model_name}')
  698. plt.show()
  699. # %%
  700. # Run evaluation for all ensembles
  701. evaluate_and_save_ensemble(ensemble1, test_ds, "ensemble1")
  702. evaluate_and_save_ensemble(ensemble2, test_ds, "ensemble2")
  703. evaluate_and_save_ensemble(ensemble3, test_ds, "ensemble3")
  704. # %%
  705. ensembles = ["Ensemble 1", "Ensemble 2", "Ensemble 3"]
  706. accuracy = [0.9947, 0.9924, 0.9908]
  707. precision = [0.9945, 0.9920, 0.9904]
  708. recall = [0.9946, 0.9921, 0.9905]
  709. f1_score = [0.9945, 0.9921, 0.9904]
  710. sensitivity = [0.9946, 0.9921, 0.9905]
  711. specificity = [0.9945, 0.9920, 0.9904]
  712. mae = [0.0076, 0.0137, 0.0130]
  713. rmse = [0.1172, 0.1747, 0.1487]
  714. colors = ["#203f85", "#1eb4cb", "#fdf6de", "#f03c29", "#fbd022"]
  715. plt.figure(figsize=(8, 5))
  716. plt.bar(ensembles, accuracy, color=colors[1])
  717. plt.xlabel("Ensemble Models")
  718. plt.ylabel("Accuracy")
  719. plt.title("Accuracy Comparison of Ensemble Models")
  720. plt.ylim(0.98, 1.0)
  721. for i, v in enumerate(accuracy):
  722. plt.text(i, v, f"{v:.4f}", ha='center', va='bottom', fontsize=12, color='black')
  723. plt.show()
  724. metrics = [precision, recall, f1_score]
  725. labels = ["Precision", "Recall", "F1 Score"]
  726. metric_colors = [colors[0], colors[3], colors[4]]
  727. plt.figure(figsize=(8, 5))
  728. bar_width = 0.25
  729. x = np.arange(len(ensembles))
  730. for i, metric in enumerate(metrics):
  731. plt.bar(x + i * bar_width, metric, width=bar_width, label=labels[i], color=metric_colors[i])
  732. plt.xlabel("Ensemble Models")
  733. plt.ylabel("Score")
  734. plt.title("Precision, Recall, and F1 Score Comparison")
  735. plt.xticks(x + bar_width, ensembles)
  736. plt.legend()
  737. plt.ylim(0.98, 1.0)
  738. plt.show()
  739. plt.figure(figsize=(8, 5))
  740. bar_width = 0.25
  741. x = np.arange(len(ensembles))
  742. plt.bar(x, mae, width=bar_width, label="MAE", color=colors[3])
  743. plt.bar(x + bar_width, rmse, width=bar_width, label="RMSE", color=colors[1])
  744. plt.xlabel("Ensemble Models")
  745. plt.ylabel("Error")
  746. plt.title("MAE and RMSE Comparison")
  747. plt.xticks(x + bar_width / 2, ensembles)
  748. plt.legend()
  749. plt.show()
  750. # %%
  751. ensembles = ["Ensemble 1", "Ensemble 2", "Ensemble 3"]
  752. accuracy = [0.9947, 0.9924, 0.9908]
  753. precision = [0.9945, 0.9920, 0.9904]
  754. recall = [0.9946, 0.9921, 0.9905]
  755. f1_score = [0.9945, 0.9921, 0.9904]
  756. sensitivity = [0.9946, 0.9921, 0.9905]
  757. specificity = [0.9945, 0.9920, 0.9904]
  758. mae = [0.0076, 0.0137, 0.0130]
  759. rmse = [0.1172, 0.1747, 0.1487]
  760. colors = ["#203f85", "#1eb4cb", "#fdf6de", "#f03c29", "#fbd022"]
  761. plt.figure(figsize=(8, 5))
  762. plt.bar(ensembles, accuracy, color=colors[1])
  763. plt.xlabel("Ensemble Models")
  764. plt.ylabel("Accuracy")
  765. plt.title("Accuracy Comparison of Ensemble Models")
  766. plt.ylim(0.98, 1.0)
  767. for i, v in enumerate(accuracy):
  768. plt.text(i, v, f"{v:.4f}", ha='center', va='bottom', fontsize=12, color='black')
  769. plt.show()
  770. metrics = [precision, recall, f1_score]
  771. labels = ["Precision", "Recall", "F1 Score"]
  772. metric_colors = [colors[0], colors[3], colors[4]]
  773. plt.figure(figsize=(8, 5))
  774. bar_width = 0.25
  775. x = np.arange(len(ensembles))
  776. for i, metric in enumerate(metrics):
  777. plt.bar(x + i * bar_width, metric, width=bar_width, label=labels[i], color=metric_colors[i])
  778. plt.xlabel("Ensemble Models")
  779. plt.ylabel("Score")
  780. plt.title("Precision, Recall, and F1 Score Comparison")
  781. plt.xticks(x + bar_width, ensembles)
  782. plt.legend()
  783. plt.ylim(0.98, 1.0)
  784. plt.show()
  785. plt.figure(figsize=(8, 5))
  786. bar_width = 0.25
  787. x = np.arange(len(ensembles))
  788. plt.bar(x, mae, width=bar_width, label="MAE", color=colors[3])
  789. plt.bar(x + bar_width, rmse, width=bar_width, label="RMSE", color=colors[1])
  790. plt.xlabel("Ensemble Models")
  791. plt.ylabel("Error")
  792. plt.title("MAE and RMSE Comparison")
  793. plt.xticks(x + bar_width / 2, ensembles)
  794. plt.legend()
  795. plt.show()
  796. # %%
  797. !zip -r /kaggle/working/all_outputs.zip /kaggle/working/
  798. # %%
  799. ensembles = ["Ensemble 1", "Ensemble 2", "Ensemble 3"]
  800. accuracy = [0.9947, 0.9924, 0.9908]
  801. precision = [0.9945, 0.9920, 0.9904]
  802. recall = [0.9946, 0.9921, 0.9905]
  803. f1_score = [0.9945, 0.9921, 0.9904]
  804. sensitivity = [0.9946, 0.9921, 0.9905]
  805. specificity = [0.9945, 0.9920, 0.9904]
  806. mae = [0.0076, 0.0137, 0.0130]
  807. rmse = [0.1172, 0.1747, 0.1487]
  808. colors = ["#203f85", "#1eb4cb", "#fdf6de", "#f03c29", "#fbd022"]
  809. plt.figure(figsize=(8, 5))
  810. plt.bar(ensembles, accuracy, color=colors[1])
  811. plt.xlabel("Ensemble Models")
  812. plt.ylabel("Accuracy")
  813. plt.title("Accuracy Comparison of Ensemble Models")
  814. plt.ylim(0.98, 1.0)
  815. for i, v in enumerate(accuracy):
  816. plt.text(i, v, f"{v:.4f}", ha='center', va='bottom', fontsize=12, color='black')
  817. plt.show()
  818. metrics = [precision, recall, f1_score]
  819. labels = ["Precision", "Recall", "F1 Score"]
  820. metric_colors = [colors[0], colors[3], colors[4]]
  821. plt.figure(figsize=(8, 5))
  822. bar_width = 0.25
  823. x = np.arange(len(ensembles))
  824. for i, metric in enumerate(metrics):
  825. plt.bar(x + i * bar_width, metric, width=bar_width, label=labels[i], color=metric_colors[i])
  826. plt.xlabel("Ensemble Models")
  827. plt.ylabel("Score")
  828. plt.title("Precision, Recall, and F1 Score Comparison")
  829. plt.xticks(x + bar_width, ensembles)
  830. plt.legend()
  831. plt.ylim(0.98, 1.0)
  832. plt.show()
  833. plt.figure(figsize=(8, 5))
  834. bar_width = 0.25
  835. x = np.arange(len(ensembles))
  836. plt.bar(x, mae, width=bar_width, label="MAE", color=colors[3])
  837. plt.bar(x + bar_width, rmse, width=bar_width, label="RMSE", color=colors[1])
  838. plt.xlabel("Ensemble Models")
  839. plt.ylabel("Error")
  840. plt.title("MAE and RMSE Comparison")
  841. plt.xticks(x + bar_width / 2, ensembles)
  842. plt.legend()
  843. plt.show()
  844. # %%
  845. # %%
  846. # %%
  847. # %%
  848. # %%
  849. # %%

pretrained_ensemble.ipynb.ipynb at commit 78bfc24, no license · at the source

Overview

Authors: Maisam Abbas1, Muhammad Hassan1, Ran-Zan Wang1, Chin-Hung Teng2
  1. Department of Computer Science and Engineering, Yuan Ze University, Yuandong Rd. Zhongli District, Taoyuan 32003, Taiwan; (M.A.); (M.H.)
  2. Department of Information Communication, Yuan Ze University, Yuandong Rd. Zhongli District, Taoyuan 32003, Taiwan
Institutions: Yuan Ze University (Taiwan)
Journal: Journal of imaging, volume 12, issue 6, article 233
Dates: received 23 March 2026; accepted 24 May 2026; published online 28 May 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.3390/jimaging12060233 · PMID 42346896 · PMCID PMC13301762 · OpenAlex W7162665632
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: structural MRI / diffusion (modality), other condition (population)
Methods: Statistics, Machine learning
Keywords: brain tumor classification, Magnetic Resonance Imaging (MRI), convolutional neural network, transfer learning, pre-trained models
Topic: Brain Tumor Detection and Classification (Neurology, Neuroscience), according to OpenAlex
Citations: not cited yet (Europe PMC); 68 references in the paper

Abstract

Early and accurate brain tumor detection is vital for effective treatment. We propose a deep learning framework for MRI-based brain tumor classification, featuring a novel Custom CNN evaluated independently alongside six pre-trained models for comparative analysis (InceptionV3, EfficientNetV2L, ResNet152V2, Xception, VGG16, and MobileNetV2). Additionally, three separate ensemble models are constructed to analyze whether model combination improves performance. Experiments conducted on the Kaggle-Multiclass brain MRI dataset show that the proposed Custom CNN achieves the best performance, with an accuracy of 99.54%, and features a task-specific architecture (0.57M parameters) that achieves superior performance through domain-specific feature learning and computational efficiency, thus outperforming both individual pre-trained models and ensemble approaches. Among pre-trained models, EfficientNetV2L (99.47%) and InceptionV3 (99.39%) show competitive results, while the best ensemble model achieves 99.47% accuracy, indicating clinical deployment potential pending external validation. These results demonstrate that the proposed Custom CNN provides superior performance without requiring ensemble complexity, thus highlighting its effectiveness and efficiency for automated brain tumor classification.

Reproduced under the paper's license (CC BY), from the paper cited above.

Repository

Its files are read in the Code ↔ Paper reader above, with 8 matches between paragraphs and lines of code.

Maisamilens/brain-tumor-classification

License: none: the authors keep all their rights
State: the link answers, verified on 28 September 2026
Evidence: files inventoried
Commit: 78bfc245eb09943c3788e28d95b4002705faf88b, 23 July 2026
Languages: Jupyter (2)
Size: 5 files, 2 scripts
Software Heritage: not archived
Found in: “Data Availability Statement”
Holds: README, 2 notebooks
Not found: license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: Keras (1 file), Matplotlib (1 file), NumPy (1 file), pandas (1 file), scikit-learn (1 file), seaborn (1 file), TensorFlow (1 file)
Availability: 1 check, the latest on 28 September 2026: the link answers
  • 28 September 2026: the link answers
3 files

The paper's code and data availability statement is in the Data section.

Tracing map

Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.

What the map holds:

  • 1 repository of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 2 scripts, each with its path and the digest of its content;
  • 8 matches between paragraphs of the paper and lines of the code (method lexical-v1);
  • neither the text of the paper nor the code itself.

Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.

Data

Datasets cited

Data Availability Statement

The datasets analyzed and utilized in this study are publicly available. The brain tumor MRI dataset by Jun Cheng can be accessed via Figshare [51]. Additional datasets used include the Brain Tumor Classification (MRI) dataset by Sartaj Bhuvaji [52], the Br35H Brain Tumor Detection dataset by Ahmed Hamada [53], and the Kaggle multiclass Brain Tumor MRI dataset by Masoud Nickparvar [54]. The source code for this work is publicly available at: https://github.com/Maisamilens/brain-tumor-classification (accessed on 23 May 2026).

Reproduced under the paper's license (CC BY), from the paper cited above.

Versions

The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.

Version 1, 28 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 4 authors, 5 keywords, 53 references.

Cite

This paper

Abbas, M., Hassan, M., Wang, R.-Z., & Teng, C.-H. (2026). Brain Tumor Classification in MRI Images Using Combined Transfer Learning and Convolutional Neural Networks. Journal of imaging, 12(6), 233. https://doi.org/10.3390/jimaging12060233

BibTeX

@article{abbas2026brain,
author = {Abbas, Maisam and Hassan, Muhammad and Wang, Ran-Zan and Teng, Chin-Hung},
title = {{Brain Tumor Classification in MRI Images Using Combined Transfer Learning and Convolutional Neural Networks}},
journal = {Journal of imaging},
year = {2026},
month = may,
volume = {12},
number = {6},
pages = {233},
publisher = {Multidisciplinary Digital Publishing Institute (MDPI)},
issn = {2313-433X},
doi = {10.3390/jimaging12060233},
url = {https://doi.org/10.3390/jimaging12060233},
pmid = {42346896},
pmcid = {PMC13301762}
}

RIS

TY - JOUR
AU - Abbas, Maisam
AU - Hassan, Muhammad
AU - Wang, Ran-Zan
AU - Teng, Chin-Hung
TI - Brain Tumor Classification in MRI Images Using Combined Transfer Learning and Convolutional Neural Networks
T2 - Journal of imaging
J2 - J Imaging
PY - 2026
DA - 2026/05/28
VL - 12
IS - 6
SP - 233
SN - 2313-433X
PB - Multidisciplinary Digital Publishing Institute (MDPI)
DO - 10.3390/jimaging12060233
UR - https://doi.org/10.3390/jimaging12060233
LA - en
ER -

CSL-JSON

{
"id": "10.3390/jimaging12060233",
"type": "article-journal",
"title": "Brain Tumor Classification in MRI Images Using Combined Transfer Learning and Convolutional Neural Networks",
"container-title": "Journal of imaging",
"author": [
{
"family": "Abbas",
"given": "Maisam"
},
{
"family": "Hassan",
"given": "Muhammad"
},
{
"family": "Wang",
"given": "Ran-Zan"
},
{
"family": "Teng",
"given": "Chin-Hung"
}
],
"container-title-short": "J Imaging",
"volume": "12",
"issue": "6",
"page": "233",
"DOI": "10.3390/jimaging12060233",
"PMID": "42346896",
"PMCID": "PMC13301762",
"ISSN": "2313-433X",
"publisher": "Multidisciplinary Digital Publishing Institute (MDPI)",
"URL": "https://doi.org/10.3390/jimaging12060233",
"language": "en",
"issued": {
"date-parts": [
[
2026,
5,
28
]
]
}
}

The tracing map gets a citation of its own once an author has validated it and it has a DOI.

Similar papers

The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.

[1] doi:10.1186/s40708-026-00325-x
CAE-BrainNet: a statistically validated class-adaptive attention ensemble model for explainable brain tumor classification from MRI.
Journal: Brain informatics
In common: kaggle.com/datasets/ahmedhamada0, kaggle.com/datasets/sartajbhuvaji, 2 other datasets, structural MRI / diffusion, other condition, 3 references
[2] doi:10.1038/s41598-026-45675-y [code]
Multi-class classification of brain tumor using a ResNet101 backbone integrated with multi-scale deformable attention module and advanced data augmentations.
Journal: Scientific reports
In common: seaborn, scikit-learn, pandas, 2 other tools, structural MRI / diffusion, other condition, 6 references
[3] doi:10.3390/diagnostics16111745
Brain Tumor Classification and Segmentation in MR Images Using EfficientNet and U-Net++ Models.
Journal: Diagnostics (Basel, Switzerland)
In common: kaggle.com/datasets/sartajbhuvaji, figshare 1512427, 1 other dataset, structural MRI / diffusion, other condition, 1 reference
[4] doi:10.3390/brainsci16050468
Advancing Brain Tumor Diagnosis Using Deep Learning: A Systematic and Critical Review on Methodological Approaches to Glioma Segmentation and Classification Through Multiparametric MRI.
Journal: Brain sciences
In common: kaggle.com/datasets/sartajbhuvaji, figshare 1512427, 1 other dataset, structural MRI / diffusion, other condition, 1 reference
[5] doi:10.3389/frai.2026.1849051
Query-guided learning for efficient and interpretable multi-class brain tumor classification in MRI.
Journal: Frontiers in artificial intelligence
In common: kaggle.com/datasets/ahmedhamada0, kaggle.com/datasets/masoudnickparvar, structural MRI / diffusion, other condition, 3 references
[6] doi:10.1371/journal.pone.0346821
LHW-Net: An ensemble-based machine learning framework for brain tumor classification.
Journal: PloS one
In common: kaggle.com/datasets/ahmedhamada0, figshare 1512427, 1 other dataset, other condition, 1 reference
[7] doi:10.1038/s41598-026-46803-4 [code]
BrainGraphNet-ViT model: a hybrid model combining vision transformers and graph convolutional networks for brain tumor diagnosis.
Journal: Scientific reports
In common: kaggle.com/datasets/ahmedhamada0, kaggle.com/datasets/sartajbhuvaji, 1 other dataset, structural MRI / diffusion, other condition
[8] doi:10.1038/s41598-026-51236-0
A minimal-net CNN model for an IoT-based brain tumor detection and monitoring system.
Journal: Scientific reports
In common: kaggle.com/datasets/sartajbhuvaji, kaggle.com/datasets/masoudnickparvar, structural MRI / diffusion, other condition, 2 references
[9] doi:10.1038/s41598-026-52615-3
MANet: a multimodal attention convolutional neural network for brain tumor classification.
Journal: Scientific reports
In common: figshare 1512427, kaggle.com/datasets/masoudnickparvar, structural MRI / diffusion, other condition, 2 references
[10] doi:
NeuroTrustNet: a cost-effective multimodal ensemble framework for brain tumor classification under cross-dataset variability
Journal: Frontiers in artificial intelligence
In common: kaggle.com/datasets/sartajbhuvaji, kaggle.com/datasets/masoudnickparvar, other condition, 2 references

Contribute

The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.

Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.

Request its removal

To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).

Discussion, reproductions, activity

Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.

Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.

Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.