一、核心知识点
1.1 U-Net:2D 分割基线架构(2015)
U-Net 由编码器(contracting path)+ 解码器(expanding path)组成,呈 U 形。
编码器:连续的两层 3×3 卷积 + ReLU + 2×2 最大池化,逐级下采样、通道翻倍,提取语义特征。
解码器:上采样(转置卷积或插值)+ 卷积,逐级恢复空间分辨率。
跳跃连接(skip connection):把编码器同层的高分辨率细节特征拼接(concat)到解码器对应层,弥补下采样造成的空间信息丢失——这是 U-Net 在医学小样本上表现好的关键。
输出:1×1 卷积将通道数映射到类别数,得到与输入同尺寸的分割掩码。
原始论文用 valid 卷积(无 padding),输入 572×572 → 输出 388×388;现代实现多用 same padding 使输入输出同尺寸,更易用。
import torch import torch.nn as nn class DoubleConv(nn.Module): # 编码器/解码器基本单元 def __init__(self, in_ch, out_ch): super().__init__() self.net = nn.Sequential( nn.Conv2d(in_ch, out_ch, 3, padding=1), nn.ReLU(inplace=True), nn.Conv2d(out_ch, out_ch, 3, padding=1), nn.ReLU(inplace=True), ) def forward(self, x): return self.net(x) class UNet(nn.Module): def __init__(self, in_ch=1, num_classes=2): super().__init__() self.enc1 = DoubleConv(in_ch, 64) self.enc2 = DoubleConv(64, 128) self.pool = nn.MaxPool2d(2) self.up = nn.ConvTranspose2d(128, 64, 2, stride=2) self.dec1 = DoubleConv(128, 64) # 拼接后通道为 64+64=128 self.out = nn.Conv2d(64, num_classes, 1) def forward(self, x): e1 = self.enc1(x) e2 = self.enc2(self.pool(e1)) # 下采样 d1 = self.up(e2) # 上采样 d1 = torch.cat([d1, e1], dim=1) # 跳跃连接(需尺寸一致) return self.out(self.dec1(d1))
注:这是 2 层简化版,用于理解结构;完整 U-Net 更深(通常 4 级下采样),并在跳跃连接处做裁剪以对齐 valid 卷积的尺寸。
输入 x │ enc1: DoubleConv(in_ch -> 64) → e1 │ pool: MaxPool2d(2) 下采样 │ enc2: DoubleConv(64 -> 128) → e2 │ up: ConvTranspose2d(128 -> 64) 上采样 → d1 │ torch.cat([d1, e1], dim=1) 跳跃连接,通道拼接 │ dec1: DoubleConv(128 -> 64) │ out: Conv2d(64 -> num_classes, 1) │ 输出 logits
1.2 nnU-Net:通用医学图像分割框架(2021)
nnU-Net 不提出新网络结构,而是把"如何把分割任务做对"工程化、自动化。核心模块:
| 模块 | 作用 |
|---|---|
| 数据集指纹(fingerprinting) | 自动统计图像尺寸、体素间距、模态数、类别占比 |
| 自适应预处理 | 按指纹自动决定重采样间距、归一化方式(按模态/前景)、裁剪 |
| 配置自动选择 | 通过 5 折交叉验证,自动在 2D / 3D fullres / 3D cascade 中选最优 |
| 5 折交叉验证 | 既用于模型选择,也用于集成(ensemble)提升鲁棒性 |
| 后处理 | 连通域分析,如保留最大连通分量、移除小假阳性 |
它成为领域基准的核心原因:
消除人为偏差:用统一、数据驱动的默认配置替代"凭经验调参";
强泛化:同一套 pipeline 在数十个数据集上均达 SOTA;
严谨可复现:固定训练细节(损失、优化器、数据增强)并开源全流程。
nnU-Net = "正确的工程默认" + "自动化验证",而不是"更花哨的网络"。
nnU-Net中的“保留最大连通分量”是一种基于先验假设的后处理操作:它假定目标结构在解剖学上是单一且连续的实体。nnU-Net不会默认启用它,而是会在交叉验证中自动评估其效果,仅当该操作能提升平均前景Dice且不降低任何类别的Dice时,才会被采纳。
适用任务:当目标结构是单一连续实体时
这类后处理主要适用于器官分割或结构本身应连续的任务,其核心价值在于去除孤立的假阳性预测。
实性器官分割:如肝脏、脾脏、肾脏等,这些器官在解剖上通常是单一连通区域。保留最大连通分量可以有效去除网络在器官周围产生的零星、孤立的假阳性预测。
管状或条状连续结构:例如脊髓管(Spinal Canal)的分割。由于脊髓管在解剖上是连续的,保留最大连通分量有助于避免将其他解剖结构误分割为脊髓管。
脑部特定区域的分割:当研究假设每个脑区(如Desikan-Killiany图谱中的区域)应为一个连续的解剖实体时,保留最大连通分量可以确保分割结果的拓扑合理性,剔除因噪声产生的碎片。
去除孤立噪声:作为一种通用的后处理手段,它可以有效移除预测结果中那些体积很小、与主体不相连的孤立噪声点或碎片。
有害情况:当目标结构天然多发或不连续时
当任务本身包含多个独立的实例,或目标结构因病理原因发生断裂时,该操作会错误地移除真实的阳性预测,引入假阴性,导致性能严重下降。
多病灶/多实例任务:
多发性肿瘤:例如,当患者体内存在多个转移瘤时,强制保留最大连通分量会删除所有较小的真实肿瘤,造成严重的假阴性。
多发性硬化症(MS)病灶:对于MS病灶分割,连通分量分析(CCA)在本质上是次优的,因为它无法正确区分“融合性病灶”(即多个病灶在空间上相连的情况),会低估病灶数量,导致假阴性增加。
因病理或成像原因导致的结构断裂:
裂隙状脑室(Slit Ventricles):在脑室分割中,如果患者脑室因病理原因变得狭窄甚至出现裂隙状分离,保留最大连通分量会丢弃那些非最大的真实脑室部分。
肿瘤坏死或空洞:对于某些坏死性肿瘤(如环形强化的肿瘤),其强化区域可能不是连续的,强制连通性会移除真实的肿瘤组织-。
召回率与精度的权衡:即使是在器官分割中,该操作在去除假阳性的同时,也可能移除一些正确预测的小结构,导致召回率的小幅下降。这是一种用精度换取召回率的权衡-。在需要高敏感度的筛查任务中,这种召回率的损失可能是不可接受的。
总结与使用建议
“保留最大连通分量”是一把双刃剑,其有效性完全取决于任务先验假设是否成立。
检查先验:在决定使用前,必须明确回答:“我的目标结构在解剖学上是否必然是单一连续的?”
精细化控制:nnU-Net通过
for_which_classes参数允许你仅对特定类别应用此操作。例如,可以只对“肝脏”应用,而不对“肝脏肿瘤”应用,因为肿瘤可能是多发的。保留次要分量:对于可能具有两个主要部分的器官(如肾脏),有研究建议保留最大和次大的连通分量,而不是只保留最大的一个-。
审慎评估:务必在验证集上对比应用该操作前后的指标。重点关注病灶级别的召回率(Lesion Recall)和假阴性数量(FN Count),而不仅仅是体素级别的Dice分数-。
二、常见坑与调参经验
数据格式不规范→ dataset.json 的标签映射、文件命名必须严格符合 nnU-Net 约定,否则
verify_dataset_integrity报错。显存不足→ 改用 2D 配置或减小 patch size;cascade 对大体积更友好但更慢。
数据量小过拟合→ 依赖 nnU-Net 默认增强(旋转、弹性形变、灰度偏移);勿盲目加大量增强。
指标上不去先查预处理→ 窗宽窗位、归一化方式不对,网络再深也救不回。
只训一折就上报→ 必须用 5 折集成结果作为最终指标,单折方差大。
后处理误关→ 某些任务(如单连通器官)开后处理能稳定提点,先让 nnU-Net 自动搜。