深度学习与卷积神经网络在医学图像分析中的应用

深度学习作为一项强大的技术,已经在多个基础研究领域中找到了应用。尽管神经网络和深度学习已经存在一段时间,但由于数据不足,长期以来并没有受到太多关注。ImageNet的创建成为了深度学习和卷积神经网络进一步发展的主导力量。

资源推荐

实践学习CNN模型

在本文中,将采取实践的方法来学习并训练一个简单的CNN模型。将使用一个名为“胸部X光图像(肺炎)”的数据集,可以在Kaggle上找到这个数据集。在进行分析之前,让先了解一下肺炎是什么。

肺炎简介

肺炎是一种可能发生在任一侧肺部的感染。这种感染可能由多种原因引起,如细菌、病毒或真菌。感染导致肺泡充满脓液或液体,从而导致患者呼吸困难。

导入库

import numpy as np import pandas as pd import matplotlib.pyplot as plt import cv2 import random import os import glob from tqdm.notebook import tqdm import albumentations as A from tensorflow.keras.layers import Conv2D, Flatten, MaxPooling2D, Dense from tensorflow.keras.models import Sequential from tensorflow.keras.preprocessing.image import ImageDataGenerator

加载数据

将使用glob模块来加载训练、测试和验证数据集。

train_data = glob.glob('../input/chest-xray-pneumonia/chest_xray/train/**/*.jpeg') test_data = glob.glob('../input/chest-xray-pneumonia/chest_xray/test/**/*.jpeg') val_data = glob.glob('../input/chest-xray-pneumonia/chest_xray/val/**/*.jpeg')

创建一个函数来同时可视化多张图片,这将有助于后续的探索性数据分析(EDA)。

def plot_multiple_img(img_matrix_list, title_list, ncols, main_title=""): fig, myaxes = plt.subplots(figsize=(20, 15), nrows=3, ncols=ncols, squeeze=False) fig.suptitle(main_title, fontsize = 30) fig.subplots_adjust(wspace=0.3) fig.subplots_adjust(hspace=0.3) for i, (img, title) in enumerate(zip(img_matrix_list, title_list)): myaxes[i // ncols][i % ncols].imshow(img) myaxes[i // ncols][i % ncols].set_title(title, fontsize=15) plt.show()

数据分布

在开始EDA之前,让先看看数据中所有类别的分布情况。

DIR = "../input/chest-xray-pneumonia/chest_xray/" sets = ["train", "test", "val"] all_pneumonia = [] all_normal = [] for cat in sets: path = os.path.join(DIR, cat) norm = glob.glob(os.path.join(path, "NORMAL/*.jpeg")) pneu = glob.glob(os.path.join(path, "PNEUMONIA/*.jpeg")) all_normal.extend(norm) all_pneumonia.extend(pneu)

可以看到肺炎图像和正常图像之间存在明显的不平衡。如果在早期阶段没有检测到这个问题,模型将无法高效地执行。现在让继续进行EDA。

探索性数据分析(EDA)

随机打乱图像顺序。

random.shuffle(all_normal) random.shuffle(all_pneumonia) images = all_normal[:50] + all_pneumonia[:50]

查看X光图像。

fig=plt.figure(figsize=(15, 10)) columns = 4; rows = 5 for i in range(1, columns*rows +1): img = cv2.imread(images[i]) img = cv2.resize(img, (128, 128)) fig.add_subplot(rows, columns, i) plt.imshow(img) plt.axis(False)

现在尝试Ben Graham的方法。首先,将图像转换为灰度,然后应用高斯模糊。

fig=plt.figure(figsize=(15, 10)) columns = 4; rows = 2 for i in range(1, columns*rows +1): img = cv2.imread(images[i]) img = cv2.resize(img, (512, 512)) img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) img = cv2.addWeighted (img, 4, cv2.GaussianBlur(img, (0,0), 512/10), -4, 128) fig.add_subplot(rows, columns, i) plt.imshow(img) plt.axis(False)

现在,来研究像素分布。将为此使用傅里叶方法。

fig=plt.figure(figsize=(15, 10)) columns = 4; rows = 2 for i in range(1, columns*rows +1): img = cv2.imread(images[i]) img = cv2.resize(img, (512, 512)) img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) f = np.fft.fft2(img) fshift = np.fft.fftshift(f) magnitude_spectrum = 20*np.log(np.abs(fshift)) fig.add_subplot(rows, columns, i) plt.imshow(magnitude_spectrum) plt.axis(False)

