!git clone  https://github.com/PaddleCV-SIG/PaddleSeg3D.git

1. PaddleSeg3D

从这个工具的github地址https://github.com/PaddleCV-SIG/PaddleSeg3D.git ,可以看出是飞桨的兴趣小组(PPSIG,飞桨特殊兴趣小组)的CV小组开发和维护的。如果对飞桨的分割套件PaddleSeg熟悉的话,知道PaddleSeg目前支持都是2D分割,没有3D分割这方面的工具,不过有很多用户或者行业有3D分割的需求,特别医疗行业的用户。现在飞桨兴趣小组开发了PaddleSeg3D的3D分割工具,后面估计会整合到PaddleSeg分割套件中。

现在尝试用PaddleSeg3D这个工具搭建3D分割项目,分割自己的医疗数据。

PaddleSeg3D跟PaddleSeg很像的,用起来也很方便,但是就是对自己的医疗数据预处理没有提供太多的脚本,例如PaddleSeg3D中快速运行的教程中,是对新冠胸部CT的数据集进行肺部的分割,里面的预处理都是根据肺部“打量的”,还不支持nii后缀名的医疗格式,所以如果你要分割自己的数据,器官不是肺部的话,那需要自己写脚本。不过除自己需要对数据进行预处理外,后面的训练,就很方便,PaddleSeg3D提供一行代码就可以训练、验证、评估。

希望PaddleSeg3D可以尽快加入PaddleSeg开发套件中。

# 安装依赖
!pip install -r ./PaddleSeg3D/requirements.txt 
#解压数据
!unzip -o /home/aistudio/data/data129670/livers.zip -d /home/aistudio/PaddleSeg3D

2. 数据集介绍

这个项目主要分割肝脏和肿瘤,数据的模式是CT,属于薄层数据(体素约为0.7x0.7x0.7),在Z轴上可以达到500多层。通过ITK-SNAP中看到显示红色的是肝脏,显示绿色的是肿瘤。这个数据集一共有28例

#记得运行这行
%cd /home/aistudio/PaddleSeg3D/
/home/aistudio/PaddleSeg3D
#导入常用的库
import nibabel as nib
import SimpleITK as sitk
import matplotlib.pyplot as plt
import numpy as np
import os
from tqdm import tqdm

3. 对数据进行预处理

PaddleSeg3D的快速运行教程是分割胸部CT数据的肺部。对数据处理如下:
用nibabel读取医疗数据后,

if "nii.gz" in filename:
           f_np = nib.load(f).get_fdata(dtype=np.float32)

对CT值裁剪,然后对数据的Size 重采样到[128,128,128],再转换成numpy数据。

 preprocess=[
     HUNorm,
     functools.partial(
                    resample, new_shape=[128, 128, 128], order=1)
            ],
HUNorm默认是 HU_min=-1000, HU_max=600
#这个值范围类似肺窗

如果是分割自己的数据(不是分割肺部)是不能用它提供的脚本,假如你的医疗数据是nii的话,直接不支持读取(脚本没有把nii的格式写进去),而且使用nibabel来读取nii的话,图像会旋转90度,对CT值裁剪也是针对肺部的。因此最好自己写脚本预处理自己的数据。

因此对这个项目的肝脏数据,自己写脚本进行如下的预处理:

  1. 用SimpleITK读取.nii医疗数据,而且用SimpleITK不会出现用nibabel读取后会旋转90度
  2. 对数据统一方向,避免SimpleITK读取后,图像上下翻转(统一方向后,用nibabel还是会旋转90度)
  3. 对数据的CT值根据窗宽窗位进行裁剪
  4. 对数据的Size 进行重采样到[128,128,128]
  5. 转换成numpy(.npy)文件
"""
发现nibabel读取会旋转90度,SImpleITK会上下翻转,为了解决这个问题,需要对数据进行方向统一.
不过统不统一方向,nibabel都会旋转90度,而PaddleSeg3D也是刚好用这库处理医学数据转换成numpy,
所以转换numpy时,我不用这分割套件自带的脚本,自己用SImpleITK写一个。
"""

plt.figure(figsize=(10,5))

f_nib = nib.load("./livers/data/volume-2.nii").get_fdata(dtype=np.float32)
print(f"nibabel读取文件转换numpy后形状为x,y,z{f_nib.shape}")

