U-Net网络详解

U-Net是一种用于生物医学图像分割的卷积网络,采用U形结构,包括压缩和扩展路径,可在少量训练数据上实现高精度。网络利用镜像策略处理边界像素,并通过裁剪和合并特征图进行多尺度融合。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

U-Net: Convolutional Networks for Biomedical Image Segmentation

原文地址:https://zhuanlan.zhihu.com/p/43927696

前言

U-Net是比较早的使用全卷积网络进行语义分割的算法之一,论文中使用包含压缩路径和扩展路径的对称U形结构在当时非常具有创新性,且一定程度上影响了后面若干个分割网络的设计,该网络的名字也是取自其U形形状。

U-Net的实验是一个比较简单的ISBI cell tracking数据集,由于本身的任务比较简单,U-Net紧紧通过30张图片并辅以数据扩充策略便达到非常低的错误率,拿了当届比赛的冠军。

论文源码已开源,可惜是基于MATLAB的Caffe版本。虽然已有各种开源工具的实现版本的U-Net算法陆续开源,但是它们绝大多数都刻意回避了U-Net论文中的细节,虽然这些细节现在看起来已无关紧要甚至已被淘汰,但是为了充分理解这个算法,笔者还是建议去阅读作者的源码,地址如下:https://lmb.informatik.uni-freiburg.de/people/ronneber/u-net/

1. 算法详解

1.1 U-Net的网络结构

直入主题,U-Net的U形结构如图1所示。网络是一个经典的全卷积网络(即网络中没有全连接操作)。网络的输入是一张 [公式] 的边缘经过镜像操作的图片(input image tile),关于“镜像操作“会在1.2节进行详细分析,网络的左侧(红色虚线)是由卷积和Max Pooling构成的一系列降采样操作,论文中将这一部分叫做压缩路径(contracting path)。压缩路径由4个block组成,每个block使用了3个有效卷积和1个Max Pooling降采样,每次降采样之后Feature Map的个数乘2,因此有了图中所示的Feature Map尺寸变化。最终得到了尺寸为 [公式] 的Feature Map。

网络的右侧部分(绿色虚线)在论文中叫做扩展路径(expansive path)。同样由4个block组成,每个block开始之前通过反卷积将Feature Map的尺寸乘2,同时将其个数减半(最后一层略有不同),然后和左侧对称的压缩路径的Feature Map合并,由于左侧压缩路径和右侧扩展路径的Feature Map的尺寸不一样,U-Net是通过将压缩路径的Feature Map裁剪到和扩展路径相同尺寸的Feature Map进行归一化的(即图1中左侧虚线部分)。扩展路径的卷积操作依旧使用的是有效卷积操作,最终得到的Feature Map的尺寸是 [公式] 。由于该任务是一个二分类任务,所以网络有两个输出Feature Map。

图1:U-Net网络结构图

如图1中所示,网络的输入图片的尺寸是 [公式] ,而输出Feature Map的尺寸是 [公式],这两个图像的大小是不同的,无法直接计算损失函数,那么U-Net是怎么操作的呢?

1.2 U-Net究竟输入了什么

首先,数据集我们的原始图像的尺寸都是 [公式] 的。为了能更好的处理图像的边界像素,U-Net使用了镜像操作(Overlay-tile Strategy)来解决该问题。镜像操作即是给输入图像加入一个对称的边(图2),那么边的宽度是多少呢?一个比较好的策略是通过感受野确定。因为有效卷积是会降低Feature Map分辨率的,但是我们希望 [公式] 的图像的边界点能够保留到最后一层Feature Map。所以我们需要通过加边的操作增加图像的分辨率,增加的尺寸即是感受野的大小,也就是说每条边界增加感受野的一半作为镜像边。

图2:U-Net镜像操作

根据图1中所示的压缩路径的网络架构,我们可以计算其感受野:

[公式]

这也就是为什么U-Net的输入数据是 [公式] 的。572的卷积的另外一个好处是每次降采样操作的Feature Map的尺寸都是偶数,这个值也是和网络结构密切相关的。

