Pneumonia X-Ray detection, Keras | Python
In this article, a simple convolutional neural network is demonstrated without any pre-trained network or any data augmentation. The aim of this article is to explain the basic concepts of the neural network using the example of Pneumonia X-Ray detection using a network from scratch using Keras TensorFlow API in Python language.
A study shows 15% of children under the age of 5 die every year due to pneumonia. Air pollution, crowded homes, or parental smoking are the major factors. Early detection will be a major benefit for the helpful treatment. Thus, we are proposing a simple yet robust network with a high true positive count. It can clearly be observed in the Confusion matrix in the coming sections.
Splitting of the article for the ease of understanding is as follows:
- Importing libraries
- Building the model
- Data Generation
- Compilation and training
- Confusion Matrix
- Prediction
Happy Readings!!!
LIBRARIES
Importing of necessary Python libraries required for the project
import numpy as np import pandas as pd import os print(os.listdir("../input")) import keras import h5py import matplotlib.pyplot as plt from keras.models import Sequential from keras.layers import Conv2D,MaxPool2D,Dense,Dropout,Softmax,Input,Flatten from keras.optimizers import Adam,RMSprop,SGD from keras.layers.merge import add from keras.layers import Dense, Activation, Flatten from keras.layers import Conv2D, MaxPooling2D, BatchNormalization from keras.layers import BatchNormalization from keras.callbacks import ModelCheckpoint, Callback, EarlyStopping from tensorflow import set_random_seed from sklearn.metrics import roc_auc_score,roc_curve,accuracy_score,recall_score from keras.metrics import categorical_accuracy %matplotlib inline from keras.preprocessing.image import ImageDataGenerator os.environ['PYTHONHASHSEED'] = "0" np.random.seed(1) set_random_seed(1)
['chest-xray-pneumonia', 'vgg16'] /opt/conda/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`. from ._conv import register_converters as _register_converters Using TensorFlow backend.
BUILDING MODEL
The building of the model using simple convolutional layers, max-pooling, flattening layer, dropout, dense, and batch normalization.
- Convolutional Layer: Capturing of low-level and high-level features from the image and understanding just the ways humans have when they visualize.
- Max-Pooling: Dropping off the parameters of the network thus reducing the size of the network.
- Flatten: Flattens the layer into a 1×1 vector for the output.
- Dropout: Used to avoid overfitting of the network by dropping off some layers from the built network
- Dense: Changes the dimension of the vectors which connect deeply to the neural network. Thus, applying operations like rotation, translation, and scaling.
- Batch Normalization: Standardization of the input to have computationally efficient and faster processing of the images.
model = Sequential() model.add(Conv2D(32, (3,3), strides=(1,1), padding='same', input_shape=(64,64,1), activation='relu')) model.add(Conv2D(32, (3,3), strides=(1,1), padding='same', activation='relu')) model.add(MaxPooling2D((2,2))) model.add(Conv2D(64, (3,3), strides=(1,1), padding='same', activation='relu')) model.add(BatchNormalization()) model.add(Conv2D(64, (3,3), strides=(1,1), padding='same', activation='relu')) model.add(MaxPooling2D((2,2))) model.add(Conv2D(128, (3,3), strides=(1,1), padding='same', activation='relu')) model.add(BatchNormalization()) model.add(Conv2D(128, (3,3), strides=(1,1), padding='same', activation='relu')) model.add(MaxPooling2D((2,2))) model.add(Flatten()) model.add(Dense(1024, activation='relu')) model.add(BatchNormalization()) model.add(Dropout(0.60)) model.add(Dense(512, activation='relu')) model.add(BatchNormalization()) model.add(Dropout(0.4)) model.add(Dense(2, activation='softmax'))
SUMMARY
Printing the summary of the network we built in the previous section using various types of layers mentioned and explained in detail.
model.summary()
_________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d_1 (Conv2D) (None, 64, 64, 32) 320 _________________________________________________________________ conv2d_2 (Conv2D) (None, 64, 64, 32) 9248 _________________________________________________________________ max_pooling2d_1 (MaxPooling2 (None, 32, 32, 32) 0 _________________________________________________________________ conv2d_3 (Conv2D) (None, 32, 32, 64) 18496 _________________________________________________________________ batch_normalization_1 (Batch (None, 32, 32, 64) 256 _________________________________________________________________ conv2d_4 (Conv2D) (None, 32, 32, 64) 36928 _________________________________________________________________ max_pooling2d_2 (MaxPooling2 (None, 16, 16, 64) 0 _________________________________________________________________ conv2d_5 (Conv2D) (None, 16, 16, 128) 73856 _________________________________________________________________ batch_normalization_2 (Batch (None, 16, 16, 128) 512 _________________________________________________________________ conv2d_6 (Conv2D) (None, 16, 16, 128) 147584 _________________________________________________________________ max_pooling2d_3 (MaxPooling2 (None, 8, 8, 128) 0 _________________________________________________________________ flatten_1 (Flatten) (None, 8192) 0 _________________________________________________________________ dense_1 (Dense) (None, 1024) 8389632 _________________________________________________________________ batch_normalization_3 (Batch (None, 1024) 4096 _________________________________________________________________ dropout_1 (Dropout) (None, 1024) 0 _________________________________________________________________ dense_2 (Dense) (None, 512) 524800 _________________________________________________________________ batch_normalization_4 (Batch (None, 512) 2048 _________________________________________________________________ dropout_2 (Dropout) (None, 512) 0 _________________________________________________________________ dense_3 (Dense) (None, 2) 1026 ================================================================= Total params: 9,208,802 Trainable params: 9,205,346 Non-trainable params: 3,456 _________________________________________________________________
DATA GENERATION
Data generation and normalizing(size and channel) of the images. Also, declaring appropriate batch size and folder directories of the dataset for the training of the model.
gen = ImageDataGenerator() train_batches = gen.flow_from_directory("../input/chest-xray-pneumonia/chest_xray/chest_xray/train",model.input_shape[1:3],color_mode="grayscale",shuffle=True,seed=1, batch_size=16) valid_batches = gen.flow_from_directory("../input/chest-xray-pneumonia/chest_xray/chest_xray/val", model.input_shape[1:3],color_mode="grayscale", shuffle=True,seed=1, batch_size=16) test_batches = gen.flow_from_directory("../input/chest-xray-pneumonia/chest_xray/chest_xray/test", model.input_shape[1:3], shuffle=False, color_mode="grayscale", batch_size=8)
Found 5216 images belonging to 2 classes. Found 16 images belonging to 2 classes. Found 624 images belonging to 2 classes.
CALL BACK
Declaring of the Callback functions. Terminates the training of the model. At the end of each epoch, the fit will check the callback functions. Also, the callback functions used here are:
- EarlyStopping: When the ‘val_loss’ stops improving, the training will be stopped.
- ModelCheckpoint: The weights and model are saved in intervals so that even if training is halted in some unexpected cases, we can load the saved model and continue training.
es = EarlyStopping(monitor='val_loss',patience=5) chkpt = ModelCheckpoint(filepath='best_model_todate', save_best_only=True, save_weights_only=True)
TRAINING
Compilation and training of the network. The compilation is done using ADAM optimizer and categorical cross-entropy loss function. 50 epochs are used to train the network but terminated at the end of the 13th epochs by the callback function.
model.compile(Adam(lr=0.0001, decay=1e-5),loss="categorical_crossentropy", metrics=["accuracy"]) model.fit_generator(train_batches,validation_data=valid_batches,epochs=50, steps_per_epoch=16, validation_steps=16)
CONFUSION MATRIX
The confusion matrix tests the images from the dataset. Then, the prediction of the image with respect to the labels. Prediction of 521 images (380 pneumonia and 141 not pneumonia) accurately and the recognition of 103 false positives (93 no pneumonia and 10 pneumonia).
from sklearn.metrics import confusion_matrix CM = confusion_matrix(pre["label"], pre["pre"]) from mlxtend.plotting import plot_confusion_matrix fig, ax = plot_confusion_matrix(conf_mat=CM , figsize=(5, 5)) plt.show()
PREDICTION
Estimation of the prediction rate and recall drawn from the confusion matrix for understanding the accuracy of the model.
tn, fp, fn, tp = CM.ravel() precision = tp/(tp+fp) recall = tp/(tp+fn) print("Recall of the model is {:.2f}".format(recall)) print("Precision of the model is {:.2f}".format(precision))
Recall of the model is 0.97 Precision of the model is 0.80
FINAL THOUGHTS
In this article, we discussed the basic deep learning framework without transfer learning or augmentation is done resulting in a prediction accuracy of 80% with just 13 epochs. The building, compiling, and training of the network. Then, explaining all these layers along with the callback functions used in this article in detail for increasing the scope of understanding of the readers. Thus, the flow is as follows: first, the importing of the dependencies for the project. Then building the model and followed by compilation and training of the model. Then, evaluation of the model to get the accuracy of the model.
The source code for the pneumonia x-ray can be found and downloaded from here.
To learn transfer learning approaches, you can refer to my blogs:
[1]. Image classification of Bird species (Used UNets fused with a Residual net)
[2]. Salt Identification (Used a VGG16 net)
To learn from my other machine learning blogs, refer here.
REFERENCES:
[1]. A Novel Transfer Learning-Based Approach for Pneumonia Detection in Chest X-ray Images (Used Transfer Learning)
[2]. Predict pneumonia with chest X-ray images based on convolutional deep neural learning networks
Thank you. Hope this article was helpful for all!
Leave a Reply