f_sitk= sitk.GetArrayFromImage(sitk.ReadImage('./livers/data/volume-2.nii'))
print(f"SimpleITK读取文件转换numpy后形状为z,y,x{f_sitk.shape}")

plt.subplot(1,2,1),plt.imshow(f_nib[:,:,60],'gray'),plt.title("nibabel")
plt.subplot(1,2,2),plt.imshow(f_sitk[60,:,:],'gray'),plt.title("SimpleITK")
plt.show()

nibabel读取文件转换numpy后形状为x,y,z(512, 512, 158)
SimpleITK读取文件转换numpy后形状为z,y,x(158, 512, 512)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JDK9eHZW-1646469900138)(output_8_1.png)]

"""
读取nii文件后,设置统一的Direction,
"""
def reorient_image(image):
    """Reorients an image to standard radiology view."""
    dir = np.array(image.GetDirection()).reshape(len(image.GetSize()), -1)
    ind = np.argmax(np.abs(dir), axis=0)
    new_size = np.array(image.GetSize())[ind]
    new_spacing = np.array(image.GetSpacing())[ind]
    new_extent = new_size * new_spacing
    new_dir = dir[:, ind]

    flip = np.diag(new_dir) < 0
    flip_diag = flip * -1
    flip_diag[flip_diag == 0] = 1
    flip_mat = np.diag(flip_diag)

    new_origin = np.array(image.GetOrigin()) + np.matmul(new_dir, (new_extent * flip))
    new_dir = np.matmul(new_dir, flip_mat)

    resample = sitk.ResampleImageFilter()
    resample.SetOutputSpacing(new_spacing.tolist())
    resample.SetSize(new_size.tolist())
    resample.SetOutputDirection(new_dir.flatten().tolist())
    resample.SetOutputOrigin(new_origin.tolist())
    resample.SetTransform(sitk.Transform())
    resample.SetDefaultPixelValue(image.GetPixelIDValue())
    resample.SetInterpolator(sitk.sitkNearestNeighbor)

    return resample.Execute(image) 

for  f  in tqdm(os.listdir("./livers/data")) :
    d_path = os.path.join('./livers/data',f)
    seg_path = os.path.join('./livers/mask',f.replace("volume","segmentation"))
    d_sitkimg = sitk.ReadImage(d_path)
    d_sitkimg = reorient_image(d_sitkimg)

    seg_sitkimg = sitk.ReadImage(seg_path)
    seg_sitkimg = reorient_image(seg_sitkimg)

    sitk.WriteImage(d_sitkimg,d_path)
    sitk.WriteImage(seg_sitkimg,seg_path)
    
#统一方向后,再用SimpleITK读取,不再是上下翻转了,显示正常了
plt.figure(figsize=(10,5))
img= sitk.GetArrayFromImage(sitk.ReadImage('./livers/data/volume-2.nii'))
seg= sitk.GetArrayFromImage(sitk.ReadImage('./livers/mask/segmentation-2.nii'))
plt.subplot(1,2,1),plt.imshow(img[60,:,:],'gray'),plt.title("origin")
plt.subplot(1,2,2),plt.imshow(seg[60,:,:],'gray'),plt.title("mask")
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tHBMBSi0-1646469900138)(output_10_0.png)]

"""
对已经CT值裁剪和size重采样的数据转换成numpy并保存.npy文件
"""
from paddleseg3d.datasets.preprocess_utils import HUNorm, resample

dataset_root = "livers/"  
image_dir = os.path.join(dataset_root, "images") #images 不要改,存放转换后原始数据的npy文件
label_dir = os.path.join(dataset_root, "labels")  #labels 不要改,存放转换后的标签npy文件
os.makedirs(image_dir, exist_ok=True)
os.makedirs(label_dir, exist_ok=True)
ww = 350
wc = 80

