使用Keras,TensorFlow和深度学习检测X射线中的COVID-19


在本指南的帮助下,在Keras,TensorFlow和深度学习的帮助下,我们将学习如何从X射线图像的手动组装数据集中自动确定COVID-19。

像许多其他人一样,我真诚地担心COVID-19。我注意到我一直在分析自己的病情,想知道我是否会传染这种疾病以及何时会发生。而且我越担心,它就越会变成痛苦的心理游戏,在这种游戏中,症状学与下软骨症相结合:

  • 我早上醒来,感到有些酸痛和无力。
  • 当我爬下床时,我发现了流鼻涕(尽管已经知道流鼻涕不是 COVID-19的症状)。
  • 到我去洗手间拿纸巾的时候,我已经咳嗽了。

刚开始我没有特别注意-我对花粉过敏,由于美国东海岸的温暖天气,今年春天是早春。这些很可能是过敏症状。但是白天我的状况没有改善。我坐着,用嘴里的温度计写这本手册。我往下看,看到37.4°C。我的正常体温略低于其他人,为36.3°C。对我来说,高于37.2°C的一切都已经有点热了。

咳嗽和轻微发烧?可能是COVID-19,或者只是我的过敏。没有测试就不可能发现,正是这种“无知”使这种情况在人的层面上如此令人生畏。

不明飞行物护理分钟


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



, .

, , .

: |

尽管有我的恐惧,我还是尝试理性地思考。我30岁多一点,身体状况很好,免疫力很强。我将隔离自己(以防万一),休息并处理所有事情。从个人健康的角度来看,COVID-19并没有吓到我(至少我会为我自己站起来)。

因此,我担心我的老年亲戚,包括所有已经被诊断出患有这种疾病的人,以及在疗养院和医院中的人。这些人很脆弱,如果死于COVID-19,这将是可怕的。

我决定不做任何事情而让自己的病使我呆在家里(无论是过敏,COVID-19还是我的恐惧),我决定做我能做的:我将编写代码,进行实验,并使用实际示例教其他人如何使用计算机视觉和深度学习

我必须马上说,这不是我写最科学的文章。她一点都不科学。所使用的方法和数据集值得发布。但是对于那些至少想要一些帮助的人来说,它们是一个起点

我担心您和这个社区。我想提供我所能提供的帮助:这篇文章是我在精神上应付困难时期的方法,同时可以帮助处于类似情况的其他人。

在本指南中,您将学习:

  1. 如何收集检测到COVID-19的患者的X射线图像的开源数据集。
  2. «» ( ) .
  3. COVID-19 .
  4. .

注意:我已经暗示过这一点,但是现在我直接说。此处描述的技术仅用于教育目的。不是严格的科学研究;不会在期刊上发表。本文面向对计算机视觉和深度学习感兴趣,希望在实践中学习的读者以及受时事启发的读者。我请你考虑所有这些。

在手册的第一部分中,我们将讨论如何在肺部X射线中检测COVID-19。然后,我们讨论数据集本身。然后,我将展示如何使用Keras和TensorFlow训练模型以预测图像中的COVID-19。

说明


这篇COVID-19自动检测文章仅用于教育目的。它没有描述可靠且准确的诊断系统COVID-19,也没有从专业人士或学术角度进行过测试。

我的目标是激发您的灵感,并展示对计算机视觉和深度学习的研究以及在医学领域的后续应用如何对世界产生重大影响。

想象一下:您不需要医学教育就能影响医学。如今,接受深度培训的从业人员与医生及其他医生紧密合作,共同解决复杂问题,挽救生命并让世界变得更加美好。

我希望我的领导能激励您这样做。

但是考虑到以上所有因素,研究人员,杂志策展人和评论系统已经不胜枚举描述COVID-19可疑质量预测模型的作品。请不要将本文的代码和模型发送给期刊或某些科学出版物,否则只会增加混乱

此外,如果您想根据本文(或任何其他有关COVID-19的出版物)进行研究,请遵循TRIPOD指南来描述预测模型。

如您所知,在医学领域使用人工智能会产生非常严重的后果。仅当您是医学专家或得到专家的详细建议时,才发布和使用此类模型。

如何在X射线中检测到COVID-19?



图1:诊断为COVID-19的患者的X射线示例。在这些图像中,您可以使用Keras和TensorFlow教授分类器以确定COVID-19。

现在很难对COVID-19进行测试-没有足够的测试,但是不可能快速生成它们,这只会增加恐慌。惊慌失措的是,有一些流氓企图利用他人的钱赚钱在COVID-19上出售假测试发现自己在社交网络和即时通讯工具中毫无戒心。

鉴于测试数量有限,我们需要依靠其他诊断方法。

我决定研究X射线,因为医生经常使用X射线和计算机断层扫描结果来诊断肺炎,肺部炎症,脓肿和淋巴结肿大。由于该病毒攻击呼吸道的上皮细胞,因此我们可以使用X射线研究人肺的状况。而且,由于X射线机几乎无处不在,使用图像您可以在没有测试套件的情况下检测到COVID-19

