MONAI入门介绍

MONAI入门介绍MONAI MedicalOpenN 是一个专注于医疗图像处理的深度学习框架

大家好,欢迎来到IT知识分享网。

MONAI入门介绍

​ MONAI (Medical Open Network for AI) 是一个专注于医疗图像处理的深度学习框架。下面我们将介绍如何使用 MONAI 进行数据预处理、DataLoader 构建、模型训练以及推理。

文档地址

https://docs.monai.io/en/1.3.1/transforms.html#dictionary-transforms

环境准备

​ 首先,确保安装了 MONAI 和其他必要的库:

pip install monai[all] torch torchvision numpy 
  • pip install monai[all]: 这个命令会使用 pip 安装 MONAI 库及其所有依赖项。方括号中的 all 表示安装 MONAI 的全部功能和依赖。MONAI 提供了许多预处理、数据加载、模型构建等用于医疗图像分析的工具和算法。
  • torch torchvision: 这会安装 PyTorch 深度学习框架及其图像处理库 torchvision。PyTorch 是一个广泛使用的深度学习框架,而 torchvision 则包含了一些常用的图像处理功能,如数据集加载、图像转换等。
  • numpy: 这是 Python 中用于科学计算的基础包,用来处理数组和矩阵数据。

导入必要的库

import os import numpy as np import torch from torch.utils.data import DataLoader from monai.transforms import ( Compose, LoadImaged, AddChanneld, ScaleIntensityd, ToTensord, RandRotate90d, RandFlipd, RandZoomd ) from monai.data import CacheDataset, Dataset, DataLoader from monai.networks.nets import UNet from monai.losses import DiceLoss from monai.metrics import DiceMetric from monai.utils import first from monai.inferers import sliding_window_inference import matplotlib.pyplot as plt 
  1. 导入库和模块:
    • import os: Python 的标准库,用于与操作系统交互,例如文件操作等。
    • import numpy as np: 用于数值计算的库,特别擅长处理数组和矩阵数据。
    • import torch: PyTorch 深度学习框架。
    • from torch.utils.data import DataLoader: PyTorch 中用于批处理和数据加载的工具。
    • from monai.transforms import ...: 导入 MONAI 中的数据转换操作,例如加载图像、添加通道、强度缩放、转换为张量等。
    • from monai.data import CacheDataset, Dataset, DataLoader: 导入 MONAI 中用于处理数据集的类,例如缓存数据集、普通数据集和数据加载器。
    • from monai.networks.nets import UNet: 导入 MONAI 中的 UNet 模型,用于图像分割任务。
    • from monai.losses import DiceLoss: 导入 MONAI 中的 Dice Loss,一种常用于图像分割任务的损失函数。
    • from monai.metrics import DiceMetric: 导入 MONAI 中的 Dice Metric,用于评估分割精度。
    • from monai.utils import first: 导入 MONAI 中的一个实用函数,用于获取迭代器的第一个元素。
    • from monai.inferers import sliding_window_inference: 导入 MONAI 中的滑动窗口推断方法,用于处理大尺寸图像。
  2. 示例中的转换操作(Transforms): 这些转换操作用于预处理和增强图像数据,以准备输入模型进行训练或推断。
    • Compose: 组合多个转换操作。
    • LoadImaged: 加载图像数据。
    • AddChanneld: 添加图像通道维度。
    • ScaleIntensityd: 缩放图像强度。
    • ToTensord: 将图像转换为 PyTorch 张量。
    • RandRotate90d, RandFlipd, RandZoomd: 随机旋转、翻转和缩放图像,用于数据增强。
  3. 其它模块和类:
    • UNet: MONAI 中的 UNet 模型,用于医学图像分割任务。
    • DiceLoss: MONAI 中实现的 Dice Loss 损失函数,用于监督学习中的图像分割损失计算。
    • DiceMetric: MONAI 中的 Dice Metric,用于评估分割精度。
    • sliding_window_inference: MONAI 中的滑动窗口推断方法,用于处理大尺寸图像的推断过程。
    • matplotlib.pyplot as plt: Matplotlib 库中的 pyplot 模块,用于绘制和显示图形。

