65.9K
CodeProject 正在变化。 阅读更多。
Home

微调 ResNet50 以诊断 COVID-19

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2021年2月18日

CPOL

5分钟阅读

viewsIcon

10257

downloadIcon

112

在本文中,我们将微调我们的 ResNet50 模型。

在本系列文章中,我们将应用一个深度学习(DL)网络ResNet50,用于诊断胸部X光图像中的Covid-19。我们将使用Python的TensorFlow库在Jupyter Notebook上训练神经网络。

您需要用于此项目的工具和库是

IDE

我们假设您熟悉 Python 和 Jupyter Notebook 的深度学习。如果您是 Python 新手,请从本教程开始。如果您还不熟悉 Jupyter,请从这里开始

上一篇文章中,我们重构了 ResNet50 模型以适应新的分类任务——区分 COVID-19 和正常的胸部 X 光片。在本文中,我们将微调模型以实现预期的性能和准确性。

训练模型

在这个项目中,我们采用迁移学习来利用 ResNet50 在新的分类任务——检测 COVID-19——中的知识。迁移学习包括两个阶段:冻结和微调。

在冻结阶段,预训练模型的公开可用权重和学习到的参数被冻结并“按原样”使用。微调首先移除 ResNet50 的全连接层 (FC),并将其重构为三个全连接层,输出层有两个输出神经元,分别对应 COVID-19 和正常的胸部 X 光片。请注意,FC 层的权重在训练期间随机初始化。其余层的权重被冻结,以确保它们能有效地提取输入图像的高抽象特征,因为它们已经在 ImageNet 数据集上的数百万张图像上进行了训练。

该网络使用梯度下降优化的随机方法在 1,590 张图像上进行训练,每批迭代包含 64 张图像。读取训练数据以及数据选择的代码在本系列的第二篇文章中进行了讨论。

为了在训练期间最小化成本函数,全连接层的初始学习率和衰减因子分别设置为 0.0001 和 0.1。训练轮次数量的选择是一个复杂的问题:它直接与训练过程中的优化次数相关。如果训练轮次数量过多,网络可能会过拟合,性能下降。

为了避免过拟合,我们监控了验证图像上的误差和性能率。结果发现,ResNet50 在第 3 轮训练时达到了最高的训练准确率和最佳的泛化能力。表 1 显示,经过 3 轮训练后,网络的训练性能良好——准确率为 98.7%(图 6)。

 tf.keras.callbacks.EarlyStopping(
    monitor='val_loss', min_delta=0, patience=0, verbose=0,
    mode='auto', baseline=None, restore_best_weights=False
)

 model.compile(optimizer='sgd', loss='categorical_crossentropy', metrics=['accuracy'])
