Recognition (3 diseases) from X-ray (Machine Learning tutorial) with accuracy: 96%. Using TensorFlow
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:
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
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!
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 inlineimage_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)
Result:
Here we are! Our model has just recognized Pneumonia.
I would like to remind you that the completed code is located here.