该方法的缺点包括需要放射科医生以及大量的处理时间。当世界各地的人们生病时,时间特别昂贵。为了节省医生的时间,您需要创建一个自动分析系统

注意: , , COVID-19 . . , , , , COVID-19, .

COVID-19



图2:左侧是阳性结果(被感染)的图片,右侧是阴性结果。在这些图像中,我们将讲授使用TensorFlow和Keras的模型来自动预测COVID-19的存在(即冠状病毒引起的疾病)。在蒙特利尔大学的研究生 Joseph Cohen博士

的指导下,将此处使用的与COVID-19一起使用的患者图像数据集进行了编译几天前,Cohen开始收集COVID-19患者的X射线图像,并将其上传到GitHub存储库。在这里,您不仅可以找到这种疾病的例子,还可以找到MERS,SARS和ARDS的例子。 要创建数据集,请执行以下操作:



  1. 从存储库中解析metadata.csv文件。
  2. 选择所有行:

总共获得25张照片在COVID-19上获得了阳性结果图2)。

现在选择健康人的照片。

为此,我采集Kaggle的肺部X射线数据集(肺炎),并选择了25张健康人的图像图2)。该数据集有很多缺点,包括标签填充不正确或不正确,但是它适合作为测试COVID-19检测器假设的起点。

结果,我得到了50次注射: 25例COVID-19患者和25例健康患者。您可以从链接下载数据集另外,我添加了用于生成数据集的Python脚本,但是在本文中我没有考虑它们。

项目结构


下载代码和数据。从那里拉出文件,您将获得以下目录结构:

$ 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

三个目录,五个文件。数据集位于数据集/目录中,分为两类-covid /和normal /。下面我们看一下训练COVID-19检测器的train_covid19.py脚本。

训练脚本实施


让我们继续微调卷积神经网络,它将使用Keras,TensorFlow和深度学习自动诊断COVID-19。

打开train_covid19.py文件并粘贴以下代码:

# 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

该脚本通过选择tensorflow.keras导入来利用TensorFlow 2.0和Keras库。我们也使用:


要了解如何安装TensorFlow 2.0(包括scikit-learn,OpenCV和matplotlib),请查看我的UbuntumacOS教程

现在,我们解析命令行的参数并初始化超参数:

# 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

我们的三个命令行参数第24-31行)包括:

  • --dataset:输入数据集的路径。
  • --plot:学习历史记录退出时间表的可选路径。默认情况下,该图形称为plot.png,除非在命令行上指定了其他名称。
  • --model:输出COVID-19定义模型的可选路径。默认情况下,它称为covid19.model。

现在,我们初始化初始学习频率,训练时代数和数据包大小超参数(第35-37行)。

接下来,下载并预处理X射线:

# 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)

要加载数据,我们采用--dataset目录(第42行)中所有图像的路径,然后为每个imagePath:

  • 我们从路径(第49行)中提取类标签(共阴或普通)。
  • 我们加载图像,将其转换为RGB通道,并将其缩小为224x224像素,以馈送卷积神经网络(第53-55行)。
  • 更新数据和标签列表(第58和59行)。

然后,我们将像素强度缩放到一个范围[0, 1],并将数据和标签转换为NumPy数组格式(第63和64行)。

接下来,我们将对标签执行一次热编码,并将数据集分为训练集和测试集:

# 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")

统一标签编码在第67-69行执行:数据将以以下格式显示:

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

以这种方式编码的每个标签都包含一个由两个元素组成的数组,其中一个元素为“ hot”(1),第二个元素为“ no”(0)。在第73和74行中,数据集分为两个部分:80%用于训练,20%用于测试。

为了概括该模型,我们执行数据扩展(数据增强),将图像随机旋转设置为顺时针旋转15度或对其进行抵消。扩展生成对象在第77-79行初始化

现在初始化VGGNet模型并准备进行微调

# 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

第83和84行中,使用预先在ImageNet上获得的权重(没有完全连接的层)创建了VGG16神经网络的实例。

接下来,我们将创建一个由POOL => FC = SOFTMAX层组成的完全连接的层(第88-93行),并将其放置在VGG16的顶部(第97行)。

现在冻结CONV权重,以便训练完全连接的图层(第101-102行)。调整完成。

现在我们准备编译和训练我们的深度学习模型:

# 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)

第106-108行中,编制了网络衰减速度训练和优化器Adam。鉴于这是两类分类任务,我们使用二进制交叉熵(binary_crossentropy)的损失函数,而不是分类交叉熵(类别交叉熵)的损失函数。