数据预处理

使用 MONAI 的变换(Transforms)进行数据预处理:

# 定义数据预处理的变换 train_transforms = Compose([ LoadImaged(keys=['image', 'label']), AddChanneld(keys=['image', 'label']), ScaleIntensityd(keys=['image', 'label']), RandRotate90d(keys=['image', 'label'], prob=0.5), RandFlipd(keys=['image', 'label'], prob=0.5), RandZoomd(keys=['image', 'label'], prob=0.2, min_zoom=0.9, max_zoom=1.1), ToTensord(keys=['image', 'label']) ]) val_transforms = Compose([ LoadImaged(keys=['image', 'label']), AddChanneld(keys=['image', 'label']), ScaleIntensityd(keys=['image', 'label']), ToTensord(keys=['image', 'label']) ]) 
1.训练集部分:

LoadImaged(keys=['image', 'label']):

  • 加载图像和标签数据,假设数据中包含 ‘image’ 和 ‘label’ 这两类数据。

AddChanneld(keys=['image', 'label']):

  • 给 ‘image’ 和 ‘label’ 数据添加一个通道维度,通常是将灰度图像转换为 RGB 格式将单通道标签图像处理为多通道

ScaleIntensityd(keys=['image', 'label']):

  • 对 ‘image’ 和 ‘label’ 数据进行强度缩放,通常是将像素值缩放到一个固定范围,如 [0, 1] 或 [-1, 1]。

RandRotate90d(keys=['image', 'label'], prob=0.5):

  • 随机对 ‘image’ 和 ‘label’ 数据进行90度的旋转,概率为0.5,即每次旋转的概率为50%。

RandFlipd(keys=['image', 'label'], prob=0.5):

  • 随机对 ‘image’ 和 ‘label’ 数据进行水平或垂直翻转,概率为0.5,即每次翻转的概率为50%。

RandZoomd(keys=['image', 'label'], prob=0.2, min_zoom=0.9, max_zoom=1.1):

  • 随机对 ‘image’ 和 ‘label’ 数据进行缩放,缩放比例在 [0.9, 1.1] 范围内,概率为0.2,即每次缩放的概率为20%。

ToTensord(keys=['image', 'label']):

  • 将 ‘image’ 和 ‘label’ 数据转换为 PyTorch 张量,以便输入到深度学习模型中。
2.验证集部分:

LoadImaged(keys=['image', 'label']):

  • 同样,加载验证集中的图像和标签数据。

AddChanneld(keys=['image', 'label']):

  • 给图像和标签数据添加通道维度。

ScaleIntensityd(keys=['image', 'label']):

  • 对图像和标签数据进行强度缩放。

ToTensord(keys=['image', 'label']):

  • 将图像和标签数据转换为 PyTorch 张量。

构建 DataLoader

使用 MONAI 构建训练和验证的 DataLoader:

# 定义数据字典 train_files = [{ 
   'image': 'path/to/image1.nii', 'label': 'path/to/label1.nii'}, { 
   'image': 'path/to/image2.nii', 'label': 'path/to/label2.nii'}, ...] val_files = [{ 
   'image': 'path/to/image3.nii', 'label': 'path/to/label3.nii'}, ...] # 构建数据集 train_ds = CacheDataset(data=train_files, transform=train_transforms, cache_rate=1.0) val_ds = CacheDataset(data=val_files, transform=val_transforms, cache_rate=1.0) # 构建 DataLoader train_loader = DataLoader(train_ds, batch_size=2, shuffle=True, num_workers=4) val_loader = DataLoader(val_ds, batch_size=1, shuffle=False, num_workers=4) 