for  f  in tqdm(os.listdir("./livers/data")) :
    d_path = os.path.join('./livers/data',f)
    seg_path = os.path.join('./livers/mask',f.replace("volume","segmentation"))
    d_img = sitk.GetArrayFromImage(sitk.ReadImage(d_path))
    d_img = HUNorm(d_img,HU_min=int(wc-int(ww/2)), HU_max=int(wc+int(ww/2)))
    d_img = resample(d_img,new_shape=[128, 128, 128], order=1).astype("float32")#new_shape=[z,y,x]

    seg_img = sitk.GetArrayFromImage(sitk.ReadImage(seg_path))
    seg_img = resample(seg_img,new_shape=[128, 128, 128], order=0).astype("int64")

    np.save(os.path.join(image_dir,f.split('.')[0]), d_img)
    np.save(os.path.join(label_dir,f.split('.')[0].replace("volume","segmentation")), seg_img)
# 划分数据集,训练集和测试集为8:2
import random
random.seed(1000)
path_origin = './livers/images/'
files = list(filter(lambda x: x.endswith('.npy'), os.listdir(path_origin)))
random.shuffle(files)
rate = int(len(files) * 0.8)#训练集和测试集8:2
train_txt = open('./livers/train_list.txt','w')
val_txt = open('./livers/val_list.txt','w')
for i,f in enumerate(files):
    image_path = os.path.join('images', f)
    label_path = image_path.replace("images", "labels").replace('volume','segmentation')
    if i < rate:
        train_txt.write(image_path + ' ' + label_path+ '\n')
    else:
        val_txt.write(image_path + ' ' + label_path+ '\n')
train_txt.close()
val_txt.close()

print('完成')
完成
"""
最后读取转换后的npy文件并展示,可见图像显示肝脏的窗宽窗位,形状大小也为128*128,数据都归一化到0到1之间
"""
data = np.load('livers/images/volume-0.npy')
print(data.shape)
print(np.max(data),np.min(data))#把数据归一化到0-1
img = data[60,:,:]
plt.imshow(img,'gray')
plt.show()
(128, 256, 256)
1.0 0.0

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OlK2aeyY-1646469900139)(output_13_1.png)]

4. 设置训练配置文件

PaddleSeg3D通过配置yaml文件来设置训练参数的。
这次训练用到的yaml文件内容如下:

data_root: livers/    #随便设置,只要是一个路径即可,因为dataset_root用来绝对路径

batch_size: 2
iters: 15000

train_dataset:
  type: LungCoronavirus    #不用管
  dataset_root: /home/aistudio/PaddleSeg3D/livers/    #这里用绝对路径省事好似
  result_dir: None    #目前好似没啥用
  transforms:
    - type: RandomResizedCrop3D    #随机缩放裁剪
      size: 128
      scale: [0.8, 1.4]
    - type: RandomRotation3D   #随机旋转
      degrees: 60    #旋转角度[-60 ,+60]度
    - type: RandomFlip3D  #  随机翻转
  mode: train    #训练模式
  num_classes: 3       #分割类别数(背景,肝脏,肿瘤)

val_dataset:
  type: LungCoronavirus
  dataset_root: /home/aistudio/PaddleSeg3D/livers/
  result_dir: None
  num_classes: 3
  transforms: []
  mode: val

optimizer:     #优化器设置
  type: sgd
  momentum: 0.9
  weight_decay: 1.0e-4

lr_scheduler:     #学习率设置
  type: PolynomialDecay
  decay_steps: 15000
  learning_rate: 0.0003
  end_lr: 0
  power: 0.9

loss:    #损失函数,交叉熵和dice结合一起用
  types:
    - type: MixedLoss
      losses:
        - type: CrossEntropyLoss
          weight: Null
        - type: DiceLoss
      coef: [1, 1]   #设置交叉熵和dice的权重
  coef: [1]

model:
  type: VNet    #目前只有Unet3d和Vnet两个3D分割网络选择
  elu: False
  in_channels: 1
  num_classes: 3
  pretrained: null

5. VNet

VNet是医疗3D分割网络,结构上也是采用U型结构。比起Unet3D,层内采用残差结构(第一个红框)。用卷积层替代池化层(第二个红框)。论文中也强调了Dice损失函数的作用

#打印vnet的网络结构

!python paddleseg3d/models/vnet.py
/home/aistudio/PaddleSeg3D/paddleseg3d/models/../../paddleseg3d/cvlibs/manager.py:118: UserWarning: VNet exists already! It is now updated to <class '__main__.VNet'> !!!
  component_name, component))
