COVID-19 Detection with ML and CXR | تشخیص کرونا توسط یادگیری ماشین و CXR

I share my academic life!

COVID-19 Detection with ML and CXR | تشخیص کرونا توسط یادگیری ماشین و CXR

زمانیکه شروع به ساخت این برنامه کردم بحران تعداد کیت داشتیم
با توجه به علائم کیفی مانند تب و سرفه و غیره نمیتوان بطور قطع گفت که فرد مبتلا به این بیماریست یا خیر …

بنابر مقاله های جدید منتشر شده در دو هفته اخیر متوجه شدم که اسکن ریه میتونه خیلی واضح توی روند تشخیص کمک کنه.
با مطالعه مقالات و پیدا کردن دیتابیسشون تونستم یه شمای کلی از مساله پیدا کنم
متاسفانه تنها مشکل این نرم افزار کم بودن داده های آموزش هست که خوب میشه اگر بیمارستان ها بتونند داده هاشون رو به اشتراک بزارن

علاوه بر عکس های ایکس ری، نیاز به داده های بیشتر مثل سچوریشن اکسیژن خون، میزان دمای بدن، جنسیت و فاکتور های دیگر رو میشه بعنوان ورودی به سیستم داد تا تخمین دقیق تری داشته باشیم

When I started to work on this problem, we had problem with numbers of DETECTING KITs to examine patients who had the symptoms.
After reading papers about this problem, I tried to create an demo app to distinguish between normal and abnormal lungs.

output| خروجی
import os
import numpy as np
import pandas as pd 
import random
import cv2
import matplotlib.pyplot as plt
import keras.backend as K

from keras.models import Model, Sequential
from keras.layers import Input, Dense, Flatten, Dropout, BatchNormalization
from keras.layers import Conv2D, SeparableConv2D, MaxPool2D, LeakyReLU, Activation
from keras.optimizers import Adam
from keras.preprocessing.image import ImageDataGenerator
from keras.callbacks import ModelCheckpoint, ReduceLROnPlateau, EarlyStopping

import tensorflow as tf



seed = 200
np.random.seed(seed)
tf.random.set_seed(seed)

input_path = 'chest_xray/DATA/'

fig, img = plt.subplots(2, 3, figsize=(15, 15))
img = img.ravel()
plt.tight_layout()

for i, _set in enumerate(['train', 'val', 'test']):
    set_path = input_path+_set
    img[i].imshow(plt.imread(set_path+'/NORMAL/'+os.listdir(set_path+'/NORMAL')[0]), cmap='gray')
    img[i].set_title('Normal'.format(_set))
    img[i+3].imshow(plt.imread(set_path+'/COVID/'+os.listdir(set_path+'/COVID')[0]), cmap='gray')
    img[i+3].set_title('nCoVid-19'.format(_set)) 
    

for _set in ['train', 'val', 'test']:
    n_normal = len(os.listdir(input_path + _set + '/NORMAL'))
    n_infect = len(os.listdir(input_path + _set + '/COVID'))
    print('normal images: {}, nCoVid-19 images: {}'.format(_set, n_normal, n_infect))
    



def process_data(img_dims, batch_size):

    train_datagen = ImageDataGenerator(rescale=1./255, zoom_range=0.3, vertical_flip=True)
    test_val_datagen = ImageDataGenerator(rescale=1./255)
    

    train_gen = train_datagen.flow_from_directory(
    directory=input_path+'train', 
    target_size=(img_dims, img_dims), 
    batch_size=batch_size, 
    class_mode='binary', 
    shuffle=True)

    test_gen = test_val_datagen.flow_from_directory(
    directory=input_path+'test', 
    target_size=(img_dims, img_dims), 
    batch_size=batch_size, 
    class_mode='binary', 
    shuffle=True)
    


    test_data = []
    test_labels = []

    for cond in ['/NORMAL/', '/COVID/']:
        for img in (os.listdir(input_path + 'test' + cond)):
            img = plt.imread(input_path+'test'+cond+img)
            img = cv2.resize(img, (img_dims, img_dims))
            img = np.dstack([img, img, img])
            img = img.astype('float32') / 255
            if cond=='/NORMAL/':
                label = 0
            elif cond=='/COVID/':
                label = 1
            test_data.append(img)
            test_labels.append(label)
        
    test_data = np.array(test_data)
    test_labels = np.array(test_labels)
    
    return train_gen, test_gen, test_data, test_labels