1.定义数据字典
  • train_files: 是一个列表,每个元素是一个字典,包含了训练集中每个样本的图像和对应的标签文件路径。例如,'image': 'path/to/image1.nii' 表示第一个样本的图像文件路径,'label': 'path/to/label1.nii' 表示对应的标签文件路径。
  • val_files: 类似于 train_files,包含了验证集中每个样本的图像和标签文件路径。
2.构建数据集

CacheDataset: 是 MONAI 中的一个数据集类,用于加载和管理数据。参数包括:

  • data: 数据字典列表,即 train_filesval_files
  • transform: 数据预处理变换,分别是 train_transformsval_transforms,用于对数据进行预处理。
  • cache_rate: 缓存率,设置为 1.0 表示缓存所有数据,可以加快训练速度。
3.构建DataLoader

DataLoader: 是 PyTorch 中的数据加载器,用于批量加载数据并提供数据的迭代器。参数包括:

  • train_dsval_ds: 分别是之前构建的训练集和验证集数据集对象。
  • batch_size: 每个批次的样本数,这里训练集设为 2,验证集设为 1
  • shuffle: 是否在每个 epoch 开始前打乱数据,训练集设为 True,验证集设为 False
  • num_workers: 加载数据时使用的子进程数,可以加速数据加载过程。

构建模型、损失函数和优化器

# 构建 UNet 模型 model = UNet( dimensions=3, in_channels=1, out_channels=2, channels=(16, 32, 64, 128, 256), strides=(2, 2, 2, 2), num_res_units=2 ).cuda() # 定义损失函数和优化器 loss_function = DiceLoss(to_onehot_y=True, softmax=True) optimizer = torch.optim.Adam(model.parameters(), 1e-4) 
1.构建 UNet 模型

UNet: 是 MONAI 中提供的 UNet 模型类,用于图像分割任务。

  • dimensions=3: 指定模型处理的数据维度数,这里是三维的医学图像数据。
  • in_channels=1: 输入图像的通道数,这里假设输入是单通道的灰度图像。
  • out_channels=2: 输出的通道数,通常用于分割任务,表示预测两类(如前景和背景)。
  • channels=(16, 32, 64, 128, 256): UNet 模型中各个层级的通道数设置,从浅层到深层依次增加。
  • strides=(2, 2, 2, 2): UNet 模型中各个层级的步长设置,决定了每个池化操作的缩减程度。
  • num_res_units=2: UNet 模型中每个层级的残差单元数,用于增强模型学习能力和稳定性。

.cuda(): 将模型移动到 GPU 上进行加速计算,如果没有 GPU,则不需要这一步。

2.定义损失函数和优化器

DiceLoss: 是 MONAI 中实现的 Dice Loss 损失函数,常用于图像分割任务。

  • to_onehot_y=True: 表示将输入的标签转换为 one-hot 编码形式,用于计算 Dice Loss。
  • softmax=True: 表示在计算 Dice Loss 之前对模型的输出进行 softmax 操作。

torch.optim.Adam(model.parameters(), 1e-4): 使用 Adam 优化器来优化模型参数。

  • model.parameters(): 获取模型中所有需要训练的参数。
  • 1e-4: Adam 优化器的学习率,这里设置为 0.0001。

训练模型

定义训练和验证过程:

