ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

UNet+SE+Transformer:脊椎CT分割的实践改进

2026/8/31 18:12:13 拓冰建站 浏览量
UNet+SE+Transformer:脊椎CT分割的实践改进 简介本资源面向医学影像分析方向的深度学习研究者与临床AI开发者提供一套基于U-Net改进SE注意力机制与Transformer全局建模能力的人体脊椎分割完整实现方案旨在解决CT/MRI图像中脊椎结构形态多变、边界模糊、背景复杂导致的分割精度瓶颈问题。压缩包共2000个文件含1501张PNG与492张JPG格式的脊椎影像及对应标注图覆盖不同扫描协议与解剖变异4个核心Python训练/推理脚本、1份详细项目说明书.docx、1份数据集说明.txt及1份README.md整体仅26.89MB轻量易部署。已有73人下载学习资源结构清晰数据与代码分离模型模块化封装含SEBlock与TransformerEncoder子模块配套说明书涵盖网络结构图、训练参数配置、评估指标说明及典型分割结果可视化示例可直接用于复现实验、迁移训练或作为课程设计/科研基线模型。 先交代一个项目背景半年前我接到一个人体脊椎分割任务原始需求是给一组脊柱CT影像做椎体自动分割目标Dice不低于0.90同时要输出一份能交给合作方复现的项目说明书和整理好的数据集。刚开始我很自信直接复用了之前跑腹部器官分割的UNet代码往里灌数据训练30轮后Dice只有0.88肉眼检查的结果更让人焦虑椎体边缘全是锯齿状伪影胸椎段相邻椎体经常连成一片部分椎体还被邻近的腰大肌灰度值吃掉大半。这一轮折腾让我真正意识到普通UNet在人体脊椎分割上不是“精度不够高”的问题而是对骨性结构的边界锐度、长距离上下文关系建模能力本质上就有短板。于是我把改进方向锁定在了两个地方一是通道注意力SE模块让网络在层层特征中主动强调“对椎体判别有用的通道”二是Transformer用来补足UNet编码器-解码器结构里严重缺失的全局感受野。这个组合听起来不新鲜但在脊椎CT这种灰度单一、边界复杂、类间形态高度相似的场景里改进幅度其实相当可观。最终我在原UNet基础上拿到了约0.93的Dice效果稳定也顺手把整个项目沉淀成了一份可复用、可交付的东西。这篇文章我就完整复盘一遍为什么UNet做椎体分割吃力SE和Transformer具体应该插在哪些位置、怎么设计才能不拖慢训练数据组织和训练参数有哪些细节推理后处理有哪些值得注意的坑。内容偏实操代码片段和参数都是我实测过的希望能给正在做人像/器官/骨性结构分割的朋友一些参考。1. 为什么普通UNet在椎体分割上总是不够用1.1 椎体在CT影像里的表现与分割难点先理解任务本身。人体脊柱由颈椎、胸椎、腰椎、骶椎组成CT上椎体骨皮质呈高密度亮带内部松质骨密度相对低一些椎间盘和周围软组织则是低密度灰区。看起来“骨头很亮”好像挺好分割但实际做起来有几个很麻烦的特点。第一椎体间形态高度相似。胸椎T8和T9在CT轴状位上几乎就是两个椭圆套在一起单靠局部纹理很难区分必须依赖椎体之间的相对位置和形态连续性。普通UNet的感受野在深层虽然能覆盖较大区域但池化堆叠带来的“粗略定位”让它对两个相邻椎体边界的区分能力不足容易出现相邻椎体黏连。第二骨皮质边缘本身只有1-2毫米。CT里椎体边缘是一条非常细的高亮环标注的时候标注医生通常会把骨皮质和部分松质骨都包进去这就导致标签里存在大量“半影”区域。UNet使用的逐像素交叉熵对边缘像素的分辨能力有限很容易把边缘预测成模糊的一圈灰带。第三HU值范围跨度极大。空气约-1000软组织约0-100骨组织在300-2000以上。如果不做窗宽窗位截断直接归一化输入网络椎体边缘信息会被其他组织淹没。这一点我在后面的数据章节会细说。第四标签噪声天然存在。不同医生标注同一例脊柱CT椎体边界可能差出1-2个像素有的标注会把椎间盘也标进去有的不会。UNet这种对标注噪声比较敏感的密集预测模型如果只在单尺度上硬学很容易学到标注者个人的“笔法”而不是椎体本身的结构。1.2 普通UNet的三个结构性短板UNet本身是一个编码器-解码器结构编码器不断下采样提取高维语义特征解码器通过上采样逐步恢复分辨率再用skip connection把同尺度细节传回来。这个结构在器官分割上经过了大量验证但放到椎体分割上有三个结构性短板是骨子里带出来的。一是通道间关系建模弱。卷积本质上是空间和通道的加权求和但每个通道的权重在训练结束后就固定了。椎体分割中有的通道可能激活的是骨皮质边缘有的通道激活的是松质骨纹理有的通道激活的是周围软组织对比。网络在推理时并不知道某一层特征中哪个通道对当前像素更重要于是一刀切地全部平等对待。SE模块要解决的就是这个动态通道加权问题。二是全局上下文不足。UNet的感受野虽然会随着下采样增加但依然是局部窗口的叠加不是真正的全局建模。对椎体分割来说T12和L1的灰度分布差异很小区分它们主要靠的是“上面还有多少椎体”这种宏观信息。我在实际项目里观察到普通UNet很容易把L5误判成L1就是因为底层特征缺少全局位置感知。Transformer天然能做全局交互正好补这个短板。三是上采样路径的细节恢复精度有限。UNet用转置卷积或双线性插值放大特征图细节主要靠skip connection往回带。但skip connection带回来的特征只是同一层的局部特征没有经过任何“筛选”噪声和无关纹理也一并传回了。我后面会在skip连接上做轻量的注意力加权目的是让解码器只收到对椎体边界有用的内容。1.3 为什么选SETransformer而不是换一个更强的主干这一步我也纠结过。市面上有很多现成的分割框架要么用DeepLabv3要么用Swin UNet甚至直接拿Transformer做分割头。我当时考虑的重点是三个项目可交付性、显存开销、复现难度。Swin UNet这类纯Transformer医疗分割模型在优质数据集上确实效果好但对训练数据量的要求也高。我手里只有约180例标注CT强行上大型纯Transformer结构容易过拟合。DeepLabv3在骨性结构上表现不错但它的ASPP层在长距离建模上不如Transformer灵活。最终我采取的是“局部补强”的思路保留UNet成熟的编码-解码骨架在瓶颈层引入轻量Transformer建模全局关系在通道维度引入SE做功选择性强调。这样既不会大幅增加训练成本又能精准补上UNet缺失的两种能力。我后来复盘结论是对这种中等规模医学影像分割项目改进不是越新越好而是要找到原模型在任务上最痛的短板然后用最小改动去补。SE和Transformer恰好是这样一对互补组合。2. 两个改进模块的落地方式SE插入点与Transformer的“轻量缝合”2.1 SE模块不改变网络骨架只教会网络“重视哪些通道”SESqueeze-and-Excitation的核心逻辑很简单先用全局平均池化把每个通道的空间信息压缩成一个数值再通过两个全连接层学习通道间的相关性最后用sigmoid输出一个0到1之间的通道权重对原特征做通道重标定。在UNet里SE模块的插入位置有很多选择。有的人喜欢在每个卷积块后面都接一个SE这样参数量涨得比较多有的人只放在编码器侧解码器完全不管还有人放在skip connection上做特征校准。我在项目里最终选择的是只在编码器侧和瓶颈处插入SE解码器不插。为什么这样设计椎体分割中编码器负责抽取不同尺度的边缘和纹理特征在编码器各阶段加SE可以让网络在逐层下采样过程中动态抑制背景通道、增强骨性结构通道。解码器侧主要负责上采样恢复细节频繁插SE反而会让锐化过程变慢。实测在编码器每层加SE之后推理速度几乎没有明显下降但边界区域的假阳性减少了。这里贴一下我在PyTorch里用的SE实现代码量很小import torch import torch.nn as nn class SEBlock(nn.Module): def __init__(self, in_channels, reduction8): super().__init__() self.pool nn.AdaptiveAvgPool2d(1) self.fc nn.Sequential( nn.Conv2d(in_channels, in_channels // reduction, 1, biasFalse), nn.ReLU(inplaceTrue), nn.Conv2d(in_channels // reduction, in_channels, 1, biasFalse), nn.Sigmoid() ) def forward(self, x): b, c, h, w x.size() w self.fc(self.pool(x)).view(b, c, 1, 1) return x * w.expand_as(x)注意reduction我用了8而不是经典SE-ResNet里的16。原因很简单医学影像的特征通道本身不像ImageNet分类网络那么多如果压缩到1/16通道信息损失太严重椎体边缘这种细腻特征很容易被压没。调参的时候试过16和4前者在Dice上掉了近0.8个点后者训练变慢且收益不明显8是最平衡的。2.2 Transformer怎么“缝”进UNet我选择在瓶颈层加局部窗口注意力Transformer模块的核心是自注意力机制。标准的全局多头自注意力计算复杂度是O(n²)对分割任务来说特征图分辨率稍大一点显存和计算量就爆炸了。比如UNet最底层的特征图如果是16×16全局注意力勉强能跑如果是32×32训练一张图就容易被显存卡死。我试过三种方案第一种是在瓶颈层直接用标准Transformer Encoder第二种是用Swin Transformer的窗口多头注意力逐步移动窗口第三种是在UNet不同尺度都引入Transformer做成一个比较彻底的Transformer-UNet混合结构。最后落地的是瓶颈层使用窗口多头注意力加移位窗口W-MSA/SW-MSA。原因一是参数量和显存可控二是脊柱CT是强结构数据相邻椎体之间虽然需要全局关系但短期依赖依然占主导局部窗口注意力已经能覆盖绝大多数语义交互没必要做大范围全局计算。项目中Transformer块的代码结构大致如下import torch import torch.nn as nn class TransformerBlock(nn.Module): def __init__(self, dim, num_heads4, window_size8, mlp_ratio4.0): super().__init__() self.norm1 nn.LayerNorm(dim) self.attn WindowAttention(dim, window_size, num_heads) self.norm2 nn.LayerNorm(dim) self.mlp nn.Sequential( nn.Linear(dim, int(dim * mlp_ratio)), nn.GELU(), nn.Linear(int(dim * mlp_ratio), dim) ) def forward(self, x): x x self.attn(self.norm1(x)) x x self.mlp(self.norm2(x)) return xWindowAttention是按窗口划分特征图后做多头自注意力并加了相对位置编码因为椎体边缘这种高频信息对位置非常敏感。这里的关键不是代码本身而是三个设计决定。第一瓶颈层通道数不需要太宽。UNet底层通常有512或1024个通道如果瓶颈层还保持512个通道然后接Transformer参数量会非常大。我实际把瓶颈层通道压缩到256Transformer的num_heads设为4每个head的维度保持64。这样的设置下180例训练数据不会过拟合推理速度比原始UNet只慢了不到20%。第二窗口大小要匹配图像和椎体尺度。我的CT切片裁剪到256×256椎体在轴状位上大约占40-60像素宽。窗口大小设为8×8每个窗口大约能覆盖1/4到1/2个椎体既能捕捉椎体内部的细粒度纹理也能通过移位窗口让相邻窗口间交换信息。如果窗口设得太大比如16×16注意力矩阵就变大了小数据集上反而容易过拟合。第三位置编码不能省。Transformer本身没有空间顺序概念如果不加位置编码网络根本不知道特征图里的位置关系。CT里椎体从上到下是明确的序列信息位置编码对分割椎体级别的结构至关重要。我用了可学习的相对位置偏置而不是固定正弦位置编码实测相对位置偏置在10轮左右就能稳定收敛正弦位置编码大概要多跑20轮效果才接近。2.3 完整网络结构一个UNet 两处改动拆解整个改进后的网络结构可以这样理解编码器五层卷积下采样每层卷积块后接一个SEBlock用来动态重标定每层通道。瓶颈层在最高维特征处先接两层TransformerBlock再做一次上采样。TransformerBlock负责全局关系建模弥补UNet感受野不足。解码器经典的转置卷积上采样逐层融合编码器对应尺度的特征进行分割。Skip Connection我在编码器每层输出和解码器融合之前加了一个轻量的SE校准只对从编码器传回的通道做加权抑制背景噪声。很多人在UNet里同时加SE和Transformer时喜欢把Transformer插到编码器和解码器每一层结构很复杂实际效果未必好。我是坚持“小改动、可解释、易复现”的原则只在两个关键位置动手。做一个通俗类比UNet本身是一栋房子的主体框架SE是给每个房间装的智能灯光系统Transformer是客厅里那个能一眼看到全局的观景窗。灯能让你看清该看的东西窗能让你把握整个空间的格局但没必要给每个角落都装一扇落地窗。3. 数据集组织与训练配置把医学影像跑顺的关键参数3.1 数据预处理方向、裁剪和归一化一个都不能少项目使用的是CT数据的标准存储格式NIfTI也就是后缀为.nii.gz的文件每个文件包含一个三维体数据和对应的仿射变换矩阵。预处理的第一步是统一方向。很多公开数据集里的CT方向不完全一致有的按RAS坐标存储有的按LAS坐标存储如果不统一同一套代码在换数据时很容易出现左右翻转、切片顺序颠倒的问题。我的做法是使用SimpleITK读取后统一重采样到RAS方向并且把spacing统一到1.0×1.0×1.0毫米。第二步是HU值裁剪。前面提过CT的HU范围非常大直接输入网络会淹没椎体的边缘信息。我实测出来的最佳窗口是[-250, 1500]范围上界取得比较高因为椎体皮质骨的HU值常年在300-1000以上下界-250可以保留周围软组织的轮廓帮助网络理解椎体的边界环境。如果只做简单的Min-Max归一化到0-255不加窗宽裁剪Dice会明显下降。裁剪之后再统一线性映射到0-1区间def preprocess_ct(volume, lower-250, upper1500): volume np.clip(volume, lower, upper) volume (volume - lower) / (upper - lower) return volume.astype(np.float32)这套参数不是拍脑袋定的。我对比过[-1000, 2000]、[-200, 1000]等几组窗口发现[-250, 1500]在区分骨皮质、松质骨、椎间盘和肌肉组织上效果最好。如果你用的是MRI或者X光片窗口参数要重新调整不能直接套用。3.2 数据集的划分与标签处理我手里这批数据一共180例来自不同设备的扫描部分带有轻度金属伪影。直接把所有切片混在一起随机划分训练集和验证集是医学影像分割最容易犯的错误——同一患者的相邻切片在灰度、结构上极度相似一旦出现在训练集和验证集里验证指标会虚高很多。正确做法是按case患者/扫描序列划分确保同一个case的所有切片只出现在训练集或验证集中。实际划分比例是144例训练、18例验证、18例测试。标签处理方面原始标注是每个椎体单独一个编号比如T1-T12、L1-L5是一个多类别语义标签。在做二值分割时我会把所有椎体编号合并成一个前景类别。但这里有一个容易被忽略的坑如果最终希望做椎体定位或识别合并前需要把每个椎体中心点记录成一份辅助标注文件放入数据集目录这样后续只做分割模型也能轻松扩展出计数/识别功能。我的数据集目录结构最终是这样的dataset/ imagesTr/ # 训练集CT nii.gz labelsTr/ # 训练集标签 nii.gz imagesVa/ labelsVa/ imagesTs/ labelsTs/ dataset.json # 数据格式、类别、划分说明 README.md # 使用说明包含数据来源格式、预处理方式dataset.json里我写了模态CT、spacing、HU裁剪参数、Train/Val/Test划分清单。这份说明书式的文件非常重要交项目时如果没有这个合作方拿到数据根本不知道怎么复现。3.3 训练策略切片训练、损失函数与优化器我采用的是2D切片训练方式把三维CT沿轴状位切成二维切片后逐片输入网络。虽然丢弃了一部分z轴连续性信息但在显存有限的情况下这是最稳妥的方案。实际操作时每个case我会间隔取出切片同时只保留含有椎体前景超过1000像素的切片减少纯背景切片的干扰。如果一个切片里前景占比过高或过低会通过采样权重来平衡。损失函数我用了Dice Loss和加权交叉熵的线性组合。单纯的Dice Loss在小目标上容易梯度不稳单纯交叉熵在椎体边缘这类像素不平衡区域又容易预测模糊。我的组合是loss 0.5 * dice_loss(pred, target) 0.5 * weighted_bce(pred, target, weight0.7)weighted_bce里椎体前景类别的权重设为0.7背景权重0.3这样前景稀疏的问题得到缓解而DiceLoss继续负责整体区域重合度的优化。训练时还用了soft label把原本硬编码的0/1标签在边缘区域做一个小范围的高斯模糊让网络不那么纠结于标注者手抖产生的边缘噪声。优化器我用AdamW初始学习率3e-4采用余弦退火调度。batch size设为8输入切片288×288总训练轮数80轮。在单张RTX 309024GB显存上每个epoch大约耗时1.5分钟总训练时间2小时左右完全可以接受。以下是训练核心流程的简化逻辑for epoch in range(epochs): for batch in train_loader: images, masks batch preds model(images) loss dice_loss(preds, masks) 0.5 * bce_loss(preds, masks) loss.backward() optimizer.step() scheduler.step()3.4 评估指标Dice、IoU和HD95分别说明什么项目说明书里的验收指标不能只写Dice一个数。我最终记录了三个指标Dice、IoU、HD95。Dice衡量的是预测区域和真实标注区域的重叠程度对整体分割效果敏感IoU更严格一些对区域的完整性和精确性同时敏感HD95是Hausdorff距离的第95百分位专门衡量边界偏差对椎体这种对边缘锐度要求高的任务非常关键。我测试下来改进前的UNet边界毛刺多HD95普遍在2.8毫米以上改进后降到了1.5毫米左右这才是临床上真正关心的改进——不是光把“堆在一起的区域”多套上一个环而是让每个椎体的轮廓更贴合真实骨皮质。4. 推理后处理与效果对比指标好不代表分割好4.1 滑动窗口推理与拼接推理阶段我把三维CT按轴状位逐片预测但如果你只简单地把每张切片独立推断再叠起来三维方向容易出现条纹伪影。我实际采用一定范围的z轴重叠推理每次取5张相邻切片作为一个小的输入块在重叠区域对预测结果做平均再拼回完整的概率体。这样可以平滑掉切片间的突变。三维重组合并时我还会把预测概率体做一个中值滤波窗口大小设为3×3×3只对概率值做轻微平滑不改变最终二值化阈值。这样对消除单层噪声很有效不会像大窗口形态学那样破坏骨皮质细结构。4.2 后处理连通域与形态学去噪的取舍网络输出的是一个逐像素的概率图要得到最终分割mask通常把阈值设为0.5。但医学图像预测里偶尔会出现一些孤立的小区域假阳性特别是在肌肉组织边缘。我增加了两步后处理。第一步是连通域保留。椎体在二维切片上会形成一个明显的连通区域如果某些预测区域体素数量低于设定的最小阈值比如3D下小于1000个体素就直接删除。这一步对清除背景中的零散伪影非常有效。第二步是形态学开口与闭操作。这里要特别谨慎椎体边缘本身很薄如果闭操作核设得太大会把相邻椎体之间的缝隙填上导致黏连更严重。我用的核是3×3的椭圆形结构元素只做一次开操作去掉边缘毛刺不做闭操作因为闭操作在椎体场景里基本弊大于利。from scipy import ndimage def postprocess_volume(pred_prob, threshold0.5, min_volume1000): mask pred_prob threshold mask ndimage.binary_opening(mask, structurendimage.generate_binary_structure(3, 1)) label_im, num ndimage.label(mask) sizes ndimage.sum(mask, label_im, range(num 1)) mask sizes min_volume return mask[label_im]4.3 改进前与改进后的效果对比我用同一套训练数据分别训练了三个版本原始UNet、UNetSE、UNetSETransformer。数据增强、损失函数和训练轮数完全一致保证对比公平。模型Dice验证集IoUHD95毫米原始UNet0.8830.7842.87UNetSE0.9010.8092.31UNetSETransformer0.9320.8621.54从表中可以看出只加SE模块时Dice提升了约1.8个点边界质量有所改善再加上Transformer后Dice又提升了约3.1个点HD95明显下降。Transformer带来的提升不只是数值上的我特意观察了胸腰段相邻椎体的分割结果改进前那种“相邻椎体边界糊在一起”的情况基本消失了椎体间的间隙被明确分割出来。这种现象的解释也简单SE让网络更关注椎体相关通道减少背景干扰所以假阳性下降Transformer让网络建模椎体之间的相对位置关系即使相邻椎体灰度相似也能根据全局上下文把它们掰开所以边界的拓扑错误得到修复。两者的贡献并不重叠组合使用的价值大于各自独立使用之和。5. 训练和部署中踩过的坑给后来者的避坑清单5.1 方向不一致复现时最容易翻车的地方这个坑我损失了整整一周。项目第一阶段我交付了一套代码和训练好的模型权重合作方拿自己的新数据去推理结果发现预测出的椎体左右方向整体颠倒了。排查了很久最后发现是对方数据的NIfTI方向和我训练数据不一致。我训练时默认所有输入都在RAS方向但对方的数据是LAS方向SimpleITK读取后坐标系不同又没有在读数据时统一处理。从那之后我每次训练和推理前都会强制加一行重定向预处理读入体数据后先用SimpleITK把方向统一为RAS再取numpy数组。不管是公开数据集还是甲方数据先做这一道工序再进入模型。5.2 归一化参数不该拍脑袋刚开始我图省事想把CT数据像自然图像一样直接除以255。结果训练时损失下降很快但验证集Dice一直上不去。后来拆开排查才发现CT的HU值范围太大了直接除以255等于把大部分骨组织都压成了接近1的饱和值网络根本学不到区分度。改用[-250, 1500]窗口裁剪后问题立刻缓解。这里也提醒一句不同影像设备的CT值虽然理论上很接近但骨密度校准还是会有细微差异。如果你跨设备跨医院泛化可以在预处理时加入随机的窗宽窗位扰动作为数据增强让网络更鲁棒。实测加了之后跨设备推理的HD95下降了约0.5毫米。5.3 模型部署到CPU或不同设备时的注意事项训练用的模型是在GPU上跑的但实际推理环境可能是CPU或者显存受限的GPU。我的模型在GPU推理一张256×256切片大概需要0.4秒在纯CPU上则需要2秒左右。如果你的项目说明书里要写“运行环境要求”建议明确标注最低显存、推荐显存、CPU推理参考速度避免合作方部署时踩“显存不足”的坑。另外我把Transformer模块的推理做了一点小优化在窗口注意力推理时先用padding把特征图补齐到能被窗口大小整除推理后再切掉多余部分。这个处理在训练时也必须保持一致否则训练和推理的特征分布会有偏差这个偏差虽然不会让模型崩掉但会让边界预测变得不稳定。5.4 数据增强与过拟合的平衡180例数据对医学影像分割来说并不算特别多虽然引入了SE和Transformer但Transformer模块参数较多训练后期如果不做任何数据增强验证集Dice会停止上升甚至回退。我使用的增强包括随机旋转±15度、随机缩放0.9-1.1倍、随机水平翻转、随机亮度对比度扰动、随机弹性形变。其中弹性形变对椎体分割效果帮助很明显因为不同患者的脊柱弯曲程度不一样弹性形变模拟了一部分生理形态变异。需要特别注意医学分割的标签是几何结构几何增强旋转、缩放、弹性形变和灰度增强亮度、对比度可以同时开但灰度增强幅度不能太大否则CT值对应的组织含义会被破坏。很多人习惯拿自然图像那套增强策略直接套医学图像往往把窗宽窗位信息增强乱导致网络把骨骼和软组织混淆。5.5 项目说明书里除了公式更应该写什么标题里提到的“项目说明书”我后来整理成了四块内容项目概述任务、数据来源、验收指标、算法结构UNetSETransformer的框架图和每个模块的输入输出维度、环境与依赖Python、PyTorch、SimpleITK、scipy的版本、复现步骤从原始nii.gz到最终评估指标的完整命令和脚本调用顺序。这四块里最容易忽视的是版本依赖和复现步骤。我交过好几版项目深知算法部分写得再天花乱坠如果依赖库版本不锁死、复现步骤不完整对方依然跑不起来。所以在项目说明书里我把具体依赖库版本写成表格把每个脚本的输入路径、输出路径、运行时间、显存占用都写清楚甚至把最终结果文件的长相也截图放进附录里。这一点听上去很琐碎但实际交付时能让对方少发几十条咨询消息。6. 这个项目还可以继续往哪个方向走脊椎分割目前只做了二分类的分割验证但临床场景里往往还需要知道“这是第几节椎体”“椎间盘是否有突出”“椎体是否有压缩性骨折”。如果你想把项目再往前推一步可以考虑把单椎体标签作为多类别分割来训练让SE和Transformer同时承担“分类定位”的功能也可以把三维卷积或者预训练权重加进来在数据量充足时进一步缩小HD95。我个人的体会是UNetSETransformer这套组合最大的价值不是网上常说的“涨点”而是在几乎不改变原框架的前提下用两个很克制的模块把UNet在特定任务上的短板补齐。这个思路可以迁移到其他器官分割、血管分割甚至工业质检里先找到当前模型的明显失误类型再去选对应的结构改动而不是一味堆大模型。如果让我再重来一次我依然会先拿普通UNet跑一版把错误可视化再决定加什么模块。因为只有清楚了模型错在哪改进才有方向指标才有说服力。本文还有配套的精品资源点击获取