Recognition (3 diseases) from X-ray (Machine Learning tutorial) with accuracy: 96%. Using TensorFlow

Alex G.
4 min readDec 8, 2020
image classification (Photo,GIF by Author) https://github.com/oleksandr-g-rock/disease-recognition-from-xray/blob/main/1_P_Z8rbx_QPtO0rrfSKWXPQ.jpeg

Short summary:

In this article, we will recognize 3 types of X-rays: Normal, Pneumonia, Tuberculosis.

With a score:
loss: 0.1144 / accuracy: 0.9600
val_loss: 0.2944 / val_accuracy: 0.9000

You can make a few steps and run this code. Code for this article available here.

So Let’s start :)

In order to get started, we need data. I took the data for this task from here:

- Dataset with Pneumonia and Normal https://www.kaggle.com/paultimothymooney/chest-xray-pneumonia

Dataset with Tuberculosis and Normal
https://www.dropbox.com/s/f64cvlhm0gp80v5/tuberculosis.zip?dl=1 -O tuberculosis.zip or from https://www.kaggle.com/raddar/tuberculosis-chest-xrays-shenzhen

I downloaded these datasets and combined them into one folder to make them look like this:

(Photo,GIF by Author) https://github.com/oleksandr-g-rock/disease-recognition-from-xray/blob/main/1_-YTYbTrUwclf5UBQubB5ng.png

Then, I used the “Imagedatagenerator” to add the data only for training the neural model (not for validation) as there is not a lot of data.

train_datagen = ImageDataGenerator(rescale=1. / 255,
height_shift_range= 0.02,
width_shift_range=0.02,
rotation_range=0.02,
shear_range = 0.01,
fill_mode='nearest',
zoom_range=0.01)
train_generator = train_datagen.flow_from_directory(
train_dir,
target_size=(image_size, image_size),
batch_size=batch_size,
class_mode='categorical')
test_datagen = ImageDataGenerator(rescale=1. / 255)test_generator = test_datagen.flow_from_directory(
test_dir,
target_size=(image_size, image_size),
batch_size=batch_size,
class_mode='categorical')

After the data was prepared, I decided to use the pretrained model “Xception”. This model works very well with images and has very high scores when trained on new data. It is also the #1 in models that are available to public and the best rated

The first stage of training is “Transfer learning”. To do this, we download the model, “freeze” the weights from “Imagenet” (since this model was trained on the Imagenet dataset), add our layers to the existing model, and train. Besides, we save only the best results when we are training the model.

pretrained_model = tf.keras.applications.Xception(weights='imagenet', include_top=False) #download Xception model without last layerpretrained_model.trainable = False #"Frozen" all weights pretrained models#Created main layers for end Xception modelx = pretrained_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(512)(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)
x = Dropout(0.5)(x)
predictions = Dense(3, activation='softmax')(x)
model = Model(inputs=pretrained_model.input, outputs=predictions)
#compile & start train modelmodel.compile(loss='categorical_crossentropy',
optimizer='adam',
metrics=["accuracy"])
filepath="inceptionv3_best.h5"
checkpoint = ModelCheckpoint(filepath, monitor='val_loss', verbose=1,
save_best_only=True, mode='min')
learning_rate_reduction = ReduceLROnPlateau(monitor='val_loss',
patience=10,
verbose=1,
factor=0.5,
min_lr=0.00001)
callbacks_list = [checkpoint, learning_rate_reduction]
steps_per_epoch = 32
history = model.fit_generator(
train_generator,
steps_per_epoch=steps_per_epoch,
validation_data=test_generator,
validation_steps=5,
callbacks=callbacks_list,
epochs=50,
verbose=1)

After “Transfer Learning” we have good results::
loss: 0.1679 — accuracy: 0.9336 — val_loss: 0.3329 — val_accuracy: 0.8687

(Photo,GIF by Author) https://github.com/oleksandr-g-rock/disease-recognition-from-xray/blob/main/1_7b5UdUPJYsMWMUPObvRXqQ.png

However, we need better results. Therefore, we will do “Fine Tuning”. For this, we will load the best weights that were saved before from “Tranfer learning”, “unfreeze” several layers, and train them on our data.

model.load_weights("inceptionv3_best.h5") #upload best weights#Defrost the last 2 blockspretrained_model.trainable = False
for layer in model.layers[:290]:
layer.trainable = False
for layer in model.layers[290:]:
layer.trainable = True
#compile & start train modelmodel.compile(loss='categorical_crossentropy',
optimizer='adam',
metrics=["accuracy"])
filepath="inceptionv3_fine_tuned.h5"
checkpoint = ModelCheckpoint(filepath, monitor='val_accuracy', verbose=1, save_best_only=True, mode='max')
callbacks_list = [checkpoint, learning_rate_reduction]
steps_per_epoch = 32
history = model.fit_generator(
train_generator,
steps_per_epoch=steps_per_epoch,
validation_data=test_generator,
validation_steps=5,
callbacks=callbacks_list,
epochs=40,
verbose=2)

Let’s check our results after applying “Fine Tuning”.

loss: 0.1144 — accuracy: 0.9600 — val_loss: 0.2944 — val_accuracy: 0.9000

Awesome!

(Photo,GIF by Author) https://github.com/oleksandr-g-rock/disease-recognition-from-xray/blob/main/1_gbwOkLpz4XACSEeZoRehwA.png

Now let’s recognize Pneumonia on the new image that neural network has not seen before.

from tensorflow.keras.applications.inception_v3 import InceptionV3
from tensorflow.keras.preprocessing import image
from tensorflow.keras.models import Model, load_model
from tensorflow.keras.callbacks import ModelCheckpoint, ReduceLROnPlateau
from tensorflow.keras.layers import Dense, GlobalAveragePooling2D, Dropout
from tensorflow.keras.layers import BatchNormalization, Activation
from tensorflow.python.keras.optimizers import Adam, RMSprop
from tensorflow.python.keras.preprocessing.image import ImageDataGenerator
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
from numpy import loadtxt
import tensorflow.keras
from PIL import Image, ImageOps
%matplotlib inline
image_size = 256
batch_size = 32
model = tensorflow.keras.models.load_model('inceptionv3_best.h5')
img_path = '/content/chest_xray/test/PNEUMONIA/person100_bacteria_475.jpeg'
img = image.load_img(img_path, target_size=(image_size, image_size))
plt.imshow(img)
plt.show()
x = image.img_to_array(img)
x /= 255
x = np.expand_dims(x, axis=0)
prediction = model.predict(x)
prediction
classes = np.argmax(prediction, axis = 1)
print(classes)
(Photo,GIF by Author) https://github.com/oleksandr-g-rock/disease-recognition-from-xray/blob/main/1_KrEbTO5tQ0omL4-ZvX17ug.png

Result:

Here we are! Our model has just recognized Pneumonia.

I would like to remind you that the completed code is located here.

--

--

Alex G.

ML DevOps engineer. 🙂 I am always open to new opportunities and offers. 🖖 I trying to help the world 🌏 with machine learning.