Detect COVID-19 in X-rays with Keras, TensorFlow and Deep Learning


With the help of this guide, with the help of Keras, TensorFlow and deep learning, we will learn how to automatically determine COVID-19 from an x-ray data set manually

Like so many others, I am sincerely worried about COVID-19. I noticed that I’m constantly analyzing my condition and wondering if I will catch the disease and when it will happen. And the more I worry about it, the more it turns into a painful game of the mind, in which symptomatology is combined with hypochondria:

  • I woke up in the morning, feeling some soreness and weakness.
  • When I crawled out of bed, I found a runny nose (although it is already known that a runny nose is not a symptom of COVID-19).
  • By the time I got to the bathroom to get a paper scarf, I was already coughing.

At first I didn’t pay much attention to it - I’m allergic to pollen, and due to the warm weather on the east coast of the United States, this spring was an early spring. Most likely, these are allergic symptoms. But during the day my condition did not improve. I sit and write this manual with a thermometer in my mouth. I look down and see 37.4 ° C. My normal body temperature is slightly lower than others, at 36.3 ° C. Everything above 37.2 ° C is already a little heat for me.

Cough and slight fever? It could be COVID-19 ... or just my allergy. It is impossible to find out without testing, and it is precisely this “ignorance” that makes the situation so intimidating on a human level.

UFO Care Minute


COVID-19 — , SARS-CoV-2 (2019-nCoV). — , /, .



, .

, , .

: |

Despite my fears, I try to think rationally. I am a little over 30, I am in great shape, and my immunity is strong. I’ll put myself in quarantine (just in case), rest and deal with everything. COVID-19 doesn’t scare me from the point of view of personal health (at least I’ll stand it for myself).

So, I worry about my elderly relatives, including all those who have already been diagnosed with the disease, as well as those who are in nursing homes and hospitals. These people are vulnerable, and it will be terrible if they die due to COVID-19.

Instead of doing nothing and letting my ailment keep me at home (be it allergy, COVID-19 or my fears), I decided to do what I can:I’ll write the code, conduct experiments and, using practical examples, teach others how to use computer vision and deep learning .

I must say right away that this is not the most scientific article written by me. She is not scientific at all. The methods and datasets used are not worth publishing. But they serve as a starting point for those who want at least something to help.

I am worried about you and this community. I want to help what I can: this article is my way to mentally cope with difficult times, while helping others in a similar situation.

In this guide you will learn:

  1. How to collect opensource-dataset of X-ray images of patients with detected COVID-19.
  2. «» ( ) .
  3. COVID-19 .
  4. .

Note: I have already hinted at this, but now I will say directly. The techniques described here are for educational purposes only. This is not a rigorous scientific study; it will not be published in journals. This article is for readers who are interested in computer vision and deep learning, who want to learn in practice, as well as for those who are inspired by current events. I ask you to take all this into account.

In the first part of the manual, we will discuss how to detect COVID-19 in lung x-rays. Then we discuss the dataset itself. And then I will show how to train the model using Keras and TensorFlow to predict COVID-19 in our images.

Explanation


This COVID-19 auto-detection article is written for educational purposes only. It does not describe a reliable and accurate diagnostic system COVID-19, has not been tested neither from a professional nor from an academic point of view.

My goal is to inspire you and show how the study of computer vision and deep learning with the subsequent application of this knowledge in the medical field can have a big impact on the world.

Imagine: you do not need a medical education to influence medicine . Deep training practitioners today work closely with doctors and other doctors in solving complex problems, save lives and make the world a better place.

I hope my leadership inspires you to do so.

But considering all the above, researchers, magazine curators and the review system are already overloaded with works that describe COVID-19 forecasting models of dubious quality. Please do not send the code and model from this article to a journal or some scientific publication - you will only increase the chaos .

Moreover, if you want to conduct research on the basis of this article (or any other publication about COVID-19), then stick to the TRIPOD guide for describing predictive models.

As you understand, the use of artificial intelligence in the medical field can have very serious consequences. Publish and use such models only if you are a medical specialist or if you have been advised in detail by such specialists.

How can COVID-19 be detected in x-rays?



Figure 1: Example X-ray of a patient diagnosed with COVID-19. In these images, you can teach the classifier using Keras and TensorFlow to determine COVID-19.

Testing for COVID-19 is now difficult - there are not enough tests , but it is impossible to quickly produce them, which only increases panic. And in a panic, there are scoundrels who are trying to cash in on others and sell fake tests on COVID-19 , finding themselves unsuspecting victims in social networks and instant messengers.