# 训练和验证过程 max_epochs = 100 val_interval = 2 dice_metric = DiceMetric(include_background=True, reduction="mean", get_not_nans=False) best_metric = -1 best_metric_epoch = -1 epoch_loss_values = [] metric_values = [] for epoch in range(max_epochs): print("-" * 10) print(f"epoch { 
     epoch + 1}/{ 
     max_epochs}") model.train() epoch_loss = 0 step = 0 for batch_data in train_loader: step += 1 inputs, labels = batch_data["image"].cuda(), batch_data["label"].cuda() optimizer.zero_grad() outputs = model(inputs) loss = loss_function(outputs, labels) loss.backward() optimizer.step() epoch_loss += loss.item() epoch_loss /= step epoch_loss_values.append(epoch_loss) print(f"epoch { 
     epoch + 1} average loss: { 
     epoch_loss:.4f}") if (epoch + 1) % val_interval == 0: model.eval() with torch.no_grad(): metric = 0 metric_count = 0 for val_data in val_loader: val_inputs, val_labels = val_data["image"].cuda(), val_data["label"].cuda() val_outputs = sliding_window_inference(val_inputs, (96, 96, 96), 4, model) value = dice_metric(y_pred=val_outputs, y=val_labels) metric += value.item() metric_count += 1 metric /= metric_count metric_values.append(metric) if metric > best_metric: best_metric = metric best_metric_epoch = epoch + 1 torch.save(model.state_dict(), "best_metric_model.pth") print(f"current epoch: { 
     epoch + 1} current mean dice: { 
     metric:.4f}") print(f"best mean dice: { 
     best_metric:.4f} at epoch: { 
     best_metric_epoch}") 

​ 这段代码实现了一个简单的 UNet 模型的训练和验证过程。通过循环迭代每个 epoch,在每个 epoch 中进行训练和验证操作。训练阶段通过计算损失函数并优化模型参数,验证阶段通过评估指标(这里是 Dice 系数)来评估模型的性能,并记录最佳指标及其对应的模型状态。这种训练和验证的循环过程可以帮助优化模型,并监控模型在验证集上的表现。

1.设置训练参数和评估指标
  • max_epochs: 总的训练轮数,这里设置为 100。
  • val_interval: 每隔多少个 epoch 进行一次验证集的评估,这里设置为 2。
  • dice_metric: DiceMetric 是 MONAI 中用于计算 Dice 系数的类。
    • include_background=True: 包括背景类在内的所有类别。
    • reduction="mean": 计算 Dice 系数的方式为取平均值。
    • get_not_nans=False: 在计算 Dice 系数时不考虑 NaN 值。
2.初始化训练过程的变量和数据结构
  • best_metric: 记录最佳的评估指标(这里是 Dice 系数),初始化为 -1。
  • best_metric_epoch: 记录达到最佳指标时的 epoch 数,初始化为 -1。
  • epoch_loss_values: 记录每个 epoch 的平均损失值。
  • metric_values: 记录每个验证阶段的评估指标(这里是 Dice 系数)。
3.主训练循环
  • for epoch in range(max_epochs): 开始迭代每个 epoch。
4.训练阶段
  • model.train(): 将模型设置为训练模式,启用 Batch Normalization 和 Dropout 等。
  • train_loader: 是之前定义的训练集 DataLoader,用于批量加载训练数据。
  • 循环遍历每个 batch 的数据,将数据和标签移动到 GPU 上,通过前向传播计算输出并计算损失,然后反向传播更新模型参数。
  • epoch_loss /= step: 计算当前 epoch 的平均损失,并将其添加到 epoch_loss_values 列表中。
5.验证阶段
  • (epoch + 1) % val_interval == 0: 每隔 val_interval 个 epoch 执行一次验证阶段。
  • model.eval(): 将模型设置为评估模式,此时不会启用 Batch Normalization 和 Dropout 等。
  • torch.no_grad(): 在评估阶段,不需要计算梯度,因此使用 torch.no_grad() 块以减少内存消耗和加速计算。
  • sliding_window_inference(val_inputs, (96, 96, 96), 4, model): 使用滑动窗口推断方法对验证集数据进行预测。
  • dice_metric(y_pred=val_outputs, y=val_labels): 计算预测输出和真实标签之间的 Dice 系数。
  • 计算并记录当前 epoch 的 Dice 系数,并更新 metric_values 列表。
  • 如果当前 epoch 的 Dice 系数优于历史最佳指标 best_metric,则更新 best_metricbest_metric_epoch,并保存模型的状态字典到文件 “best_metric_model.pth”。
  • 打印当前 epoch 的评估结果和历史最佳指标。

推理

使用训练好的模型进行推理:

