【机器学习实战入门】基于深度学习的乳腺癌分类

什么是深度学习?

作为对机器学习的一种深入方法,深度学习受到了人类大脑和其生物神经网络的启发。它包括深层神经网络、递归神经网络、卷积神经网络和深度信念网络等架构,这些架构由多层组成,数据必须通过这些层才能最终产生输出。深度学习旨在改进人工智能并使许多应用成为可能;它被应用于计算机视觉、语音识别、自然语言处理、音频识别和药物设计等多个领域。

什么是 Keras?

Keras 是一个用 Python 编写的开源神经网络库。它是一个高级 API,并可以在 TensorFlow、CNTK 和 Theano 上运行。Keras 专注于支持快速实验和原型设计,同时在 CPU 和 GPU 上无缝运行。它用户友好、模块化且可扩展。

乳腺癌分类 -- 目标

我们将在一个 IDC 数据集上构建一个乳腺癌分类器,可以准确地将组织学图像分类为良性或恶性。

关于 Python 项目 -- 乳腺癌分类

在这个 Python 项目中,我们将构建一个分类器,以 80% 的乳腺癌组织学图像数据集进行训练。其中,我们将保留 10% 的数据用于验证。使用 Keras,我们将定义一个 CNN(卷积神经网络),并将其命名为 CancerNet,然后在我们的图像上进行训练。最后,我们将构建一个混淆矩阵来分析模型的性能。

IDC 是浸润性导管癌;这是一种在乳管中开始并在管外侵犯乳腺纤维或脂肪组织的癌症;它是最常见的乳腺癌形式,占所有乳腺癌诊断的 80%。而组织学是研究组织微观结构的学科。

数据集

我们将使用来自 Kaggle 的 IDC_regular 数据集(乳腺癌组织学图像数据集)。这个数据集包含从 162 份乳腺癌整体装片扫描图像中提取的 277524 个 50x50 尺寸的图像块。其中有 198738 个测试结果为 IDC 阴性,78786 个测试结果为 IDC 阳性。数据集公开发布,你可以在这里下载。为此,你需要至少 3.02GB 的磁盘空间。

此数据集中的文件名如下:

8863_idx5_x451_y1451_class0

这里,8863_idx5 是患者编号,451 和 1451 是裁剪图像的 x 和 y 坐标,0 是类别标签(0 表示 IDC 缺失)。

链接: 基于深度学习的乳腺癌分类 源代码与数据集

前提条件

你需要安装一些 Python 包才能运行这个高级 Python 项目。你可以使用 pip 安装:

pip install numpy opencv-python pillow tensorflow keras imutils scikit-learn matplotlib

高级 Python 项目 -- 乳腺癌分类的步骤

  1. 下载压缩包。在你选择的位置解压缩它,并进入该位置。

乳腺癌检测 Python 项目

  1. 现在,在内部的 breast-cancer-classification 目录中,创建目录 datasets- 在此目录下,创建目录 original:
bash 复制代码
mkdir datasets
mkdir datasets\original
  1. 下载数据集。

  2. 在 original 目录中解压缩数据集。为了观察该目录的结构,我们将使用 tree 命令:

bash 复制代码
cd breast-cancer-classification\breast-cancer-classification\datasets\original
tree

项目中的原始结构

我们为每个患者编号有一个目录。在每个这样的目录中,我们有存放良性和恶性图像的 0 和 1 目录。

config.py:

这里包含了一些我们构建数据集和训练模型时所需的配置。你可以在 cancernet 目录中找到它。

python 复制代码
import os
INPUT_DATASET = "datasets/original"
BASE_PATH = "datasets/idc"
TRAIN_PATH = os.path.sep.join([BASE_PATH, "training"])
VAL_PATH = os.path.sep.join([BASE_PATH, "validation"])
TEST_PATH = os.path.sep.join([BASE_PATH, "testing"])
TRAIN_SPLIT = 0.8
VAL_SPLIT = 0.1

在这里,我们声明了原始数据集的路径(datasets/original),新目录的路径(datasets/idc),以及使用基本路径声明的训练、验证和测试目录的路径。我们还声明 80% 的整个数据集将用于训练,而其中的 10% 将用于验证。

build_dataset.py:

此脚本将根据上述比例将数据集分割为训练集、验证集和测试集- 80% 用于训练(其中 10% 用于验证),20% 用于测试。使用 Keras 的 ImageDataGenerator,我们将提取图像批处理,以避免一次性将整个数据集加载到内存中。