Given the limited number of tests, we need to rely on other diagnostic methods.

I decided to study X-rays, because doctors often use them and CT scans to diagnose pneumonia, pulmonary inflammation, abscesses and enlarged lymph nodes. Since the virus attacks the epithelial cells that line the respiratory tract, we can use X-rays to study the condition of the human lungs. And since X-ray machines are almost everywhere, using the images you can detect COVID-19 without test kits.

The disadvantages of the method include the need for radiologists, as well as a significant processing time. And time is especially expensive when people are sick all over the world. And to save doctors time, you need to create an automatic analysis system .

Note: , , COVID-19 . . , , , , COVID-19, .

COVID-19



Figure 2: on the left are pictures of people with a positive result (infected), on the right - with a negative. In these images, we will teach the model using TensorFlow and Keras to automatically predict the presence of COVID-19 (that is, a disease resulting from coronavirus).

The dataset of patient images used with COVID-19 used here was compiled under the supervision of Dr. Joseph Cohen , a graduate student at the University of Montreal. A few days ago, Cohen began collecting X-ray images of patients with COVID-19 and uploading them to the GitHub repository. There you will find examples of not only this disease, but also MERS, SARS and ARDS.

To create a dataset I:

  1. Parse the metadata.csv file from the repository.
  2. Selected all the lines:

In total, 25 shots were obtained with positive results on COVID-19 ( Figure 2 , left ).

Now choose the pictures of healthy people.

To do this, I took a Kaggle's lung X-ray dataset (pneumonia) and selected 25 healthy people images ( Figure 2 , right ). This dataset has a number of drawbacks, including badly or incorrectly filled labels, but it is suitable as a starting point for testing the hypothesis of the COVID-19 detector.

As a result, I got 50 shots: 25 patients with COVID-19 and 25 healthy. You can download the dataset from the link. In addition, I added Python scripts with which I generated the dataset, but in this article I did not consider them.

Project structure


Download the code and data. Pull out the files from there, and you get the following directory structure:

$ tree --dirsfirst --filelimit 10
.
├── dataset
│   ├── covid [25 entries]
│   └── normal [25 entries]
├── build_covid_dataset.py
├── sample_kaggle_dataset.py
├── train_covid19.py
├── plot.png
└── covid19.model

Three directories, five files. The dataset lies in the dataset / directory and is divided into two classes - covid / and normal /. Below we look at the train_covid19.py script that trains our COVID-19 detector.

Training script implementation


Let's move on to fine-tuning the convolutional neural network, which will automatically diagnose COVID-19 using Keras, TensorFlow, and deep learning.

Open the train_covid19.py file and paste the following code:

# import the necessary packages
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.applications import VGG16
from tensorflow.keras.layers import AveragePooling2D
from tensorflow.keras.layers import Dropout
from tensorflow.keras.layers import Flatten
from tensorflow.keras.layers import Dense
from tensorflow.keras.layers import Input
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.utils import to_categorical
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from imutils import paths
import matplotlib.pyplot as plt
import numpy as np
import argparse
import cv2
import os

This script takes advantage of TensorFlow 2.0 and Keras libraries by selecting tensorflow.keras imports. Also we use:

  • scikit-learn , this is a de facto Python machine learning library,
  • matplotlib for charting,
  • OpenCV for uploading and preprocessing images in a dataset.

To learn how to install TensorFlow 2.0 (including scikit-learn, OpenCV and matplotlib), check out my tutorials for Ubuntu or macOS .

Now we parse the arguments for the command line and initialize the hyperparameters:

# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-d", "--dataset", required=True,
    help="path to input dataset")
ap.add_argument("-p", "--plot", type=str, default="plot.png",
    help="path to output loss/accuracy plot")
ap.add_argument("-m", "--model", type=str, default="covid19.model",
    help="path to output loss/accuracy plot")
args = vars(ap.parse_args())

# initialize the initial learning rate, number of epochs to train for,
# and batch size
INIT_LR = 1e-3
EPOCHS = 25
BS = 8

Our three command line arguments ( lines 24-31 ) include:

  • --dataset: path to the input dataset.
  • --plot: optional path to the exit schedule of learning history. By default, the graph is called plot.png unless a different name is specified on the command line.
  • --model: optional path to our output COVID-19 definition model. By default, it is called covid19.model.

Now we initialize the initial learning frequency, the number of training eras, and the packet size hyperparameters ( lines 35-37 ).

Next, download and pre-process the x-rays:

# grab the list of images in our dataset directory, then initialize
# the list of data (i.e., images) and class images
print("[INFO] loading images...")
imagePaths = list(paths.list_images(args["dataset"]))
data = []
labels = []

# loop over the image paths
for imagePath in imagePaths:
    # extract the class label from the filename
    label = imagePath.split(os.path.sep)[-2]

    # load the image, swap color channels, and resize it to be a fixed
    # 224x224 pixels while ignoring aspect ratio
    image = cv2.imread(imagePath)
    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    image = cv2.resize(image, (224, 224))

    # update the data and labels lists, respectively
    data.append(image)
    labels.append(label)

# convert the data and labels to NumPy arrays while scaling the pixel
# intensities to the range [0, 1]
data = np.array(data) / 255.0
labels = np.array(labels)

To load the data, we take all the paths to the images in the --dataset directory ( line 42 ), and then for each imagePath:

  • We extract from the path ( line 49 ) the class label (covid or normal).
  • We load the image, convert it to RGB channels and reduce it to a size of 224x224 pixels to feed a convolutional neural network ( lines 53-55 ).
  • Updating lists of data and labels ( lines 58 and 59 ).

Then we scale the pixel intensity into a range [0, 1]and convert the data and labels to the NumPy array format ( lines 63 and 64 ).

Next, we will perform one-hot-coding of our labels and divide the dataset into training and test sets:

# perform one-hot encoding on the labels
lb = LabelBinarizer()
labels = lb.fit_transform(labels)
labels = to_categorical(labels); print(labels)

# partition the data into training and testing splits using 80% of
# the data for training and the remaining 20% for testing
(trainX, testX, trainY, testY) = train_test_split(data, labels,
    test_size=0.20, stratify=labels, random_state=42)

# initialize the training data augmentation object
trainAug = ImageDataGenerator(
    rotation_range=15,
    fill_mode="nearest")

Unitary label coding is performed in lines 67-69 : the data will be presented in this format:

[[0. 1.]
 [0. 1.]
 [0. 1.]
 ...
 [1. 0.]
 [1. 0.]
 [1. 0.]]

Each label encoded in this way consists of a two-element array, in which one of the elements is “hot” (1) and the second is “no” (0). In lines 73 and 74, the dataset is divided into two parts: 80% for training, 20% for testing.

To generalize the model, we perform data expansion (data augmentation), setting a random image rotation by 15 degrees clockwise or counter it. The extension generation object is initialized on lines 77-79 .

Now initialize the VGGNet model and prepare it for fine tuning :

# load the VGG16 network, ensuring the head FC layer sets are left
# off
baseModel = VGG16(weights="imagenet", include_top=False,
    input_tensor=Input(shape=(224, 224, 3)))

# construct the head of the model that will be placed on top of the
# the base model
headModel = baseModel.output
headModel = AveragePooling2D(pool_size=(4, 4))(headModel)
headModel = Flatten(name="flatten")(headModel)
headModel = Dense(64, activation="relu")(headModel)
headModel = Dropout(0.5)(headModel)
headModel = Dense(2, activation="softmax")(headModel)

# place the head FC model on top of the base model (this will become
# the actual model we will train)
model = Model(inputs=baseModel.input, outputs=headModel)

# loop over all layers in the base model and freeze them so they will
# *not* be updated during the first training process
for layer in baseModel.layers:
    layer.trainable = False

In lines 83 and 84 , an instance of the VGG16 neural network is created with the weights obtained in advance on ImageNet without a fully connected layer.

Next, we will create a fully connected layer consisting of POOL => FC = SOFTMAX layers ( lines 88-93 ) and place it on top of VGG16 ( line 97 ).

Now freeze CONV-weights so that only a fully connected layer is trained ( lines 101-102 ). This finishes tuning.

Now we are ready to compile and train our deep learning model:

# compile our model
print("[INFO] compiling model...")
opt = Adam(lr=INIT_LR, decay=INIT_LR / EPOCHS)
model.compile(loss="binary_crossentropy", optimizer=opt,
    metrics=["accuracy"])

# train the head of the network
print("[INFO] training head...")
H = model.fit_generator(
    trainAug.flow(trainX, trainY, batch_size=BS),
    steps_per_epoch=len(trainX) // BS,
    validation_data=(testX, testY),
    validation_steps=len(testX) // BS,
    epochs=EPOCHS)

In lines 106-108 compiled network attenuation speed training and optimizer Adam. Given that this is a two-class classification task, we use the loss function of binary cross-entropy (binary_crossentropy), not categorical cross-entropy (categorical crossentropy).