W0228 19:18:39.534801 27494 device_context.cc:447] Please NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 10.1, Runtime API Version: 10.1
W0228 19:18:39.538172 27494 device_context.cc:465] device: 0, cuDNN Version: 7.6.
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/nn/layer/norm.py:653: UserWarning: When training, we now always track global mean and variance.
  "When training, we now always track global mean and variance.")
out Tensor(shape=[1], dtype=float32, place=CUDAPlace(0), stop_gradient=False,
       [-0.45796004]) Tensor(shape=[1], dtype=float32, place=CUDAPlace(0), stop_gradient=True,
       [0.49996352])
-----------------------------------------------------------------------------------------------------------
   Layer (type)                      Input Shape                        Output Shape          Param #    
===========================================================================================================
     Conv3D-1                  [[1, 1, 128, 256, 256]]             [1, 16, 128, 256, 256]      2,016     
  BatchNorm3D-1               [[1, 16, 128, 256, 256]]             [1, 16, 128, 256, 256]       64       
     PReLU-1                  [[1, 16, 128, 256, 256]]             [1, 16, 128, 256, 256]       16       
InputTransition-1              [[1, 1, 128, 256, 256]]             [1, 16, 128, 256, 256]        0       
     Conv3D-2                 [[1, 16, 128, 256, 256]]             [1, 32, 64, 128, 128]       4,128     
  BatchNorm3D-2                [[1, 32, 64, 128, 128]]             [1, 32, 64, 128, 128]        128      
     PReLU-2                   [[1, 32, 64, 128, 128]]             [1, 32, 64, 128, 128]        32       
     Conv3D-3                  [[1, 32, 64, 128, 128]]             [1, 32, 64, 128, 128]      128,032    
  BatchNorm3D-3                [[1, 32, 64, 128, 128]]             [1, 32, 64, 128, 128]        128      
     PReLU-4                   [[1, 32, 64, 128, 128]]             [1, 32, 64, 128, 128]        32       
     LUConv-1                  [[1, 32, 64, 128, 128]]             [1, 32, 64, 128, 128]         0       
     PReLU-3                   [[1, 32, 64, 128, 128]]             [1, 32, 64, 128, 128]        32       
 DownTransition-1             [[1, 16, 128, 256, 256]]             [1, 32, 64, 128, 128]         0       
     Conv3D-4                  [[1, 32, 64, 128, 128]]              [1, 64, 32, 64, 64]       16,448     
  BatchNorm3D-4                 [[1, 64, 32, 64, 64]]               [1, 64, 32, 64, 64]         256      
     PReLU-5                    [[1, 64, 32, 64, 64]]               [1, 64, 32, 64, 64]         64       
     Conv3D-5                   [[1, 64, 32, 64, 64]]               [1, 64, 32, 64, 64]       512,064    
  BatchNorm3D-5                 [[1, 64, 32, 64, 64]]               [1, 64, 32, 64, 64]         256      
     PReLU-7                    [[1, 64, 32, 64, 64]]               [1, 64, 32, 64, 64]         64       
     LUConv-2                   [[1, 64, 32, 64, 64]]               [1, 64, 32, 64, 64]          0       
     Conv3D-6                   [[1, 64, 32, 64, 64]]               [1, 64, 32, 64, 64]       512,064    
  BatchNorm3D-6                 [[1, 64, 32, 64, 64]]               [1, 64, 32, 64, 64]         256      
     PReLU-8                    [[1, 64, 32, 64, 64]]               [1, 64, 32, 64, 64]         64       
     LUConv-3                   [[1, 64, 32, 64, 64]]               [1, 64, 32, 64, 64]          0       
     PReLU-6                    [[1, 64, 32, 64, 64]]               [1, 64, 32, 64, 64]         64       
 DownTransition-2              [[1, 32, 64, 128, 128]]              [1, 64, 32, 64, 64]          0       
     Conv3D-7                   [[1, 64, 32, 64, 64]]               [1, 128, 16, 32, 32]      65,664     
  BatchNorm3D-7                [[1, 128, 16, 32, 32]]               [1, 128, 16, 32, 32]        512      
     PReLU-9                   [[1, 128, 16, 32, 32]]               [1, 128, 16, 32, 32]        128      
   Dropout3D-3                 [[1, 128, 16, 32, 32]]               [1, 128, 16, 32, 32]         0       
     Conv3D-8                  [[1, 128, 16, 32, 32]]               [1, 128, 16, 32, 32]     2,048,128   
  BatchNorm3D-8                [[1, 128, 16, 32, 32]]               [1, 128, 16, 32, 32]        512      
     PReLU-11                  [[1, 128, 16, 32, 32]]               [1, 128, 16, 32, 32]        128      
     LUConv-4                  [[1, 128, 16, 32, 32]]               [1, 128, 16, 32, 32]         0       
     Conv3D-9                  [[1, 128, 16, 32, 32]]               [1, 128, 16, 32, 32]     2,048,128   
  BatchNorm3D-9                [[1, 128, 16, 32, 32]]               [1, 128, 16, 32, 32]        512      
     PReLU-12                  [[1, 128, 16, 32, 32]]               [1, 128, 16, 32, 32]        128      
     LUConv-5                  [[1, 128, 16, 32, 32]]               [1, 128, 16, 32, 32]         0       
    Conv3D-10                  [[1, 128, 16, 32, 32]]               [1, 128, 16, 32, 32]     2,048,128   
  BatchNorm3D-10               [[1, 128, 16, 32, 32]]               [1, 128, 16, 32, 32]        512      
     PReLU-13                  [[1, 128, 16, 32, 32]]               [1, 128, 16, 32, 32]        128      
     LUConv-6                  [[1, 128, 16, 32, 32]]               [1, 128, 16, 32, 32]         0       
     PReLU-10                  [[1, 128, 16, 32, 32]]               [1, 128, 16, 32, 32]        128      
 DownTransition-3               [[1, 64, 32, 64, 64]]               [1, 128, 16, 32, 32]         0       
    Conv3D-11                  [[1, 128, 16, 32, 32]]               [1, 256, 8, 16, 16]       262,400    
  BatchNorm3D-11                [[1, 256, 8, 16, 16]]               [1, 256, 8, 16, 16]        1,024     
     PReLU-14                   [[1, 256, 8, 16, 16]]               [1, 256, 8, 16, 16]         256      
   Dropout3D-4                  [[1, 256, 8, 16, 16]]               [1, 256, 8, 16, 16]          0       
    Conv3D-12                   [[1, 256, 8, 16, 16]]               [1, 256, 8, 16, 16]      8,192,256   
  BatchNorm3D-12                [[1, 256, 8, 16, 16]]               [1, 256, 8, 16, 16]        1,024     
     PReLU-16                   [[1, 256, 8, 16, 16]]               [1, 256, 8, 16, 16]         256      
     LUConv-7                   [[1, 256, 8, 16, 16]]               [1, 256, 8, 16, 16]          0       
    Conv3D-13                   [[1, 256, 8, 16, 16]]               [1, 256, 8, 16, 16]      8,192,256   
  BatchNorm3D-13                [[1, 256, 8, 16, 16]]               [1, 256, 8, 16, 16]        1,024     
     PReLU-17                   [[1, 256, 8, 16, 16]]               [1, 256, 8, 16, 16]         256      
     LUConv-8                   [[1, 256, 8, 16, 16]]               [1, 256, 8, 16, 16]          0       
     PReLU-15                   [[1, 256, 8, 16, 16]]               [1, 256, 8, 16, 16]         256      
 DownTransition-4              [[1, 128, 16, 32, 32]]               [1, 256, 8, 16, 16]          0       
   Dropout3D-5                  [[1, 256, 8, 16, 16]]               [1, 256, 8, 16, 16]          0       
   Dropout3D-6                 [[1, 128, 16, 32, 32]]               [1, 128, 16, 32, 32]         0       
