一、论文介绍
1.介绍
本文提出了一种用于生物医学图像分割的卷积神经网络结构,称为 U-Net。U-Net 的设计主要针对生物医学图像分割任务,如细胞分割、器官分割等。U-Net 网络结构具有 U 字形的特点,它由对称的下采样(编码器)和上采样(解码器)部分组成。
原文:https://arxiv.org/abs/1505.04597
原码:http://lmb.informatik.uni-freiburg.de/people/ronneber/u-net
2.网络结构
U-Net网络结构如图所示,它由对称的下采样(编码器)和上采样(解码器)部分组成。下采样部分用于逐渐缩小输入图像的空间尺寸,并提取抽象的特征表示。上采样部分则通过反卷积操作将特征图逐步放大,并进行逐层的特征融合,最终生成与输入图像相同尺寸的分割结果。还使用了一些常见的卷积神经网络中的组件,它包括重复应用两个3x3卷积(未填充卷积),每个卷积后面都有一个校正线性单元(ReLU)和一个2x2最大池化操作,步长为2,用于下采样。在每个下采样步骤,我们将特征通道的数量增加一倍。扩展路径中的每一步都包括特征图的上采样,然后是将特征通道数量减半的2x2卷积(“上卷积”),与收缩路径中相应裁剪的特征图的级联,以及两个3x3卷积,每个卷积后面都有ReLU。由于每个卷积中都会丢失边界像素,因此裁剪是必要的。在最后一层,用了一个 1×1 的卷积层将每个64分量特征向量映射到期望数量的类,并应用了sigmoid激活函数,以生成像素级别的二进制分割结果。网络总共有23个卷积层。 U-Net 的主要创新在于它引入了跳跃连接,即将下采样过程中的特征图与对应的上采样过程中的特征图进行连接。这种跳跃连接的设计有助于将低层次的局部特征与高层次的全局特征进行融合,能够更好地保留细节信息并提高分割精度。
3.结论
这篇论文通过在生物医学图像分割任务上的实验证明,U-Net 在分割精度和细节保留方面取得了显著的改进,成为了生物医学图像分割领域的重要工具和基准模型。它在许多任务中取得了优秀的性能,并被广泛应用于医学图像分析、医学影像诊断等领域。
二、代码注释
1.所需相关库
import torch
import torch.nn as nn
import torch.nn.functional as F
这段代码导入了 PyTorch 库,并分别导入了 torch
、torch.nn
和 torch.nn.functional
模块。这些模块提供了构建神经网络和执行各种操作的函数和类。
2.双卷积层
class double_conv(nn.Module): # 定义一个双卷积层的类
def __init__(self, in_channels, out_channels):
super().__init__()
self.double_conv = nn.Sequential(
nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1, padding_mode='reflect', bias=False), # 使用3x3卷积核的卷积层
nn.BatchNorm2d(out_channels), # 批归一化层
nn.ReLU(inplace=True), # ReLU激活函数
nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1, padding_mode='reflect', bias=False), # 再次使用3x3卷积核的卷积层
nn.BatchNorm2d(out_channels), # 批归一化层
nn.ReLU(inplace=True)) # ReLU激活函数
def forward(self, x):
return self.double_conv(x) # 返回双卷积层的输出
这个双卷积层的设计在神经网络中常用于提取特征并增加模型的非线性能力。通过使用卷积层进行特征提取,并结合批归一化和激活函数的操作,可以增强网络的表达能力和学习能力。
3.下采样
class Down(nn.Module): # 定义一个下采样模块的类
def __init__(self, in_channels, out_channels):
super().__init__()
self.maxpool_conv = nn.Sequential(
nn.MaxPool2d(2), # 最大池化层,缩小特征图尺寸为原来的一半
double_conv1(in_channels, out_channels)) # 使用上面定义的双卷积层进行特征提取
def forward(self, x):
return self.maxpool_conv(x) # 返回下采样模块的输出
下采样操作可以帮助网络获取更大范围的上下文信息,并减小特征图的尺寸,从而提高计算效率和模型的感受野。
4.上采样
class Up(nn.Module): # 定义一个上采样模块的类
def __init__(self, in_channels, out_channels):
super().__init__()
self.up = nn.ConvTranspose2d(in_channels, in_channels // 2, kernel_size=2, stride=2) # 转置卷积层,实现上采样操作
self.conv = double_conv1(in_channels, out_channels) # 使用上面定义的双卷积层进行特征提取
def forward(self, x1, x2):
x1 = self.up(x1) # 对输入进行上采样操作
diffY = x2.size()[2] - x1.size()[2] # 计算x2和x1在高度上的差异
diffX = x2.size()[3] - x1.size()[3] # 计算x2和x1在宽度上的差异
x1 = F.pad(x1, [diffX // 2, diffX - diffX // 2, diffY // 2, diffY - diffY // 2]) # 对x1进行填充,使其与x2的尺寸相同
x = torch.cat([x2, x1], dim=1) # 在通道维度上将x2和x1拼接起来
return self.conv(x) # 返回上采样模块的输出
上采样操作可以帮助恢复特征图的空间分辨率,并通过特征融合操作丰富特征表示,从而提高分割结果的细节保留能力。
5.输入卷积
class inconv(nn.Module): # 定义一个输入卷积模块的类
def __init__(self, in_channels, out_channels):
super().__init__()
self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1) # 3x3卷积层,用于特征提取
def forward(self, x):
return self.conv(x) # 返回输入卷积模块的输出
输入卷积模用于对输入特征图进行初步的特征提取。通过使用3x3卷积核进行卷积操作,可以提取输入特征图的局部信息,并减小特征图的尺寸。
6.U-Net网络
class UNet(nn.Module):
def __init__(self, input_channels, output_channels):
super(UNet, self).__init__()
# 定义网络的各个模块
self.inc = double_conv1(input_channels, 64) # 输入卷积模块
self.down1 = Down(64, 128) # 下采样模块
self.down2 = Down(128, 256) # 下采样模块
self.down3 = Down(256, 512) # 下采样模块
self.down4 = Down(512, 1024) # 下采样模块
self.up1 = Up(1024, 512) # 上采样模块
self.up2 = Up(512, 256) # 上采样模块
self.up3 = Up(256, 128) # 上采样模块
self.up4 = Up(128, 64) # 上采样模块
self.outc = inconv(64, output_channels) # 输出卷积模块
def forward(self, x):
# 网络的前向传播过程
x1 = self.inc(x) # 输入卷积模块
x2 = self.down1(x1) # 下采样模块1
x3 = self.down2(x2) # 下采样模块2
x4 = self.down3(x3) # 下采样模块3
x5 = self.down4(x4) # 下采样模块4
x = self.up1(x5, x4) # 上采样模块1
x = self.up2(x, x3) # 上采样模块2
x = self.up3(x, x2) # 上采样模块3
x = self.up4(x, x1) # 上采样模块4
x = self.outc(x) # 输出卷积模块
return torch.tanh(x) # 使用tanh函数对输出进行激活,将值映射到[-1, 1]的范围内