深度学习作为机器学习的一个子集,已经在多个领域得到应用,帮助解决现有问题。在医学领域,深度学习对放射科医生尤其有益,因为手动分析工作需要很长时间。本文将讨论使用深度学习算法ResNet对疟疾感染血细胞进行分类的应用。这个应用可以在线公开访问,地址为:。本文使用的数据集来源于美国国立卫生研究院(NIH)的官方公共数据集,也可以通过Kaggle.com访问这个数据集。
在开始之前,需要导入所需的库。本文主要使用的库包括Keras作为机器学习库;Matplotlib作为可视化工具;Sklearn作为评估矩阵。以下是导入所需库的代码示例:
from keras.optimizers import Adam
from keras.models import Sequential
from keras.layers import Conv2D, MaxPool2D, Flatten, Dense, Dropout, Input, AveragePooling2D
from keras.preprocessing.image import ImageDataGenerator, img_to_array, load_img
from keras.applications import ResNet50V2
from keras.models import Model
%matplotlib inline
from matplotlib import pyplot as plt
from matplotlib import image as mpimg
from sklearn.metrics import confusion_matrix
import seaborn as sn
import numpy as np
首先,需要导入所需的库并加载数据集。以下是加载数据集的代码示例,它将图像数据集加载到环境中进行处理,并显示两个类别/分类类别,即未感染和寄生。使用的库包括Keras和NumPy作为深度学习库,Sklearn作为模型评估库,Matplotlib帮助可视化。以下是代码的输出,这两个文件夹名称表示类别名称。未感染代表健康/正常类别,而寄生是感染患者的类别。
import os
data_dir = "/kaggle/input/cell-images-for-detecting-malaria/cell_images/cell_images"
print(os.listdir(data_dir))
然后显示一个预加载的感染和健康细胞的图像,以确保加载的数据正确且适当。从每个类别中随机抽取一张图像进行显示。
img_path = "/kaggle/input/cell-images-for-detecting-malaria/cell_images/cell_images/Parasitized/C33P1thinF_IMG_20150619_114756a_cell_179.png"
gambar = mpimg.imread(img_path)
plt.imshow(gambar)
img_path2 = "/kaggle/input/cell-images-for-detecting-malaria/cell_images/cell_images/Uninfected/C1_thinF_IMG_20150604_104722_cell_60.png"
gambar2 = mpimg.imread(img_path2)
plt.imshow(gambar2)
在预处理阶段,将图像调整为128×128像素的尺寸,然后应用灰度处理。此外,还对数据集应用了图像增强。使用的增强包括旋转、缩放、宽度偏移、高度偏移、剪切和水平翻转。以下是预处理的代码示例:
dim = 128
batch = 32
datagen = ImageDataGenerator(rescale=1/255.0, validation_split=0.3,
rotation_range=20,
zoom_range=0.05,
width_shift_range=0.05,
height_shift_range=0.05,
shear_range=0.05,
horizontal_flip=True)
train_data = datagen.flow_from_directory(data_dir, target_size=(dim,dim), batch_size=batch, class_mode='categorical', subset='training')
validation_data = datagen.flow_from_directory(data_dir, target_size=(dim,dim), batch_size=batch, class_mode='categorical', subset='validation', shuffle=False)
使用的数据量为27,558,其中19,292个数据(70%)用于训练,8,266个数据(30%)用于测试或验证。
在这个阶段,构建模型。基础CNN架构使用ResNet-50。顾名思义,开发的模型有50个卷积层以及它们的池化层。在模型的末端,有两个全连接层。第一层由128个神经元组成,使用ReLU激活。第二层由2个神经元组成,代表分类类别的数量,使用softmax激活。在这两个全连接层之间,有一个dropout层,配置设置为50%。这个模型总共有23,827,330个参数/权重。这个模型使用在ImageNet数据集上预训练的模型进行迁移学习。以下是创建模型的代码示例:
baseModel = ResNet50V2(include_top=False,
input_tensor=Input(shape=(dim,dim, 3)))
headModel = baseModel.output
headModel = AveragePooling2D(pool_size=(4, 4))(headModel)
headModel = Flatten(name="flatten")(headModel)
headModel = Dense(128, activation="relu")(headModel)
headModel = Dropout(0.5)(headModel)
headModel = Dense(2, activation="softmax")(headModel)
model = Model(inputs=baseModel.input, outputs=headModel)
模型使用迁移学习从预训练的模型加速训练过程。输入图像进入卷积和池化层。这个卷积和池化层将被重复。在层之间,还有批量归一化用于调节,还有一个激活层。在ResNet模型中,有一个非常重要的层,即额外的层。这是前一个卷积层的残差之和在下一个卷积层上。这是ResNet的标志,也是深度学习领域的一次革命。
训练过程的配置如下:使用Adam优化器,二元交叉熵作为损失函数,因为只有两个类别要分类。以下是训练过程的代码示例:
EP = 30
model.compile(optimizer="adam", loss="binary_crossentropy", metrics=["accuracy"])
history = model.fit(train_data, validation_data=validation_data, epochs=EP)
print("*** 训练过程完成 ***")
训练过程包括验证数据,以便在评估步骤中跟踪过拟合。
以下是评估模型性能的代码示例,包括绘制训练和验证的损失和准确率图表,以及计算测试数据的准确率:
plt.style.use("ggplot")
plt.figure()
plt.plot(np.arange(0,EP), history.history["loss"], label="train_loss")
plt.plot(np.arange(0,EP), history.history["val_loss"], label="val_loss")
plt.plot(np.arange(0,EP), history.history["accuracy"], label="train_acc")
plt.plot(np.arange(0,EP), history.history["val_accuracy"], label="val_acc")
plt.title("训练损失和准确率")
plt.xlabel("周期 #")
plt.ylabel("损失/准确率")
plt.legend(loc="lower left")
test_loss, test_acc = model.evaluate(validation_data)
获得的准确率结果为测试数据的96.19%。在前面的图表中,可以看到训练和测试线非常接近,没有显示出任何过拟合。图表顶部的两条紫色线表示准确率,准确率看起来相对稳定且在增加。相比之下,图表底部的红色和蓝色线表示损失。
以下是使用混淆矩阵评估模型性能的代码示例,展示了模型对感染和正常图像的分类能力:
predictions = model.predict(validation_data)
y_pred = np.argmax(predictions, axis=-1)
cf_matrix = confusion_matrix(validation_data.classes, y_pred)
group_names = ["真正例", "假正例", "假负例", "真负例"]
group_counts = ["{0:0.0f}".format(value) for value in cf_matrix.flatten()]
group_percentages = ["{0:.2%}".format(value) for value in cf_matrix.flatten()/np.sum(cf_matrix)]
labels = [f"{v1}\n{v2}\n{v3}" for v1, v2, v3 in zip(group_names, group_counts, group_percentages)]
labels = np.asarray(labels).reshape(2,2)
categories = ["感染", "正常"]
sn.heatmap(cf_matrix, annot=labels, fmt='', xticklabels=categories, yticklabels=categories, cmap='Blues')
混淆矩阵显示模型能够很好地泛化,无论是对感染图像的分类还是对正常图像的分类。敏感性和特异性均匀分布。对感染和正常图像的错误预测也仅在2%的阈值。因此,可以得出结论,ResNet-50在疟疾图像分类中取得了良好的结果。
model.save('./cnn_malaria_binary.h5')