要开始训练,我们将其称为Keras -technique fit_generator,并通过数据对象扩展名(第112-117行为他提供X射线

现在让我们评估模型:

# 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_))

为此,我们首先基于测试套件执行预测并获得预测索引(第121-125行)。然后,我们将使用scikit-learn实用工具生成并显示分类报告(第128和129行)。

现在,让我们计算混淆矩阵,以便将来进行统计估计:

# 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))

我们在这儿:

  • 生成不准确性矩阵(第133行),
  • 我们使用此矩阵确定准确性,敏感性和特异性(第135-137行),然后得出所有这些指标(第141-143行)。

然后,为了进行后续分析,我们以图形形式在文件中显示准确性和损失的变化历史:

# 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"])

最后,我们将tf.keras分类器模型序列化到磁盘:

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

我们使用Keras和TensorFlow训练我们的探测器


在执行train_covid19.py脚本之后,我们可以训练自动检测器。

下载源代码,数据集和预训练的模型。打开终端并运行命令来训练检测器:

$ 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...

自动X射线诊断


注意:在本部分中,我们不会“解决”确定COVID-19的问题。它是在当前情况下编写的,仅用于教育目的。这是计算机视觉和深度学习的实际应用示例,因此您可以适应不同的指标,包括通常的准确性,敏感性和特异性(以及处理医学数据时必须考虑的权衡)。我再说一遍,我们不能解决确定COVID-19 问题。

因此,我们的自动检测器X射线图像样本上显示的精度约为90-92%。没有其他信息用于训练模型,包括地理位置,人口密度等。 我们还收到了

敏感性为100%特异性为80%,这意味着:

  • 在这些患者中 COVID-19(真阳性病例),利用该模型,我们能够准确地识别为案件100%“COVID-19阳性”。
  • 没有 COVID-19阴性的患者(真正的阴性病例)中,使用该模型,我们仅能将80%的病例准确地识别为“ COVID-19阴性”。

如训练历史图所示,尽管训练数据的大小非常小,但并未对神经网络进行再训练:


图3:此准确性和损失图表明我们的模型未经过重新训练。

我们在检测COVID-19时达到了100%的准确性,这非常好。但是,真正消极情况的情况令人尴尬:我们不想将实际上是“ COVID-19阳性”的人归因于“ COVID-19阴性”。

我们最不希望让患病的患者与家人和朋友一起回家,为疾病的进一步传播做出贡献。

您还需要非常小心假阳性病例:我们不想误认为某人有病,并将其与其他患者隔离,以使他被其他人感染

在敏感性和特异性之间找到平衡-这是一项极为艰巨的任务,尤其是在药物方面,尤其是在迅速传播传染病方面。

在谈到医疗计算机视觉和深度学习时,您应该始终记住,我们的预测模型可能会产生非常严重的后果:错误的诊断可能会导致生命损失

我再说一遍,本文中的结果仅供参考这不是期刊出版物,该数据不符合发布预测模型TRIPOD标准

局限性,改进和进一步工作



图4:如今,人工智能和深度学习专业人员缺乏高质量的COVID-19数据来有效地训练自动图像识别系统。

本手册中描述的方法的主要限制之一是数据。

我们没有足够的(可靠)数据来训练COVID-19检测器。

医院已经有许多关于这种病毒的病史,但是鉴于隐私和人权,从医学图像快速组装高质量数据集变得更加困难。我相信在接下来的12-18个月中,我们将获得更多质量数据。但是就目前而言,您必须使用现有的东西。

我尝试在有限的时间和资源条件下(考虑到我的身体和精神状况)为有兴趣使用计算机视觉和深度学习的人编写本指南。但是,请允许我提醒您,我不是专业医生

为了在现实生活中使用COVID-19检测器,必须由与深度学习专家携手合作的真正医生进行严格的测试。我描述的方法不适用于此方法。

此外,必须谨慎对待模型“学习”的内容。

正如我在Grad-CAM手册中所写,该模型很可能会学习与COVID-19不相关的模式,但只能区分两个数据样本(即阳性和阴性诊断)。我们检测器的结果将需要由医生严格测试和检查。

最后,未来的(和更高级的)检测器将是多峰的。

现在,我们仅使用视觉数据(X射线)。更好的检测器应使用其他数据:患者生命指标,人口密度,地理位置等。仅凭视觉数据通常不足以满足此类任务

由于这些原因,我想再次强调:本指南仅起培训材料的作用-不能视为可靠的COVID-19检测器。

如果您认为自己或接近COVID-19的人,请遵循医疗保健系统的建议。

希望本指南对您有所帮助。我也希望这对某人来说是寻找使用计算机视觉和深度学习自动确定COVID-19的方法的起点。

摘要


在本指南中,您学习了如何使用Keras,TensorFlow和深度学习在X射线图像的数据集上创建COVID-19自动检测器。

到目前为止,该疾病还没有高质量且经过验证的图像数据集,因此您必须使用Joseph Cohen存储库


然后在Keras和TensorFlow的帮助下,我们训练了COVID-19检测器,该检测器在我们的测试样品上显示出90-92%准确度,灵敏度为100%,特异性为80%(在我们的小型数据集上)。

请记住,此处描述的检测器仅用于教育目的(请参见文本中的注释)。我想激发其他人使用深度学习,以表明将其与计算机视觉结合可以对我们的生活产生重大影响

我希望你喜欢它。

All Articles