Teach you to use TensorFlow2 to determine whether a cell image is infected

@Author: Runsen

In this tutorial, we will use TensorFlow (Keras API) to implement a deep learning model for a binary classification task, which includes marking images of cells as infected or uninfected with malaria.

Data set source: https://www.kaggle.com/iarunava/cell-images-for-detecting-malaria

The data set contains 2 folders

  • Infection: 13780 pictures
  • Uninfected: 13,780 pictures

There are 27558 pictures in total.

This data set is taken from the official NIH website: https://ceb.nlm.nih.gov/repositories/malaria-datasets/

For image data, there are different shapes, so OpenCV needs to be used for image preprocessing.

Convert the picture into a numpy array (number format) to grayscale and adjust it to a (70x70) shape.

Environment: kaggle, tianchi laboratory or gogole colab can be used.

Import related modules

import cv2
import tensorflow as tf
from tensorflow.keras.models import Sequential 
from tensorflow.keras.layers import Dense, Conv2D, MaxPool2D, Flatten, Activation
from sklearn.model_selection import train_test_split
import numpy as np
import matplotlib.pyplot as plt
import glob
import os
img_dir="../input/cell-images-for-detecting-malaria/cell_images"  
img_size=70
def load_img_data(path):
    # 打乱数据
    image_files = glob.glob(os.path.join(path, "Parasitized/*.png")) + \
                  glob.glob(os.path.join(path, "Uninfected/*.png"))
    X, y = [], []
    for image_file in image_files:
        # 命名标签  0 for uninfected and 1 for infected
        label = 0 if "Uninfected" in image_file else 1
        # load the image in gray scale 变成灰度图片
        img_arr = cv2.imread(image_file, cv2.IMREAD_GRAYSCALE)
        # resize the image to (70x70)  调整图片大小
        img_resized = cv2.resize(img_arr, (img_size, img_size))
        X.append(img_resized)
        y.append(label)
    return X, y
X, y = load_img_data(img_dir)

Check the shape of X.

print(X.shape)

The shape of X is (27558, 70, 70, 1), 27558 represents the data of the 70*70picture , and represents the length and width pixels of the picture.

In addition, in order to help the network converge faster, we should perform data normalization. There are some scaling methods in sklearn, for example:

  • StandardScaler:  x n o r m = (X − average) / S T D x_norm = (X-average)/ STD xn​o r m=( X−Level average value ) / S T D (Where std is the standard deviation)
  • MinMaxScaler:  x n o r m = ( x − x m i n ) / ( x m a x − x m i n ) x_norm = (x - x_{min}) / (x_{max} - x_{min}) xn​o r m=( x−xm i n​) / ( xm a x​−xm i n​)This causes x_norm to be between 0 and 1

Here we will divide by 255, because the maximum value a pixel can reach is 255, which will cause the pixel range to be between 0 and 1 after scaling is applied.

X, y = load_img_data(img_dir)
# reshape to (n_samples, 70, 70, 1) (to fit the NN)
X = np.array(X).reshape(-1, img_size, img_size, 1)
#从[0,255]到[0,1]缩放像素 帮助神经网络更快地训练
X = X / 255

# shuffle & split the dataset
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, stratify=y)
print("Total training samples:", X_train.shape)
print("Total validation samples:", X_test.shape[0])

Use sklearn's train_test_split() method to divide the data set into a training set and a test set. We use 10% of the total data to verify it later.

In the established model, we will add 3 convolutional layers, and then Flatten is a fully connected Dense layer composed of layers.

model = Sequential()
model.add(Conv2D(64, (3, 3), input_shape=X_train.shape[1:]))
model.add(Activation("relu"))
model.add(MaxPool2D(pool_size=(2, 2)))

model.add(Conv2D(64, (3, 3)))
model.add(Activation("relu"))
model.add(MaxPool2D(pool_size=(2, 2)))

model.add(Conv2D(64, (3, 3)))
model.add(Activation("relu"))
model.add(MaxPool2D(pool_size=(2, 2)))

model.add(Flatten())

model.add(Dense(64))
model.add(Activation("relu"))

model.add(Dense(64))
model.add(Activation("relu"))

model.add(Dense(1))
model.add(Activation("sigmoid"))

model.compile(loss="binary_crossentropy", optimizer="adam", metrics=["accuracy"])
print(model.summary())

Since the output is binary (infected or uninfected), we use the Sigmoid function as the activation function of the output layer.

# train the model with 10 epochs, 64 batch size
model.fit(X_train, np.array(y_train), batch_size=64, epochs=10, validation_split=0.2)

A 94% accuracy rate was achieved on the training data set and its verification split.

Now use evaluate()to evaluate the model on the test data set

loss, accuracy = model.evaluate(X_test, np.array(y_test), verbose=0)
print(f"Testing on {len(X_test)} images, the results are\n Accuracy: {accuracy} | Loss: {loss}")

The output is as follows

Testing on 2756 images, the results are
Accuracy: 0.9404934644699097 | Loss: 0.1666732281446457

The model also performed OK in the test data, with an accuracy rate of 94%

Finally, we will end all this process by saving our model.

model.save("model.h5")