history = model.fit_generator(generator = train_generator, steps_per_epoch=train_generator.n//train_generator.batch_size, epochs = 3)

图 6:网络的训练过程

为了评估模型在训练期间的性能,我们绘制了准确率和损失随训练轮次数量的变化(图 7 和图 8)。

acc = history.history['accuracy']
loss = history.history['loss']
plt.figure()
plt.plot(acc, label='Training Accuracy')
plt.ylabel('Accuracy')
plt.title('Training Accuracy')
plt.figure()
plt.plot(loss, label='Training Loss')
plt.ylabel('Loss')
plt.title('Training Loss')
plt.xlabel('epoch')
plt.show()

图 7:训练准确率与训练轮次的关系

图 8:损失与训练轮次的关系

从图 7 和图 8 可以看出,随着训练轮次数量的增加,训练准确率增加,而训练损失在每个轮次都会减少。这正是运行梯度下降优化时应有的表现。换句话说,误差应该在每次迭代中都得到降低。

模型评估

模型以良好的准确率训练完成后,我们可以开始在测试数据集上对其进行测试,该数据集包含 895 张图像,不属于训练集。测试集在本系列的第二篇文章中已作为 test_generator 加载。

为了测试我们的模型,我们使用 model.evaluate 函数。此函数根据您传入的输入数据计算损失和准确率。我们将所有输入的测试数据作为 test_generator 传入并评估了模型。

Testresults = model.evaluate(test_generator)
print("test loss, test acc:", Testresults)

图 9:测试准确率的快照

如上图(图 9)所示,我们的模型在将新图像分类为 COVID-19 或正常方面表现出良好的泛化能力,准确率为 95%,测试损失为 0.108。

我们也可以使用 model.predict 函数来评估我们的模型。此函数与 model.evaluate 类似,不同之处在于它会生成您提供给模型的给定输入的预测输出。使用 model.predict 获取测试数据的全部预测。

predictions = model.predict(test_generator, batch_size=None, verbose=0, steps=None, callbacks=None)
print(predictions)

在获得 Softmax 函数生成的概率预测后,我们将这些预测四舍五入为 0 或 1。四舍五入后的输出存储在 classes 中,而实际输出存储在 test_generator.Labels 中。

# Generate arg maxes for predictions
classes = np.argmax(predictions, axis = 1)
print(classes)
print(test_generator.labels)

我们还使用 model.predict 对一张图像的类别进行了分类。我们首先使用以下命令打印了所有测试图像的类别:

print(test_generator.labels)

然后,我们选择了一张属于类别 0(COVID-19)的图像,并将其输入 model.predict

x=test_generator[5]
predictions = model.predict(x) 
print('First prediction:', predictions[0])
category = np.argmax(predictions[0], axis = 0)
print("the image class is:", category)

梯度权重类激活映射 (Grad-Cam)

为了更好地解释和评估所使用的模型,我们可以采用许多参数和指标,例如Grad-Cam。我们可视化了一些正确分类的 COVID-19 和正常测试图像的 Grad-Cam。

Grad-Cam 是一种方法,可以可视化网络为了分类特定图像而关注的区域的激活情况。与预测类别相关的可疑区域通过热图突出显示,其中最活跃的区域显示为深红色,激活程度最低的区域显示为深蓝色。

图 10 显示了一些被 ResNet50 正确分类的测试图像的 Grad-Cam。上排显示了正常样本,下排显示了 COVID-19 图像。请注意,我们在计算和绘制热图时使用了 OpenCV (CV2) 和 TensorFlow,因此需要导入 CV2。

我们选择了一些测试图像并计算了它们的 Grad_Cam。要处理其他图像,只需在 IMAGE_PATH 中更改图像名称即可。重要的是选择最后一个卷积层作为 LAYER_NAME 来研究模型在最后一个卷积层中可视化了什么,这有助于它做出最终决定。Class_INDEX 代表给定图像的类别,在本例中为 COVID-19(0)。

import cv2
IMAGE_PATH = r'C:\Users\abdul\Desktop\ContentLab\P1\archive\COVID-19 Radiography Database\test\NORMAL\NORMAL (2).png'
LAYER_NAME = 'conv5_block3_out'
CLASS_INDEX = 0
img = tf.keras.preprocessing.image.load_img(IMAGE_PATH, target_size=(224, 224))
img = tf.keras.preprocessing.image.img_to_array(img)

# Load initial model
model = model

# Create a graph that outputs target convolution and output
grad_model = tf.keras.models.Model([model.inputs], [model.get_layer(LAYER_NAME).output, model.output])

# Get the score for target class
with tf.GradientTape() as tape:
    conv_outputs, predictions = grad_model(np.array([img]))
    loss = predictions[:, CLASS_INDEX]

# Extract filters and gradients
output = conv_outputs[0]
grads = tape.gradient(loss, conv_outputs)[0]

# Average gradients spatially
weights = tf.reduce_mean(grads, axis=(0, 1))

# Build a ponderated map of filters according to gradients importance
cam = np.ones(output.shape[0:2], dtype=np.float32)

for index, w in enumerate(weights):
    cam += w * output[:, :, index]

# Heatmap visualization
cam = cv2.resize(cam.numpy(), (224, 224))
cam = np.maximum(cam, 0)
heatmap = (cam - cam.min()) / (cam.max() - cam.min())
cam = cv2.applyColorMap(np.uint8(255*heatmap), cv2.COLORMAP_JET)
output_image = cv2.addWeighted(cv2.cvtColor(img.astype('uint8'), cv2.COLOR_RGB2BGR), 0.5, cam, 1, 0)
plt.imshow(output_image, cmap='rainbow')

图 10:测试图像的热图

下一步

在下一篇文章中,我们将讨论我们模型实现的 COVID-19 检测结果,并将其与其他模型的 G结果进行比较。敬请关注!

© . All rights reserved.