# 加载最佳模型 model.load_state_dict(torch.load("best_metric_model.pth")) # 进行推理 model.eval() with torch.no_grad(): for i, test_data in enumerate(val_loader): test_images, test_labels = test_data["image"].cuda(), test_data["label"].cuda() test_outputs = sliding_window_inference(test_images, (96, 96, 96), 4, model) test_outputs = torch.argmax(test_outputs, dim=1).detach().cpu().numpy() # 可视化推理结果 plt.figure("check", (18, 6)) plt.subplot(1, 3, 1) plt.title("image") plt.imshow(test_images[0, 0, :, :, 50].cpu(), cmap="gray") plt.subplot(1, 3, 2) plt.title("label") plt.imshow(test_labels[0, 0, :, :, 50].cpu()) plt.subplot(1, 3, 3) plt.title("output") plt.imshow(test_outputs[0, :, :, 50]) plt.show() 

​ 这段代码加载了经过训练和验证的最佳模型,并使用该模型对验证集或测试集的数据进行推理。推理过程中,首先将模型设置为评估模式,然后通过滑动窗口推断方法对每个数据样本进行预测,最后将预测结果和真实标签进行可视化展示。这种推理和可视化过程有助于直观地理解模型在图像分割任务中的表现和效果。

1.加载最佳模型
  • torch.load("best_metric_model.pth"): 使用 PyTorch 的 torch.load 函数加载之前保存的最佳模型的状态字典。这个文件路径 "best_metric_model.pth" 需要根据你实际保存的模型文件名来指定。
  • model.load_state_dict(): 将加载的模型状态字典加载到预先定义的模型 model 中,以恢复训练时的模型参数和状态。
2.进行推理
  • model.eval(): 将模型设置为评估模式,确保在推理过程中不启用 Dropout 和 Batch Normalization。
  • torch.no_grad(): 在推理过程中不需要计算梯度,使用 torch.no_grad() 上下文管理器以减少内存消耗和加速计算。
  • val_loader: 是之前定义的验证集 DataLoader,用于批量加载验证集数据。
  • sliding_window_inference(test_images, (96, 96, 96), 4, model): 使用滑动窗口推断方法对验证集或测试集数据进行预测。这里的参数 (96, 96, 96) 表示滑动窗口的大小,4 表示滑动窗口的步长。
  • torch.argmax(test_outputs, dim=1): 对模型输出的概率分布取最大值的索引,得到预测的类别标签。
  • .detach().cpu().numpy(): 将张量从 GPU 转移到 CPU,并转换为 NumPy 数组,以便后续的可视化处理。
3.可视化推理结果
  • plt.figure("check", (18, 6)): 创建一个名为 “check” 的图形窗口,大小为 (18, 6) 英寸。
  • plt.subplot(1, 3, 1): 将窗口分成一行三列,当前操作在第一列中。
  • plt.title("image"): 设置第一列的标题为 “image”。
  • plt.imshow(test_images[0, 0, :, :, 50].cpu(), cmap="gray"): 显示测试图像的切片(在这里是第 50 层),使用灰度颜色映射显示。
  • plt.subplot(1, 3, 2): 切换到第二列,用于显示真实标签。
  • plt.title("label"): 设置第二列的标题为 “label”。
  • plt.imshow(test_labels[0, 0, :, :, 50].cpu()): 显示真实标签的切片图像。
  • plt.subplot(1, 3, 3): 切换到第三列,用于显示模型预测结果。
  • plt.title("output"): 设置第三列的标题为 “output”。
  • plt.imshow(test_outputs[0, :, :, 50]): 显示模型预测输出的切片图像。
  • plt.show(): 显示所有子图。

​ 以上代码展示了如何使用 MONAI 进行数据预处理、DataLoader 构建、模型训练以及推理。根据具体任务和数据集,可以调整变换、模型参数以及训练过程中的细节。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/132695.html

(0)
上一篇 2025-07-29 17:00
下一篇 2025-07-29 17:10

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信