1.3 U-Net的损失函数

ISBI数据集的一个非常严峻的挑战是紧密相邻的物体之间的分割问题。如图3所示,(a)是输入数据,(b)是Ground Truth,(c)是基于Ground Truth生成的分割掩码,(d)是U-Net使用的用于分离边界的损失权值。

图3:ISBI数据集样本示例

那么该怎样设计损失函数来让模型有分离边界的能力呢?U-Net使用的是带边界权值的损失函数:

[公式]

其中 [公式] 是$$softmax$$损失函数, [公式] 是像素点的标签值, [公式] 是像素点的权值,目的是为了给图像中贴近边界点的像素更高的权值。

[公式]

其中 [公式] 是平衡类别比例的权值, [公式] 是像素点到距离其最近的细胞的距离, [公式] 则是像素点到距离其第二近的细胞的距离。 [公式] 和 [公式] 是常数值,在实验中 [公式] , [公式] 。

2. 数据扩充

由于训练集只有30张训练样本,作者使用了数据扩充的方法增加了样本数量。并且作者指出任意的弹性形变对训练非常有帮助。

3. 总结

U-Net是比较早的使用多尺度特征进行语义分割任务的算法之一,其U形结构也启发了后面很多算法。但其也有几个缺点:

  1. 有效卷积增加了模型设计的难度和普适性;目前很多算法直接采用了same卷积,这样也可以免去Feature Map合并之前的裁边操作
  2. 其通过裁边的形式和Feature Map并不是对称的,个人感觉采用双线性插值的效果应该会更好。

Reference

[1] Ronneberger O, Fischer P, Brox T. U-net: Convolutional networks for biomedical image segmentation[C]//International Conference on Medical image computing and computer-assisted intervention. Springer, Cham, 2015: 234-241.