python 复制代码
from cancernet import config
from imutils import paths
import random, shutil, os
originalPaths=list(paths.list_images(config.INPUT_DATASET))
random.seed(7)
random.shuffle(originalPaths)
index=int(len(originalPaths)*config.TRAIN_SPLIT)
trainPaths=originalPaths[:index]
testPaths=originalPaths[index:]
index=int(len(trainPaths)*config.VAL_SPLIT)
valPaths=trainPaths[:index]
trainPaths=trainPaths[index:]
datasets=[("training", trainPaths, config.TRAIN_PATH),
          ("validation", valPaths, config.VAL_PATH),
          ("testing", testPaths, config.TEST_PATH)
]
for (setType, originalPaths, basePath) in datasets:
        print(f'Building {setType} set')
        if not os.path.exists(basePath):
                print(f'Building directory {basePath}')
                os.makedirs(basePath)
        for path in originalPaths:
                file=path.split(os.path.sep)[-1]
                label=file[-5:-4]
                labelPath=os.path.sep.join([basePath,label])
                if not os.path.exists(labelPath):
                        print(f'Building directory {labelPath}')
                        os.makedirs(labelPath)
                newPath=os.path.sep.join([labelPath, file])
                shutil.copy2(path, newPath)

机器学习 Python 项目

在此脚本中,我们将从 config、imutils、random、shutil 和 os 导入。我们构建一个原始图像路径的列表,然后将列表打乱。接着,我们通过将列表长度乘以 0.8 来计算索引,以便可以截取该列表以创建训练和测试数据集的子列表。然后,我们进一步计算索引,将训练数据集的 10% 用于验证,剩下的用于训练自己。

现在,datasets 是一个包含训练集、验证集和测试集信息的列表。这些信息包括路径和基本路径。对于此列表中的每个 set 类型、路径和基本路径,我们将打印如'构建测试集'。如果基本路径不存在,我们将创建目录。对于 originalPaths 中的每个路径,我们将提取文件名和类别标签。然后,我们将构建标签目录(0 或 1)的路径-如果它还不存在,我们将明确创建该目录。现在,我们将构建目标图像的路径并将其复制到这里-它所属的位置。

  1. 运行脚本 build_dataset.py:
bash 复制代码
py build_dataset.py

构建数据集

cancernet.py:

我们将构建的网络是一个 CNN(卷积神经网络),并命名为 CancerNet。该网络执行以下操作:

  • 使用 3x3 CONV 滤波器
  • 将这些滤波器堆叠在一起
  • 执行最大池化
  • 使用深度分离卷积(更高效,占用较少内存)
python 复制代码
from keras.models import Sequential
from keras.layers.normalization import BatchNormalization
from keras.layers.convolutional import SeparableConv2D
from keras.layers.convolutional import MaxPooling2D
from keras.layers.core import Activation
from keras.layers.core import Flatten
from keras.layers.core import Dropout
from keras.layers.core import Dense
from keras import backend as K
class CancerNet:
  @staticmethod
  def build(width,height,depth,classes):
    model=Sequential()
    shape=(height,width,depth)
    channelDim=-1
    if K.image_data_format()=="channels_first":
      shape=(depth,height,width)
      channelDim=1
    model.add(SeparableConv2D(32, (3,3), padding="same",input_shape=shape))
    model.add(Activation("relu"))
    model.add(BatchNormalization(axis=channelDim))
    model.add(MaxPooling2D(pool_size=(2,2)))
    model.add(Dropout(0.25))
    model.add(SeparableConv2D(64, (3,3), padding="same"))
    model.add(Activation("relu"))
    model.add(BatchNormalization(axis=channelDim))
    model.add(SeparableConv2D(64, (3,3), padding="same"))
    model.add(Activation("relu"))
    model.add(BatchNormalization(axis=channelDim))
    model.add(MaxPooling2D(pool_size=(2,2)))
    model.add(Dropout(0.25))
    model.add(SeparableConv2D(128, (3,3), padding="same"))
    model.add(Activation("relu"))
    model.add(BatchNormalization(axis=channelDim))
    model.add(SeparableConv2D(128, (3,3), padding="same"))
    model.add(Activation("relu"))
    model.add(BatchNormalization(axis=channelDim))
    model.add(SeparableConv2D(128, (3,3), padding="same"))
    model.add(Activation("relu"))
    model.add(BatchNormalization(axis=channelDim))
    model.add(MaxPooling2D(pool_size=(2,2)))
    model.add(Dropout(0.25))
    model.add(Flatten())
    model.add(Dense(256))
    model.add(Activation("relu"))
    model.add(BatchNormalization())
    model.add(Dropout(0.5))
    model.add(Dense(classes))
    model.add(Activation("softmax"))
    return model