Conv3DTranspose-1               [[1, 256, 8, 16, 16]]               [1, 128, 16, 32, 32]      262,272    
  BatchNorm3D-14               [[1, 128, 16, 32, 32]]               [1, 128, 16, 32, 32]        512      
     PReLU-18                  [[1, 128, 16, 32, 32]]               [1, 128, 16, 32, 32]        128      
    Conv3D-14                  [[1, 256, 16, 32, 32]]               [1, 256, 16, 32, 32]     8,192,256   
  BatchNorm3D-15               [[1, 256, 16, 32, 32]]               [1, 256, 16, 32, 32]       1,024     
     PReLU-20                  [[1, 256, 16, 32, 32]]               [1, 256, 16, 32, 32]        256      
     LUConv-9                  [[1, 256, 16, 32, 32]]               [1, 256, 16, 32, 32]         0       
    Conv3D-15                  [[1, 256, 16, 32, 32]]               [1, 256, 16, 32, 32]     8,192,256   
  BatchNorm3D-16               [[1, 256, 16, 32, 32]]               [1, 256, 16, 32, 32]       1,024     
     PReLU-21                  [[1, 256, 16, 32, 32]]               [1, 256, 16, 32, 32]        256      
    LUConv-10                  [[1, 256, 16, 32, 32]]               [1, 256, 16, 32, 32]         0       
     PReLU-19                  [[1, 256, 16, 32, 32]]               [1, 256, 16, 32, 32]        256      
  UpTransition-1     [[1, 256, 8, 16, 16], [1, 128, 16, 32, 32]]    [1, 256, 16, 32, 32]         0       
   Dropout3D-7                 [[1, 256, 16, 32, 32]]               [1, 256, 16, 32, 32]         0       
   Dropout3D-8                  [[1, 64, 32, 64, 64]]               [1, 64, 32, 64, 64]          0       