To start the training we call Keras-method fit_generator and give him our X-rays through a data object extension ( lines 112-117 ).

Now let's evaluate the model:

# make predictions on the testing set
print("[INFO] evaluating network...")
predIdxs = model.predict(testX, batch_size=BS)

# for each image in the testing set we need to find the index of the
# label with corresponding largest predicted probability
predIdxs = np.argmax(predIdxs, axis=1)

# show a nicely formatted classification report
print(classification_report(testY.argmax(axis=1), predIdxs,
    target_names=lb.classes_))

To do this, we first perform forecasting based on the test suite and obtain forecast indices ( lines 121-125 ). Then we will generate and display the classification report ( lines 128 and 129 ) using the scikit-learn utility .

Now let's calculate the confusion matrix for future statistical estimation:

# compute the confusion matrix and and use it to derive the raw
# accuracy, sensitivity, and specificity
cm = confusion_matrix(testY.argmax(axis=1), predIdxs)
total = sum(sum(cm))
acc = (cm[0, 0] + cm[1, 1]) / total
sensitivity = cm[0, 0] / (cm[0, 0] + cm[0, 1])
specificity = cm[1, 1] / (cm[1, 0] + cm[1, 1])

# show the confusion matrix, accuracy, sensitivity, and specificity
print(cm)
print("acc: {:.4f}".format(acc))
print("sensitivity: {:.4f}".format(sensitivity))
print("specificity: {:.4f}".format(specificity))

We are here:

  • generate a matrix of inaccuracies ( line 133 ),
  • we use this matrix to determine the accuracy, sensitivity and specificity ( lines 135-137 ), and then we derive all these metrics ( lines 141-143 ).

Then, for subsequent analysis, we display in the form of a graph in a file the history of accuracy and loss changes:

# plot the training loss and accuracy
N = EPOCHS
plt.style.use("ggplot")
plt.figure()
plt.plot(np.arange(0, N), H.history["loss"], label="train_loss")
plt.plot(np.arange(0, N), H.history["val_loss"], label="val_loss")
plt.plot(np.arange(0, N), H.history["accuracy"], label="train_acc")
plt.plot(np.arange(0, N), H.history["val_accuracy"], label="val_acc")
plt.title("Training Loss and Accuracy on COVID-19 Dataset")
plt.xlabel("Epoch #")
plt.ylabel("Loss/Accuracy")
plt.legend(loc="lower left")
plt.savefig(args["plot"])

And finally, we serialize the tf.keras classifier model to disk:

# serialize the model to disk
print("[INFO] saving COVID-19 detector model...")
model.save(args["model"], save_format="h5")

We train our detector with Keras and TensorFlow


After the implementation of the train_covid19.py script, we can train the automatic detector.

Download the source code, dataset and pre-trained model. Open a terminal and run the command to train the detector:

$ python train_covid19.py --dataset dataset
[INFO] loading images...
[INFO] compiling model...
[INFO] training head...
Epoch 1/25
5/5 [==============================] - 20s 4s/step - loss: 0.7169 - accuracy: 0.6000 - val_loss: 0.6590 - val_accuracy: 0.5000
Epoch 2/25
5/5 [==============================] - 0s 86ms/step - loss: 0.8088 - accuracy: 0.4250 - val_loss: 0.6112 - val_accuracy: 0.9000
Epoch 3/25
5/5 [==============================] - 0s 99ms/step - loss: 0.6809 - accuracy: 0.5500 - val_loss: 0.6054 - val_accuracy: 0.5000
Epoch 4/25
5/5 [==============================] - 1s 100ms/step - loss: 0.6723 - accuracy: 0.6000 - val_loss: 0.5771 - val_accuracy: 0.6000
...
Epoch 22/25
5/5 [==============================] - 0s 99ms/step - loss: 0.3271 - accuracy: 0.9250 - val_loss: 0.2902 - val_accuracy: 0.9000
Epoch 23/25
5/5 [==============================] - 0s 99ms/step - loss: 0.3634 - accuracy: 0.9250 - val_loss: 0.2690 - val_accuracy: 0.9000
Epoch 24/25
5/5 [==============================] - 27s 5s/step - loss: 0.3175 - accuracy: 0.9250 - val_loss: 0.2395 - val_accuracy: 0.9000
Epoch 25/25
5/5 [==============================] - 1s 101ms/step - loss: 0.3655 - accuracy: 0.8250 - val_loss: 0.2522 - val_accuracy: 0.9000
[INFO] evaluating network...
              precision    recall  f1-score   support

       covid       0.83      1.00      0.91         5
      normal       1.00      0.80      0.89         5

    accuracy                           0.90        10
   macro avg       0.92      0.90      0.90        10