在本脚本中,我们使用 Sequential API 构建 CancerNet,并使用 SeparableConv2D 实现深度卷积。CancerNet 类有一个静态方法 build,它接受四个参数- 图像的宽度和高度、深度(每个图像的颜色通道数)以及网络将在其间预测的类别数,对于我们来说,这一数字为 2(0 和 1)。

在此方法中,我们初始化 model 和 shape。使用 channels_first 时,我们更新 shape 和通道维度。

现在,我们将定义三个 DEPTHWISE_CONV => RELU => POOL 层;每一层都有更高的堆叠和更多的滤波器。softmax 分类器输出每个类别的预测百分比。最后,我们返回模型。

train_model.py:

此脚本用于训练和评估我们的模型。在这里,我们将从 keras、sklearn、cancernet、config、imutils、matplotlib、numpy 和 os 导入。

python 复制代码
import matplotlib
matplotlib.use("Agg")
from keras.preprocessing.image import ImageDataGenerator
from keras.callbacks import LearningRateScheduler
from keras.optimizers import Adagrad
from keras.utils import np_utils
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from cancernet.cancernet import CancerNet
from cancernet import config
from imutils import paths
import matplotlib.pyplot as plt
import numpy as np
import os
NUM_EPOCHS=40; INIT_LR=1e-2; BS=32
trainPaths=list(paths.list_images(config.TRAIN_PATH))
lenTrain=len(trainPaths)
lenVal=len(list(paths.list_images(config.VAL_PATH)))
lenTest=len(list(paths.list_images(config.TEST_PATH)))
trainLabels=[int(p.split(os.path.sep)[-2]) for p in trainPaths]
trainLabels=np_utils.to_categorical(trainLabels)
classTotals=trainLabels.sum(axis=0)
classWeight=classTotals.max()/classTotals
trainAug = ImageDataGenerator(
  rescale=1/255.0,
  rotation_range=20,
  zoom_range=0.05,
  width_shift_range=0.1,
  height_shift_range=0.1,
  shear_range=0.05,
  horizontal_flip=True,
  vertical_flip=True,
  fill_mode="nearest")
valAug=ImageDataGenerator(rescale=1 / 255.0)
trainGen = trainAug.flow_from_directory(
  config.TRAIN_PATH,
  class_mode="categorical",
  target_size=(48,48),
  color_mode="rgb",
  shuffle=True,
  batch_size=BS)
valGen = valAug.flow_from_directory(
  config.VAL_PATH,
  class_mode="categorical",
  target_size=(48,48),
  color_mode="rgb",
  shuffle=False,
  batch_size=BS)
testGen = valAug.flow_from_directory(
  config.TEST_PATH,
  class_mode="categorical",
  target_size=(48,48),
  color_mode="rgb",
  shuffle=False,
  batch_size=BS)
model=CancerNet.build(width=48,height=48,depth=3,classes=2)
opt=Adagrad(lr=INIT_LR,decay=INIT_LR/NUM_EPOCHS)
model.compile(loss="binary_crossentropy",optimizer=opt,metrics=["accuracy"])
M=model.fit_generator(
  trainGen,
  steps_per_epoch=lenTrain//BS,
  validation_data=valGen,
  validation_steps=lenVal//BS,
  class_weight=classWeight,
  epochs=NUM_EPOCHS)