Conv3DTranspose-2              [[1, 256, 16, 32, 32]]               [1, 64, 32, 64, 64]       131,136    
  BatchNorm3D-17                [[1, 64, 32, 64, 64]]               [1, 64, 32, 64, 64]         256      
     PReLU-22                   [[1, 64, 32, 64, 64]]               [1, 64, 32, 64, 64]         64       
    Conv3D-16                  [[1, 128, 32, 64, 64]]               [1, 128, 32, 64, 64]     2,048,128   
  BatchNorm3D-18               [[1, 128, 32, 64, 64]]               [1, 128, 32, 64, 64]        512      
     PReLU-24                  [[1, 128, 32, 64, 64]]               [1, 128, 32, 64, 64]        128      
    LUConv-11                  [[1, 128, 32, 64, 64]]               [1, 128, 32, 64, 64]         0       
    Conv3D-17                  [[1, 128, 32, 64, 64]]               [1, 128, 32, 64, 64]     2,048,128   
  BatchNorm3D-19               [[1, 128, 32, 64, 64]]               [1, 128, 32, 64, 64]        512      
     PReLU-25                  [[1, 128, 32, 64, 64]]               [1, 128, 32, 64, 64]        128      
    LUConv-12                  [[1, 128, 32, 64, 64]]               [1, 128, 32, 64, 64]         0       
     PReLU-23                  [[1, 128, 32, 64, 64]]               [1, 128, 32, 64, 64]        128      
  UpTransition-2     [[1, 256, 16, 32, 32], [1, 64, 32, 64, 64]]    [1, 128, 32, 64, 64]         0       
Conv3DTranspose-3              [[1, 128, 32, 64, 64]]              [1, 32, 64, 128, 128]      32,800     
  BatchNorm3D-20               [[1, 32, 64, 128, 128]]             [1, 32, 64, 128, 128]        128      
     PReLU-26                  [[1, 32, 64, 128, 128]]             [1, 32, 64, 128, 128]        32       
    Conv3D-18                  [[1, 64, 64, 128, 128]]             [1, 64, 64, 128, 128]      512,064    
  BatchNorm3D-21               [[1, 64, 64, 128, 128]]             [1, 64, 64, 128, 128]        256      
     PReLU-28                  [[1, 64, 64, 128, 128]]             [1, 64, 64, 128, 128]        64       
    LUConv-13                  [[1, 64, 64, 128, 128]]             [1, 64, 64, 128, 128]         0       
     PReLU-27                  [[1, 64, 64, 128, 128]]             [1, 64, 64, 128, 128]        64       
  UpTransition-3    [[1, 128, 32, 64, 64], [1, 32, 64, 128, 128]]  [1, 64, 64, 128, 128]         0       
