Computer vision techniques have shown tremendous results in some areas in the medical domain like surgery and therapy of different diseases. Even researchers are trying to experiment with the detection of different diseases like cancer in the lungs and kidneys. Different medical imaging datasets are publicly available today for researchers like Cancer Imaging Archive where we can get data access of large databases free of cost. A brain tumor is one of the problems wherein the brain of a patient’s different abnormal cells develops. They are called tumors that can again be divided into different types.
Through this article, we will build a classification model that would take MRI images of the patient and compute if there is a tumor in the brain or not. We will be using Brain MRI Images for Brain Tumor Detection that is publicly available on Kaggle. We will first build the model using simple custom layers convolutional neural networks and then evaluate it. At last, we will compute some prediction by the model and compare the results.
The Dataset
The data set consists of two different folders that are Yes or No. Both the folders contain different MRI images of the patients. Yes folder has patients that have brain tumors whereas No folder has MRI images of patients with no brain tumor. There are a total of 155 images of positive patients of brain tumor and 98 images of other patients having no brain tumor. All the images are of 240X240 pixels.
Brain Tumor Classification Model
First, we need to enable the GPU. To do so go to ‘Runtime’ in Google Colab and then click on ‘Change runtime type’ and select GPU. Once the runtime is changed we will move forward importing the required libraries and dataset. We will be directly importing the data set from kaggle. Use the below code to do the same.
import tensorflow as tf from zipfile import ZipFile import os,glob import cv2 from tqdm._tqdm_notebook import tqdm_notebook as tqdm import numpy as np from sklearn import preprocessing from sklearn.model_selection import train_test_split from keras.models import Sequential from keras.layers import Convolution2D, Dropout, Dense,MaxPooling2D from keras.layers import BatchNormalization from keras.layers import MaxPooling2D from keras.layers import Flatten
Downloading Dataset From Kaggle
We first need to install the dependencies. As we will import data directly from Kaggle we need to install the package that supports that. So we have installed the Kaggle package using pip.
!pip install kaggle
Now we will import data from Kaggle. To do so we need to first add a kaggle.json file which you will get by creating a new API token on Kaggle. Go to my account in Kaggle and scroll down and you will see an option for creating a new API. Once you click on that a file ‘kaggle.json’ will be downloaded. Once you have that file upload it and change the permissions using the code shown below.
from google.colab import files files.upload() !mkdir -p ~/.kaggle !cp kaggle.json ~/.kaggle/ !chmod 600 ~/.kaggle/kaggle.json kaggle datasets download -d navoneel/brain-mri-images-for-brain-tumor-detection
Once we run the above command the zip file of the data would be downloaded. We now need to unzip the file using the below code.
from zipfile import ZipFile file_name = "/content/brain-mri-images-for-brain-tumor-detection.zip" with ZipFile(file_name,'r') as zip: zip.extractall() print('Done')
Now we will read the images and store it in a separate list. Use the below code to the same.
os.chdir('/content/yes') X = [] y = [] for i in tqdm(os.listdir()): img = cv2.imread(i) img = cv2.resize(img,(28,28)) X.append(img) y.append((i[0:1])) os.chdir('/content/no') for i in tqdm(os.listdir()): img = cv2.imread(i) img = cv2.resize(img,(28,28)) X.append(img) for i in range(1,99): y.append('N')
We have stored all the images in X and all the corresponding labels into y. Let us see some of the images that we just read. Use the below code to the same.
%matplotlib inline import matplotlib.pyplot as plt plt.figure(figsize=(10, 10)) for i in range(4): plt.subplot(1, 4, i+1) plt.imshow(X[i], cmap="gray") plt.axis('off') plt.show()
Output:
The images are distorted because we have resized them into 28X28 pixels. We will not split the data into training and testing data. Use the below code to do the same.
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42) print ("Shape of an image in X_train: ", X_train[0].shape) print ("Shape of an image in X_test: ", X_test[0].shape)
Output:
We have split the data into training and testing sets. We will now convert the labels into categorical using Keras. utils and also transform them into NumPy arrays. Use the below code to do so.
le = preprocessing.LabelEncoder() y_train = le.fit_transform(y_train) y_test = le.fit_transform(y_test) y_train = tf.keras.utils.to_categorical(y_train, num_classes=2) y_test = tf.keras.utils.to_categorical(y_test, num_classes=2) y_train = np.array(y_train) X_train = np.array(X_train) y_test = np.array(y_test) X_test = np.array(X_test)
We have transformed and now we will check the shape of the training and testing sets. Use the below to code to do the same.
print("X_train Shape: ", X_train.shape) print("X_test Shape: ", X_test.shape) print("y_train Shape: ", y_train.shape) print("y_test Shape: ", y_test.shape)
Output:
We have 169 images of 28X28 pixels in the training and 84 images of the same pixels in the testing sets. Now we will build our network for classifying the MRI images. Use the below code to define the network by adding different convents and pooling layers.
m1=Sequential() m1.add(BatchNormalization(input_shape = (28,28,3))) m1.add(Convolution2D(32, (3,3), activation ='relu', input_shape = (28, 28, 3))) m1.add(MaxPooling2D(pool_size=2)) m1.add(Convolution2D(filters=64, kernel_size=4, padding='same', activation='relu')) m1.add(MaxPooling2D(pool_size=2)) m1.add(Convolution2D(filters=128, kernel_size=3, padding='same', activation='relu')) m1.add(MaxPooling2D(pool_size=2)) m1.add(Convolution2D(filters=128, kernel_size=2, padding='same', activation='relu')) m1.add(MaxPooling2D(pool_size=2)) m1.add(Dropout(0.25)) m1.add(Flatten()) m1.add(Dense(units=128,activation = 'relu')) m1.add(Dense(units = 64, activation = 'relu')) m1.add(Dense(units = 32, activation = 'relu')) m1.add(Dense(units = 2, activation = 'softmax'))
After defining the network we will now compile the network using optimizer as adam and loss function as categorical cross_entropy. We will be using metrics as accuracy to measure the performance. Use the below code to compile the model.
m1.compile(optimizer='adam', loss = 'categorical_crossentropy',metrics = ['accuracy'])
After compiling the model we will now train the model for 50 epochs and check the results on the validation dataset. Use the below code to do the same.
history = m1.fit(X_train,y_train, epochs=50, validation_data=(X_test,y_test), verbose = 1, initial_epoch=0)
After the training has completed for 50 epochs we will evaluate the performance of the model on validation data. Use the below code to compute the same.
m1.evaluate(X_test,y_test) plt.plot(history.history['val_accuracy']) plt.title('model accuracy') plt.ylabel('accuracy') plt.xlabel('epoch') plt.legend(['train', 'validation'], loc='upper left') plt.show()
Output:
We got 86% on the validation data with a loss of 0.592. Now let’s see the training and testing accuracy and loss with graphs. Use the below code to visualize the same.
plt.plot(history.history['accuracy'])
Output:
plt.plot(history.history['loss']) plt.plot(history.history['val_loss']) plt.title('model loss') plt.ylabel('loss') plt.xlabel('epoch') plt.legend(['train', 'validation'], loc='upper left') plt.show()
Output:
After this, we will check some predictions made by the model whether they were correct or not. Use the below code to compute some predictions on some of the MRI images.
y_predicted=m1.predict_classes(X_test) y_actual=np.argmax(y_test,axis=1) L = 2 W = 2 fig, axes = plt.subplots(L, W, figsize = (12,12)) axes = axes.ravel() for i in np.arange(0, L * W): axes[i].imshow(X_test[i]) axes[i].set_title(f"Prediction Class = {y_predicted[i]:0.1f}\n Actual Label = {y_actual[i]:0.1f}") axes[i].axis('off') plt.subplots_adjust(wspace=0.5)
Output:
The model computed 5 out of 6 predictions right and 1 image was misclassified by the model. We will now evaluate the model performance using a classification report. Check the below code to check the classification report of the model.
from sklearn.metrics import classification_report print(classification_report(y_true, y_pred))
Output:
Conclusion
In this article, we made a classification model with the help of custom CNN layers to classify whether the patient has a brain tumor or not through MRI images. With a few no of training samples, the model gave 86% accuracy. If we increase the training data may be by more MRI images of patients or perform data augmentation techniques we can achieve higher classification accuracy. Also, we can make use of pre-trained architectures like Vgg16 or Resnet 34 for improving the model performance.