weighted avg       0.92      0.90      0.90        10

[[5 0]
 [1 4]]
acc: 0.9000
sensitivity: 1.0000
specificity: 0.8000
[INFO] saving COVID-19 detector model...

Auto X-ray Diagnostics


Note: in this part we do not "solve" the problem of determining COVID-19. It is written in the context of the current situation and only for educational purposes. This is an example of the practical application of computer vision and deep learning, so that you get comfortable with different metrics, including the usual accuracy, sensitivity and specificity (and trade-offs that must be considered when working with medical data). I repeat, we do not solve the problem of determining COVID-19.

So, our automatic detector showed an accuracy of ~ 90-92% on samples ofX-ray images alone . No other information was used to train the model, including geographic location, population density, etc.

We also receivedsensitivity of 100% and specificity of 80% , which means:

  • Of the patients with COVID-19 (true positive cases), using the model, we were able to accurately identify as “COVID-19 positive” in 100% of cases.
  • Of the patients who did not have COVID-19 (true negative cases), using the model, we were able to accurately identify as “COVID-19-negative” in only 80% of cases.

As the training history graph shows, the neural network is not retrained, despite the very small size of the training data:


Figure 3: This graph of accuracy and loss demonstrates that our model is not retrained.

It’s great that we achieved 100% accuracy when detecting COVID-19. However, the situation with truly negative cases is embarrassing: we do not want to attribute to “COVID-19-negative” those who are actually “COVID-19-positive”.

We least want to let sick patients go home, to families and friends, contributing to the further spread of the disease.

You also need to be very careful with the share of false-positive cases: we do not want to mistakenly count someone as sick and quarantine him with other patients so that he gets infected from them .

Finding a balance between sensitivity and specificity -an extremely difficult task, especially when it comes to medicine, and especially when it comes to rapidly spreading infectious diseases.

Speaking about medical computer vision and deep learning, you should always remember that the work of our predictive models can have very serious consequences: erroneous diagnoses can cost lives .

I repeat, the results in this article are presented for educational purposes only . This is not a journal publication, this data does not meet the TRIPOD criteria for the publication of forecast models.

Limitations, improvements and further work



Figure 4: Today, AI and deep learning professionals lack quality COVID-19 data to effectively train automatic image recognition systems.

One of the main limitations of the method described in this manual is data.

We do not have enough (reliable) data to train COVID-19 detectors.

Hospitals already have many case histories with this virus, but given privacy and human rights, it becomes even more difficult to quickly assemble a high-quality dataset from medical images. I believe that in the next 12-18 months we will have more quality data. But for now, you have to use what you have.

I tried (given my physical and mental condition) in the conditions of limited time and resources to write this guide for those who are interested in the use of computer vision and deep learning. But let me remind you that I am not a professional medic .

In order to use the COVID-19 detector in real life, it has to be rigorously tested by real doctors working hand in hand with deep learning specialists. The method I described is not suitable for this.

Moreover, one must be careful with what exactly the model “learns”.

As I wrote in the Grad-CAM manual, it is likely that the model will learn patterns that are not relevant to COVID-19, but only be able to distinguish between two data samples (i.e., positive and negative diagnoses). The results of our detector will need to be rigorously tested and checked by doctors.

And finally, future (and more advanced) detectors will be multimodal.

Now we use only visual data (x-rays). Better detectors should use other data: patient vital indicators, population density, geographical location, etc. Visual data alone is usually not enough for such tasks .

For these reasons, I want to emphasize again: this guide only plays the role of training material - it cannot be considered as a reliable COVID-19 detector.

If you think that you or someone close to COVID-19, then follow the recommendations of your healthcare system.

I hope this guide has been helpful to you. I also hope that it will be for someone a starting point in the search for methods of using computer vision and deep learning to automatically determine COVID-19.

Summary


In this guide, you learned how to use Keras, TensorFlow, and deep learning to create a COVID-19 automatic detector on an x-ray dataset.

Today (yet) there are no high-quality and verified image datasets for this disease, so you have to work with the Joseph Cohen repository :


Then with the help of Keras and TensorFlow we trained the COVID-19 detector, which showed an accuracy of 90-92% on our test sample, with a sensitivity of 100% and a specificity of 80% (on our small dataset).

Remember that the detector described here is for educational purposes only (see Note in text). I wanted to inspire other people to use deep learning, to show that in combination with computer vision it can have a big impact on our lives.

I hope you enjoyed it.

All Articles