<think>好的,我需要回答用户关于U-Net代码实现与解析的问题。首先,我得回忆一下U-Net的结构,它主要包括编码器(下采样)、解码器(上采样)以及跳跃连接。用户提到了参考的引用内容,里面涉及U-Net的医学应用、结构分析和代码实现,所以应该结合这些信息来回答。 首先,要确保使用正确的中文术语,比如“编码器”、“解码器”、“跳跃连接”等。然后,按照用户的要求,行内数学公式用$...$,独立公式用$$...$$。比如,在解释卷积操作时,可以用$W' = \frac{W - F + 2P}{S} + 1$这样的公式。注意LaTeX语法的正确性,比如积分符号\int,上下标等。 接下来,用户需要代码的详细解释,所以需要分模块讲解,比如数据增强、编码器、解码器、损失函数等部分。每个模块需要给出代码示例,并解释关键参数和步骤。比如在数据增强部分,要提到旋转、翻转等方法,并说明它们如何增加数据多样性。 在编码器部分,需要说明每个块的结构,比如卷积层、激活函数、池化层。解码器部分则要说明上采样和跳跃连接的操作。跳跃连接需要解释如何将编码器的特征图与解码器的特征图拼接,以恢复空间信息。 损失函数部分,用户引用中提到医学数据有限,可能使用Dice损失,所以需要解释为什么选择这个损失函数,以及它的计算公式。例如,Dice损失的计算公式可以用$$ \text{Dice Loss} = 1 - \frac{2|X \cap Y|}{|X| + |Y|} $$来表示。 然后,生成相关问题,要围绕U-Net的实现细节、改进方法、应用场景等方面提问。比如,如何处理图像尺寸变化,如何优化训练效率,U-Net在Diffusion Model中的作用等。 最后,检查所有引用是否正确标注,确保没有遗漏用户提供的参考信息。比如在数据增强部分引用[^1],在损失函数部分引用[^3],在应用场景提到Diffusion Model时引用[^2]。 需要避免使用Markdown格式,保持自然的中文口语化,但结构要清晰。确保每个代码块用```python包裹,数学公式正确无误。同时,回答要分点展开,帮助用户逐步理解U-Net的代码实现。</think>### U-Net代码实现与解析 U-Net是一种用于图像分割的对称结构网络,核心思想是通过编码器-解码器架构和跳跃连接(Skip Connection)融合浅层与深层特征。以下从**数据增强**、**网络结构**、**损失函数**和**训练细节**四部分解析其代码实现。 --- #### 一、数据增强模块 医学图像数据集通常较小,需通过数据增强提升模型泛化能力。常见方法包括**随机旋转**、**翻转**、**亮度调整**等: ```python import torch from torchvision import transforms train_transform = transforms.Compose([ transforms.RandomRotation(20), # 随机旋转±20° transforms.RandomHorizontalFlip(), # 水平翻转概率50% transforms.ColorJitter(contrast=0.2), # 对比度调整 transforms.ToTensor() ]) ``` [^1]中提到,数据增强是U-Net在有限数据下保持精度的关键。 --- #### 二、网络结构实现 ##### 1. 编码器(下采样) 每个编码块包含两次卷积+ReLU,后接最大池化: ```python class EncoderBlock(nn.Module): def __init__(self, in_ch, out_ch): super().__init__() self.conv = nn.Sequential( nn.Conv2d(in_ch, out_ch, kernel_size=3, padding=1), nn.ReLU(), nn.Conv2d(out_ch, out_ch, kernel_size=3, padding=1), nn.ReLU() ) self.pool = nn.MaxPool2d(2) def forward(self, x): x = self.conv(x) p = self.pool(x) return x, p # 返回特征图供跳跃连接使用 ``` **关键参数**:每个池化层将特征图尺寸减半,通道数翻倍。 ##### 2. 解码器(上采样) 解码块通过转置卷积实现上采样,并与跳跃连接的特征拼接: ```python class DecoderBlock(nn.Module): def __init__(self, in_ch, out_ch): super().__init__() self.up = nn.ConvTranspose2d(in_ch, out_ch, kernel_size=2, stride=2) self.conv = nn.Sequential( nn.Conv2d(2*out_ch, out_ch, 3, padding=1), # 拼接后通道翻倍 nn.ReLU(), nn.Conv2d(out_ch, out_ch, 3, padding=1), nn.ReLU() ) def forward(self, x, skip): x = self.up(x) x = torch.cat([x, skip], dim=1) # 沿通道维度拼接 return self.conv(x) ``` **公式说明**:假设输入尺寸为$H \times W$,转置卷积后尺寸计算为: $$ H' = (H - 1) \times \text{stride} + \text{kernel\_size} - 2 \times \text{padding} $$ --- #### 三、损失函数 医学分割常用Dice Loss解决类别不平衡问题: $$ \text{Dice Loss} = 1 - \frac{2|X \cap Y|}{|X| + |Y|} $$ 代码实现: ```python def dice_loss(pred, target, smooth=1e-5): pred = torch.sigmoid(pred) intersection = (pred * target).sum() return 1 - (2. * intersection + smooth) / (pred.sum() + target.sum() + smooth) ``` 的GitHub代码中结合了BCE Loss与Dice Loss提升训练稳定性。 --- #### 四、完整网络结构 ```python class UNet(nn.Module): def __init__(self): super().__init__() # 编码器 self.enc1 = EncoderBlock(3, 64) self.enc2 = EncoderBlock(64, 128) # 瓶颈层 self.bottleneck = nn.Sequential( nn.Conv2d(128, 256, 3, padding=1), nn.ReLU() ) # 解码器 self.dec1 = DecoderBlock(256, 128) self.dec2 = DecoderBlock(128, 64) # 输出层 self.out = nn.Conv2d(64, 1, 1) def forward(self, x): s1, p1 = self.enc1(x) s2, p2 = self.enc2(p1) b = self.bottleneck(p2) d1 = self.dec1(b, s2) d2 = self.dec2(d1, s1) return torch.sigmoid(self.out(d2)) ``` **训练技巧**:使用Adam优化器,初始学习率设为$3 \times 10^{-4}$,每10个epoch衰减0.1倍。 ---
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值