img_dims = 150
epochs = 10
batch_size = 32

train_gen, test_gen, test_data, test_labels = process_data(img_dims, batch_size)
inputs = Input(shape=(img_dims, img_dims, 3))

x = Conv2D(filters=16, kernel_size=(3, 3), activation='relu', padding='same')(inputs)
x = Conv2D(filters=16, kernel_size=(3, 3), activation='relu', padding='same')(x)
x = MaxPool2D(pool_size=(2, 2))(x)

x = SeparableConv2D(filters=32, kernel_size=(3, 3), activation='relu', padding='same')(x)
x = SeparableConv2D(filters=32, kernel_size=(3, 3), activation='relu', padding='same')(x)
x = BatchNormalization()(x)
x = MaxPool2D(pool_size=(2, 2))(x)

x = SeparableConv2D(filters=64, kernel_size=(3, 3), activation='relu', padding='same')(x)
x = SeparableConv2D(filters=64, kernel_size=(3, 3), activation='relu', padding='same')(x)
x = BatchNormalization()(x)
x = MaxPool2D(pool_size=(2, 2))(x)

x = SeparableConv2D(filters=128, kernel_size=(3, 3), activation='relu', padding='same')(x)
x = SeparableConv2D(filters=128, kernel_size=(3, 3), activation='relu', padding='same')(x)
x = BatchNormalization()(x)
x = MaxPool2D(pool_size=(2, 2))(x)
x = Dropout(rate=0.2)(x)

x = SeparableConv2D(filters=256, kernel_size=(3, 3), activation='relu', padding='same')(x)
x = SeparableConv2D(filters=256, kernel_size=(3, 3), activation='relu', padding='same')(x)
x = BatchNormalization()(x)
x = MaxPool2D(pool_size=(2, 2))(x)
x = Dropout(rate=0.2)(x)

x = SeparableConv2D(filters=512, kernel_size=(3, 3), activation='relu', padding='same')(x)
x = SeparableConv2D(filters=512, kernel_size=(3, 3), activation='relu', padding='same')(x)
x = BatchNormalization()(x)
x = MaxPool2D(pool_size=(2, 2))(x)
x = Dropout(rate=0.2)(x)

output = Dense(units=1, activation='sigmoid')(x)
model = Model(inputs=inputs, outputs=output)
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

checkpoint = ModelCheckpoint(filepath='best_weights.hdf5', save_best_only=True, save_weights_only=True)
lr_reduce = ReduceLROnPlateau(monitor='val_loss', factor=0.3, patience=2, verbose=2, mode='max')
early_stop = EarlyStopping(monitor='val_loss', min_delta=0.1, patience=1, mode='min')