所有这些图像可能看起来像是蓝色背景上的一堆绿点,但并非仅此而已。这些图像本质上是幅度谱,告诉大部分增长在哪里。

图像腐蚀:

fig=plt.figure(figsize=(15, 10)) columns = 5; rows = 2 for i in range(1, columns*rows +1): img = cv2.imread(images[i]) img = cv2.resize(img, (512, 512)) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) kernel = np.ones((5, 5), np.uint8) img_erosion = cv2.erode(img, kernel, iterations=3) fig.add_subplot(rows, columns, i) plt.imshow(img_erosion) plt.axis(False)

图像膨胀:

fig=plt.figure(figsize=(15, 10)) columns = 5; rows = 2 for i in range(1, columns*rows +1): img = cv2.imread(images[i]) img = cv2.resize(img, (512, 512)) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) kernel = np.ones((5, 5), np.uint8) img_erosion = cv2.dilate(img, kernel, iterations=3) fig.add_subplot(rows, columns, i) plt.imshow(img_erosion) plt.axis(False)

现在让使用OpenCV的Canny边缘检测:

fig=plt.figure(figsize=(15, 10)) columns = 5; rows = 2 for i in range(1, columns*rows +1): img = cv2.imread(images[i]) img = cv2.resize(img, (512, 512)) img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) edges = cv2.Canny(img, 80, 100) fig.add_subplot(rows, columns, i) plt.imshow(edges) plt.axis(False)

首先,使用Keras Image DataGenerator将数据分为训练集和验证集。

train_gen = ImageDataGenerator( rescale=1/255., horizontal_flip=True, vertical_flip=True, rotation_range=0.4, zoom_range=0.4 ) val_gen = ImageDataGenerator( rescale=1/255., ) Train = train_gen.flow_from_directory( "../input/chest-xray-pneumonia/chest_xray/train", target_size=(224, 224), batch_size=16 ) Test = train_gen.flow_from_directory( "../input/chest-xray-pneumonia/chest_xray/test", target_size=(224, 224), batch_size=8 )

现在是最有趣的部分。开始使用Keras Sequential API构建模型。这将是一个简单的CNN。将使用Rectifier Linear Unit作为激活函数。

model = Sequential() model.add(Conv2D(filters=128, kernel_size=(3,3), activation='relu', input_shape=(224, 224, 3))) model.add(MaxPooling2D(pool_size=(2,2))) model.add(Conv2D(filters=128, kernel_size=(3,3), activation='relu')) model.add(MaxPooling2D(pool_size=(2,2))) model.add(Conv2D(filters=64, kernel_size=(3,3), activation='relu')) model.add(MaxPooling2D(pool_size=(2,2))) model.add(Conv2D(filters=32, kernel_size=(3,3), activation='relu')) model.add(MaxPooling2D(pool_size=(2,2))) model.add(Flatten()) model.add(Dense(256, activation='relu')) model.add(Dense(128, activation='relu')) model.add(Dense(64, activation='relu')) model.add(Dense(2, activation='softmax'))

编译模型以查看其结构和参数。

model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy']) model.summary()

现在模型已经准备好了!让训练它20个周期,看看它的性能如何。将添加最后5个周期的截图:

hist = model.fit_generator( Train, epochs=20, validation_data=Test ) model.save("best_model.hdf5")

现在,让可视化模型的性能:

plt.style.use("classic") plt.figure(figsize=(16, 9)) plt.plot(hist.history['loss'], label="Train Loss") plt.plot(hist.history['val_loss'], label="Valid Loss") plt.legend() plt.xlabel("Epochs") plt.ylabel("Loss") plt.title("Loss over the Epochs") plt.show() plt.style.use("ggplot") plt.figure(figsize=(16, 9)) plt.plot(hist.history['accuracy'], label="Train Accuracy") plt.plot(hist.history['val_accuracy'], label="Valid Accuracy") plt.legend() plt.xlabel("Epochs") plt.ylabel("Accuracy") plt.title("Accuracy over the Epochs") plt.show()

如所见,模型可以提供近86%的准确率,这是相当可观的。因此,可以自信地在现实世界案例中使用这个模型来预测肺炎。

在本文中,学习了如何使用Keras库创建一个简单的CNN。在探索性数据分析中,主要使用了OpenCV库。首先,看到了数据在两个类别中的分布,并发现肺炎肺部的图像比正常图像多得多。首先随机打乱图像,以抵消拥有更多一种类型数据的影响。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485