Conv3DTranspose-4              [[1, 64, 64, 128, 128]]             [1, 16, 128, 256, 256]      8,208     
  BatchNorm3D-22              [[1, 16, 128, 256, 256]]             [1, 16, 128, 256, 256]       64       
     PReLU-29                 [[1, 16, 128, 256, 256]]             [1, 16, 128, 256, 256]       16       
    Conv3D-19                 [[1, 32, 128, 256, 256]]             [1, 32, 128, 256, 256]     128,032    
  BatchNorm3D-23              [[1, 32, 128, 256, 256]]             [1, 32, 128, 256, 256]       128      
     PReLU-31                 [[1, 32, 128, 256, 256]]             [1, 32, 128, 256, 256]       32       
    LUConv-14                 [[1, 32, 128, 256, 256]]             [1, 32, 128, 256, 256]        0       
     PReLU-30                 [[1, 32, 128, 256, 256]]             [1, 32, 128, 256, 256]       32       
  UpTransition-4   [[1, 64, 64, 128, 128], [1, 16, 128, 256, 256]] [1, 32, 128, 256, 256]        0       
    Conv3D-20                 [[1, 32, 128, 256, 256]]             [1, 2, 128, 256, 256]       8,002     
  BatchNorm3D-24               [[1, 2, 128, 256, 256]]             [1, 2, 128, 256, 256]         8       
     PReLU-32                  [[1, 2, 128, 256, 256]]             [1, 2, 128, 256, 256]         2       
    Conv3D-21                  [[1, 2, 128, 256, 256]]             [1, 2, 128, 256, 256]         6       
OutputTransition-1            [[1, 32, 128, 256, 256]]             [1, 2, 128, 256, 256]         0       
===========================================================================================================
Total params: 45,609,250
Trainable params: 45,598,618
Non-trainable params: 10,632
-----------------------------------------------------------------------------------------------------------
Input size (MB): 32.00
Forward/backward pass size (MB): 29372.00
Params size (MB): 173.99
Estimated Total Size (MB): 29577.99
-----------------------------------------------------------------------------------------------------------

Vnet test is complete

6. 开始训练

一行代码开始训练

#开始训练
"""
!python3 train.py --config /home/aistudio/vnet_livers.yml #yaml文件路径
    --save_dir  "/home/aistudio/output/livers" #模型保存路径
    --save_interval 500 #多少iters保存模型参数
    --log_iters 60  #多少iters打印一次信息
    --iters 15000 #训练多少iters
    --num_workers 6 
    --do_eval  #是否训练期间验证模型性能
    --use_vdl  #是否使用VisualDL可视化训练指标的走势
"""
!python3 train.py --config /home/aistudio/vnet_livers.yml \
    --save_dir  "/home/aistudio/output/livers_vent128x128x128" \
    --save_interval 500 --log_iters 20  \
    --num_workers 6 --do_eval --use_vdl 

7. 模型的验证和导出

2022-02-28 01:24:12 [INFO]	[EVAL] #Images: 6, Dice: 0.6289, Loss: 0.634533
2022-02-28 01:24:12 [INFO]	[EVAL] Class dice: 
[0.9893 0.8679 0.0295]

用VNet跑了15000,验证集的效果如下:肝脏的dice为0.8679,肿瘤的dice为0.0295。对肿瘤这些小目标的检测效果比较差

#验证
"""
!python3 val.py --config /home/aistudio/vnet_livers.yml \  #yaml文件路径
--model_path /home/aistudio/output/livers/best_model/model.pdparams \ #最优模型的路径
--save_dir  /home/aistudio/output/livers/best_model  #验证后结果的保存路径
"""
!python3 val.py --config /home/aistudio/vnet_livers.yml \
--model_path /home/aistudio/output/livers/best_model/model.pdparams \
--save_dir  /home/aistudio/output/livers/best_model
2022-02-28 01:24:04 [INFO]	
---------------Config Information---------------
batch_size: 2
data_root: livers/
iters: 15000
loss:
  coef:
  - 1
  types:
  - coef:
    - 0.7
    - 0.3
    losses:
    - type: CrossEntropyLoss
      weight: null
    - type: DiceLoss
    type: MixedLoss
lr_scheduler:
  decay_steps: 15000
  end_lr: 0
  learning_rate: 0.0003
  power: 0.9
  type: PolynomialDecay
model:
  elu: false
  in_channels: 1
  num_classes: 3
  pretrained: null
  type: VNet
optimizer:
  momentum: 0.9
  type: sgd
  weight_decay: 0.0001