hist = model.fit_generator(train_gen, steps_per_epoch=train_gen.samples // batch_size,epochs=epochs, validation_data=test_gen,validation_steps=test_gen.samples // batch_size,callbacks=[checkpoint, lr_reduce])
https://pubs.rsna.org/2019-nCoV#images

https://www.itnonline.com/content/ct-provides-best-diagnosis-novel-coronavirus-covid-19



https://radiopaedia.org/cases/covid-19-pneumonia-4

Update 1: A Chinese group developed improved version of my idea :

https://www.medrxiv.org/content/10.1101/2020.02.14.20023028v3

A deep learning algorithm using CT images to screen for Corona Virus Disease (COVID-19)

Shuai Wang, Bo Kang, Jinlu Ma, Xianjun Zeng, Mingming Xiao, Jia Guo, Mengjiao Cai, Jingyi Yang, Yaodong Li, Xiangfei Meng, Bo Xu

doi: https://doi.org/10.1101/2020.02.14.20023028 

Update 2: Dataset I used: DOWNLOAD

Update 3: Add this part to the code if you face with errors

import os
import numpy as np
import pandas as pd 
import random
import cv2
import matplotlib.pyplot as plt
import keras.backend as K

from keras.models import Model, Sequential
from keras.layers import Input, Dense, Flatten, Dropout, BatchNormalization
from keras.layers import Conv2D, SeparableConv2D, MaxPool2D, LeakyReLU, Activation
from keras.optimizers import Adam
from keras.preprocessing.image import ImageDataGenerator
from keras.callbacks import ModelCheckpoint, ReduceLROnPlateau, EarlyStopping

import tensorflow as tf



seed = 200
np.random.seed(seed)
tf.random.set_seed(seed)

input_path = 'chest_xray/DATA/'

fig, img = plt.subplots(2, 3, figsize=(15, 15))
img = img.ravel()
plt.tight_layout()

for i, _set in enumerate(['train', 'val', 'test']):
    set_path = input_path+_set
    img[i].imshow(plt.imread(set_path+'/NORMAL/'+os.listdir(set_path+'/NORMAL')[0]), cmap='gray')
    img[i].set_title('Normal'.format(_set))
    img[i+3].imshow(plt.imread(set_path+'/COVID/'+os.listdir(set_path+'/COVID')[0]), cmap='gray')
    img[i+3].set_title('nCoVid-19'.format(_set)) 
    

for _set in ['train', 'val', 'test']:
    n_normal = len(os.listdir(input_path + _set + '/NORMAL'))
    n_infect = len(os.listdir(input_path + _set + '/COVID'))
    print('normal images: {}, nCoVid-19 images: {}'.format(_set, n_normal, n_infect))
    



def process_data(img_dims, batch_size):

    train_datagen = ImageDataGenerator(rescale=1./255, zoom_range=0.3, vertical_flip=True)
    test_val_datagen = ImageDataGenerator(rescale=1./255)
    

    train_gen = train_datagen.flow_from_directory(
    directory=input_path+'train', 
    target_size=(img_dims, img_dims), 
    batch_size=batch_size, 
    class_mode='binary', 
    shuffle=True)

    test_gen = test_val_datagen.flow_from_directory(
    directory=input_path+'test', 
    target_size=(img_dims, img_dims), 
    batch_size=batch_size, 
    class_mode='binary', 
    shuffle=True)
    


    test_data = []
    test_labels = []

    for cond in ['/NORMAL/', '/COVID/']:
        for img in (os.listdir(input_path + 'test' + cond)):
            img = plt.imread(input_path+'test'+cond+img)
            img = cv2.resize(img, (img_dims, img_dims))
            img = np.dstack([img, img, img])
            img = img.astype('float32') / 255
            if cond=='/NORMAL/':
                label = 0
            elif cond=='/COVID/':
                label = 1
            test_data.append(img)
            test_labels.append(label)
        
    test_data = np.array(test_data)
    test_labels = np.array(test_labels)
    
    return train_gen, test_gen, test_data, test_labels

img_dims = 150
epochs = 10
batch_size = 32

train_gen, test_gen, test_data, test_labels = process_data(img_dims, batch_size)
inputs = Input(shape=(img_dims, img_dims, 3))

x = Conv2D(filters=16, kernel_size=(3, 3), activation='relu', padding='same')(inputs)
x = Conv2D(filters=16, kernel_size=(3, 3), activation='relu', padding='same')(x)
x = MaxPool2D(pool_size=(2, 2))(x)

x = SeparableConv2D(filters=32, kernel_size=(3, 3), activation='relu', padding='same')(x)
x = SeparableConv2D(filters=32, kernel_size=(3, 3), activation='relu', padding='same')(x)
x = BatchNormalization()(x)
x = MaxPool2D(pool_size=(2, 2))(x)

x = SeparableConv2D(filters=64, kernel_size=(3, 3), activation='relu', padding='same')(x)
x = SeparableConv2D(filters=64, kernel_size=(3, 3), activation='relu', padding='same')(x)
x = BatchNormalization()(x)
x = MaxPool2D(pool_size=(2, 2))(x)

x = SeparableConv2D(filters=128, kernel_size=(3, 3), activation='relu', padding='same')(x)
x = SeparableConv2D(filters=128, kernel_size=(3, 3), activation='relu', padding='same')(x)
x = BatchNormalization()(x)
x = MaxPool2D(pool_size=(2, 2))(x)
x = Dropout(rate=0.2)(x)

x = SeparableConv2D(filters=256, kernel_size=(3, 3), activation='relu', padding='same')(x)
x = SeparableConv2D(filters=256, kernel_size=(3, 3), activation='relu', padding='same')(x)
x = BatchNormalization()(x)
x = MaxPool2D(pool_size=(2, 2))(x)
x = Dropout(rate=0.2)(x)

x = SeparableConv2D(filters=512, kernel_size=(3, 3), activation='relu', padding='same')(x)
x = SeparableConv2D(filters=512, kernel_size=(3, 3), activation='relu', padding='same')(x)
x = BatchNormalization()(x)
x = MaxPool2D(pool_size=(2, 2))(x)
x = Dropout(rate=0.2)(x)

x = Flatten()(x)
x = Dense(units=512, activation='relu')(x)
x = Dropout(rate=0.7)(x)
x = Dense(units=128, activation='relu')(x)
x = Dropout(rate=0.5)(x)
x = Dense(units=64, activation='relu')(x)
x = Dropout(rate=0.3)(x)
x = Dense(units=32, activation='relu')(x)
x = Dropout(rate=0.1)(x)

output = Dense(units=1, activation='sigmoid')(x)
model = Model(inputs=inputs, outputs=output)
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

checkpoint = ModelCheckpoint(filepath='best_weights.hdf5', save_best_only=True, save_weights_only=True)
lr_reduce = ReduceLROnPlateau(monitor='val_loss', factor=0.3, patience=2, verbose=2, mode='max')
early_stop = EarlyStopping(monitor='val_loss', min_delta=0.1, patience=1, mode='min')


hist = model.fit_generator(train_gen, steps_per_epoch=train_gen.samples // batch_size,epochs=epochs, validation_data=test_gen,validation_steps=test_gen.samples // batch_size,callbacks=[checkpoint, lr_reduce])

Tags: , , , , , , , , , , , , , ,

16 Responses

  1. Rose Verma says:

    Hi,
    Can you share the dataset on which you worked?

    • rezaamini says:

      I updated this post and added dataset. I changed folders containing COVID-19 subjects and deleted low-quality images, just add yours and run the code 🙂 good luck.

  2. AJ says:

    Thank you for this. Do you know if the Chinese group’s dataset is available? I can’t seem to access it.
    https://ai.nscc-tj.cn/thai/deploy/public/pneumonia_ct

    Do you know other places with the CT dataset?

  3. ali says:

    سلام مرسی از مطالبی که گذاشتید
    دیتاستتون رو نگا میکردم فقط با 3 تا عکس از کرونا استفاده کردین . دقت شبکه تا چند درصد بود ؟
    از چه معماری استفاده کردید ؟
    نسخه تنسورفلو شما چنده ؟ چون من میخواستم تست کنم کلا بهم ارور داد با کد های بالا
    نسخه پایتون چند استفاده کردید؟

    • rezaamini says:

      سلام. تعداد 16 عکس استفاده کردم که غیر ا این 3 تا. 4 تا عکس دیگه از توی مقالات پیدا کرده بودم و بقیش رو هم دوستم که در بیمارستان کار میکنه برام فرستاده بود(9 عکس). 4 تا رو بخاطر اینکه حس کردم کیفیتش بده حذف کردم و بقیه رو بخاطر اینکه رایگان نبودن.
      صرفا جهت ایده بود انجامش چون تازه اولای بیماری بود و تقریبا تعداد تصویر کمی با رعایت پروتکل های تصویر برداری خاص وجود داشت
      شاید اگه ارور مورد نظر رو مینوشتین میتونستم کمکتون کنم چون برای من اروری نداده
      Spyder 3.3.6
      python 3.7
      tensorflow 2.0.0

      • ali says:

        مرسی از راهنماییتون
        تو شبکه ای که پیاده کردین خروجی نهایی چی هست؟
        سگمنتیشن انجام میگیره مثل یونت ؟ یا چی؟

    • rezaamini says:

      احتمالا مشکلتون رو فهمیدم! از قسمت آپدیت سوم استفاده کنید

      • ali says:

        مرسی اینم حتما چک میکنم . سپاس

      • ali says:

        ایول حل شد .
        مشکلش چی بود ؟ میشه اشاره کنی بهش؟
        من کلی بررسی کردم چیزی نفهمیده بودم

        • rezaamini says:

          بخاطر ابعاد ورودی ها بود
          من هرچی بگم کم گفتم بخاطر همین توابعی که میگم رو گوگل کن:
          flatten – dropout
          کاری هم که کردم خیلی سادس. فقط چن ردیف شبکه کانولوشنی تشکیل دادم/ (همونطور که گفتم این یه دمو هست و هدف ایده دادن بود فقط )

  4. I foresaw this from February 9th, having started an ai based ct scan initiative:

    http://www.facebook.com/ProgrammingGodJordan%2Fposts%2F889038718221822

Comments are closed.