print("Now evaluating the model")
testGen.reset()
pred_indices=model.predict_generator(testGen,steps=(lenTest//BS)+1)
pred_indices=np.argmax(pred_indices,axis=1)
print(classification_report(testGen.classes, pred_indices, target_names=testGen.class_indices.keys()))
cm=confusion_matrix(testGen.classes,pred_indices)
total=sum(sum(cm))
accuracy=(cm[0,0]+cm[1,1])/total
specificity=cm[1,1]/(cm[1,0]+cm[1,1])
sensitivity=cm[0,0]/(cm[0,0]+cm[0,1])
print(cm)
print(f'Accuracy: {accuracy}')
print(f'Specificity: {specificity}')
print(f'Sensitivity: {sensitivity}')
N = NUM_EPOCHS
plt.style.use("ggplot")
plt.figure()
plt.plot(np.arange(0,N), M.history["loss"], label="train_loss")
plt.plot(np.arange(0,N), M.history["val_loss"], label="val_loss")
plt.plot(np.arange(0,N), M.history["acc"], label="train_acc")
plt.plot(np.arange(0,N), M.history["val_acc"], label="val_acc")
plt.title("Training Loss and Accuracy on the IDC Dataset")
plt.xlabel("Epoch No.")
plt.ylabel("Loss/Accuracy")
plt.legend(loc="lower left")
plt.savefig('plot.png')





总结

在这个 Python 项目中,我们学习了如何使用 IDC 数据集(浸润性导管癌的组织学图像)构建一个乳腺癌分类器,并为此创建了 CancerNet 网络。我们使用 Keras 实现了这一点。希望你喜欢这个 Python 项目。

参考资料

资料名称 链接
Kaggle IDC 数据集 链接
Keras 文档 链接
TensorFlow 官方文档 链接
Python for Data Science Handbook 链接
PyImageSearch 深度学习教程 链接
《深度学习》 - Ian Goodfellow 链接
Medium 深度学习文章 链接
DataFlair Python 项目 链接
《利用深度学习对抗癌症》 -.scalatest 链接
维基百科 - 乳腺癌 链接
中国深度学习社区 链接
深度学习读书会 链接
Deep Learning Book by Yoshua Bengio 链接

关于数据集

背景

浸润性导管癌(IDC)是所有乳腺癌中最常见的亚型。为了对整个组织样本进行侵袭性分级,病理学家通常专注于包含 IDC 的区域。因此,自动侵袭性分级的常见预处理步骤之一是划定整个组织切片中 IDC 的确切区域。

内容

原始数据集包含 162 张乳腺癌(BCa)标本的整个组织切片图像,扫描倍率为 40 倍。从中提取了 277,524 个大小为 50 x 50 的 patches(198,738 个 IDC 阴性,78,786 个 IDC 阳性)。每个 patch 的文件名格式为:u_xX_yY_classC.png ------ 例如 10253_idx5_x1351_y1101_class0.png。其中,u 是患者 ID(10253_idx5),X 是该 patch 裁剪位置的 x 坐标,Y 是该 patch 裁剪位置的 y 坐标,C 表示类别,0 为非 IDC,1 为 IDC。

致谢

原始文件位于:http://gleason.case.edu/webdata/jpi-dl-tutorial/IDC_regular_ps50_idx5.zip

引用文献:https://www.ncbi.nlm.nih.gov/pubmed/27563488http://spie.org/Publications/Proceedings/Paper/10.1117/12.2043872

启发

乳腺癌是女性中最常见的癌症形式,而浸润性导管癌(IDC)是乳腺癌中最常见的类型。准确识别和分类乳腺癌亚型是一项重要的临床任务,自动化方法可用于节省时间并减少错误。

相关推荐
学习嵌入式的小羊~1 小时前
RV1126+FFMPEG推流项目(7)AI音频模块编码流程
人工智能·ffmpeg·音视频
程序猿阿伟2 小时前
《在ArkTS中实现模型的可视化调试和监控:探索与实践》
人工智能
算家云2 小时前
OpenAI推出首个AI Agent!日常事项自动化处理!
人工智能·自动化·openai·算家云·tasks
zfj3215 小时前
学英语学技术:Elasticsearch 线程池
大数据·elasticsearch·搜索引擎
白白糖6 小时前
深度学习 Pytorch 张量的索引、分片、合并以及维度调整
人工智能·pytorch·python·深度学习
白白糖6 小时前
深度学习 Pytorch 张量(Tensor)的创建和常用方法
人工智能·pytorch·python·深度学习
王子良.6 小时前
Hadoop 与 Spark:大数据处理的比较
大数据·hadoop·spark
Noos_7 小时前
AI面试官
人工智能
lovelin+v175030409667 小时前
从零到一:构建高效稳定的电商数据API接口
大数据·网络·人工智能·爬虫·python
深度学习实战训练营7 小时前
基于机器学习的电信用户流失预测与数据分析可视化
人工智能·机器学习·数据分析