train_dataset:
  dataset_root: /home/aistudio/PaddleSeg3D/livers/
  mode: train
  num_classes: 3
  result_dir: None
  transforms:
  - scale:
    - 0.8
    - 1.2
    size: 128
    type: RandomResizedCrop3D
  - degrees: 60
    type: RandomRotation3D
  - type: RandomFlip3D
  type: LungCoronavirus
val_dataset:
  dataset_root: /home/aistudio/PaddleSeg3D/livers/
  mode: val
  num_classes: 3
  result_dir: None
  transforms: []
  type: LungCoronavirus
------------------------------------------------
W0228 01:24:04.360675 32748 device_context.cc:447] Please NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 10.1, Runtime API Version: 10.1
W0228 01:24:04.360720 32748 device_context.cc:465] device: 0, cuDNN Version: 7.6.
2022-02-28 01:24:08 [INFO]	Loading pretrained model from /home/aistudio/output/livers/best_model/model.pdparams
2022-02-28 01:24:09 [INFO]	There are 178/178 variables loaded into VNet.
2022-02-28 01:24:09 [INFO]	Loaded trained params of model successfully
2022-02-28 01:24:09 [INFO]	Start evaluating (total_samples: 6, total_iters: 6)...
2022-02-28 01:24:10 [INFO]	[EVAL] Sucessfully save iter 0 pred and label.
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/fluid/dygraph/math_op_patch.py:253: UserWarning: The dtype of left and right variables are not the same, left dtype is paddle.float32, but right dtype is paddle.bool, the right dtype will convert to paddle.float32
  format(lhs_dtype, rhs_dtype, lhs_dtype))
1/6 [====>.........................] - ETA: 3s - batch_cost: 0.6990 - reader cost: 0.20632022-02-28 01:24:10 [INFO]	[EVAL] Sucessfully save iter 1 pred and label.
2/6 [=========>....................] - ETA: 2s - batch_cost: 0.5683 - reader cost: 0.10322022-02-28 01:24:11 [INFO]	[EVAL] Sucessfully save iter 2 pred and label.
3/6 [==============>...............] - ETA: 1s - batch_cost: 0.5247 - reader cost: 0.06882022-02-28 01:24:11 [INFO]	[EVAL] Sucessfully save iter 3 pred and label.
4/6 [===================>..........] - ETA: 1s - batch_cost: 0.5027 - reader cost: 0.05172022-02-28 01:24:12 [INFO]	[EVAL] Sucessfully save iter 4 pred and label.
5/6 [========================>.....] - ETA: 0s - batch_cost: 0.4912 - reader cost: 0.04132022-02-28 01:24:12 [INFO]	[EVAL] Sucessfully save iter 5 pred and label.
6/6 [==============================] - 3s 483ms/step - batch_cost: 0.4830 - reader cost: 0.0345
2022-02-28 01:24:12 [INFO]	[EVAL] #Images: 6, Dice: 0.6289, Loss: 0.634533
2022-02-28 01:24:12 [INFO]	[EVAL] Class dice: 
[0.9893 0.8679 0.0295]
#导出模型,方便推理和部署
"""
!python export.py --config /home/aistudio/vnet_livers.yml \ #yaml文件路径
--save_dir  '/home/aistudio/save_model'  \#导出模型的保存路径
--model_path /home/aistudio/output/livers/best_model/model.pdparams #需要导出的模型的路径
"""
!python export.py --config /home/aistudio/vnet_livers.yml \
--save_dir  '/home/aistudio/save_model'  \
--model_path /home/aistudio/output/livers/best_model/model.pdparams
#加载导出来的模型,对数据进行推理
!python deploy/python/infer.py  --config /home/aistudio/save_model/deploy.yaml \
--image_path /home/aistudio/PaddleSeg3D/livers/images/volume-5.npy \
--save_dir '/home/aistudio'
#可视化推理后的结果
pre = np.load('/home/aistudio/volume-5.npy')
pre = np.squeeze(pre)
print(pre.shape)

img = pre[60,:,:]
plt.imshow(img,'gray')
plt.show()
(256, 128, 128)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iYgKTcE5-1646469900140)(output_23_1.png)]

Logo

学大模型,用大模型上飞桨星河社区!每天8点V100G算力免费领!免费领取ERNIE 4.0 100w Token >>>

更多推荐