☰
3D医学影像分割的自监督预训练:自适应分层掩码建模实战
2026/10/19 9:59:53 网站建设 项目流程

做 3D 医学影像分割的同行,最近应该都绕不开“自监督预训练”这个词。我今年把一套代号 GMIM 的方案从预训练一路跑到了下游分割微调,整体踩过的坑、调过的参数、验证过的设计思路,整理成这篇偏实战的记录。GMIM 的思路概括起来是三件事:3D 医学图像分割、自监督预训练、自适应加分层的掩码建模。它解决的核心问题很直接:标注样本不够时,怎么让模型在无标注数据上先把解剖结构、边界细节这些通用知识学好,再用少量标注做分割也能达到不错的效果。这篇文章适合正在搞医学影像算法、被标注数据稀缺卡住的项目,或者想在三维体数据上尝试预训练的同学。我不做论文复述,就讲个人怎么理解、怎么落地、怎么避坑。

做医学影像标注的人都知道,一例三维 CT 或者 MRI 的精细分割,不是画几笔就能交差的。肝、肺、血管、病灶一圈一圈标下来,熟练工也要大半天,还要医生复核。大多数项目最终能拿到的干净掩码,常常只有几十例。几十例数据直接训练一个 3D 分割网络,别说 Transformer 结构,就是传统 U 形卷积也容易过拟合。自监督预训练的出现,就是先把“没有标注但有结构”的海量数据用起来,让模型在预训练阶段学会图像本身的规律。GMIM 这类方案的核心价值,就体现在这种“先自学,再少量监督”的流程里。

1. 拆解 3D 医学分割预训练:为什么会需要“自适应+分层”

1.1 医学影像标注的痛点和预训练的定位

3D 数据的特点可以概括成“大、稀、贵”。大,是体素规模大,一个 512×512×300 的扫描就是七千多万个体素;稀,是目标组织往往只占很小比例,背景、空气、脂肪占大头;贵,指人工标注成本极高。正因为这样,医学影像预训练不能照搬自然图像那套。自然图像的预训练模型通常是在二维网络上做的,把三维体数据切成切片再来用,等于主动丢掉了 z 轴方向的连续性,分割器官边界时很容易出现层间不连续的问题。

我这边一开始也试过直接用图像分类的预训练权重做初始化,效果一般。问题在于分类任务要求的是“这张图是什么”,而分割任务要求的是“每个体素是什么”,两者的表征粒度完全不同。自监督掩码建模则不一样,它的伪任务是“把挖掉的区域补回来”,强制模型理解局部结构、全局上下文、边界连续性,这些恰恰就是分割所需要的底层能力。GMIM 正是把这一思想用在了三维场景上,所以从定位上讲,预训练阶段学的不是标签,而是解剖结构的“语法”。

1.2 对比学习和掩码重建,GMIM 为什么选了后者

做自监督有两条主要路线,对比学习和掩码重建。对比学习通过数据增强构造正负样本对,把同一图像的不同视角拉近,把不同图像推开。在自然图像分类里,这条路曾经很火,但放到医学分割里有个明显短板:同一部位的三维图像在全局上太相似了。所有肝的 CT 看上去都差不多,对比学习很容易找到捷径——比如只凭体素强度直方图或者边框位置就完成判别——而不用真正理解器官边界和形状。

掩码重建没有这个问题。让网络去还原被挖掉的区域,它必须知道“这个位置原本应该有血管、有胆管、边界过渡应该是什么样的”。重建出来的图像越真实,说明模型对结构理解越深入。GMIM 选择站在掩码重建这一边,又针对三维数据做了两个改进:一个是自适应掩码,一个是分层重建。这两个改进的目的,都是让预训练出来的特征从“能重建”变成“对分割有用”。

1.3 “自适应”和“分层”到底解决了什么

随机掩码在自然图像上勉强能用,因为自然图像信息分布相对均匀,天空、草地、物体都包含有效纹理。但三维医学图像不是均匀的,可能全图 90% 都是空气和背景。随机挖块,大概率挖到的是没信息的地方,模型用周围平滑过渡一下就能补回来,根本不用理解器官结构。自适应掩码的思路,是让模型先判断哪些区域结构信息丰富、恢复难度大,再优先挖这些区域。相当于把有限的训练预算花在最有价值的地方。

“分层”解决的是尺度问题。如果只在网络最深层输出一个重建结果,模型学到的是大致轮廓,对小血管、肋骨边缘这种高频细节不敏感。GMIM 把编码器的不同阶段拿出来分别做重建:浅层恢复局部细节,深层恢复全局形状。这样预训练阶段就已经在模拟分割解码器的多尺度行为,下游微调时自然更顺。说白了,自适应找难点,分层学细节,两者配合起来,预训练出的骨干才真正是给分割任务准备过的。

2. 核心机制拆解:自适应掩码和分层重建怎么配合

2.1 自适应掩码的计算过程

实际实现时,输入不是整个三维体,而是切成固定大小的 patch,比如 96×96×96。patch 内部再按 16×16×16 划分 token。普通掩码就是随机把这些 token 按比例遮掉,自适应掩码需要额外一步“复杂度评估”。

我的做法是让输入先经过一个浅层卷积块,拿到每个 token 的局部特征,然后给每个 token 算一个分数。分数可以取局部梯度幅度、方差或者高频能量。梯度幅度大说明边缘密集,很可能就是器官边界;方差大说明纹理丰富,结构复杂。把分数从高到低排序,按预定掩码比例选出最高的一批 token 作为候选掩码区域。

这里有个容易翻车的细节:如果全部按高复杂度选,掩码会集中在边界和纹理区,网络很快就会发现“被挖的总是边界”,反而学会投机。我习惯做一个混合策略,比如 70% 的掩码来自高复杂度 token,30% 随机选。这个比例可以调整,我管它叫自适应强度,一般从 0.7 起步。太低了退化成随机掩码,太高了训练不稳定。

评估器也不用单独训练。最开始随机初始化的评估器给出的分数可能没什么意义,但主网络在重建损失上更新时,评估器也跟着一起更新。跑大概几十个 step 之后,分数分布就明显拉开差距了。这算是比较省事的设计。

需要注意,自适应掩码比随机多跑一次轻量前向,会带来额外显存和时间开销。如果 GPU 比较紧张,可以把复杂度评估放到低分辨率特征上做,或者每隔几步才更新一次评估结果,用缓存代替实时计算。实测下来,评估结果隔几个 step 更新一次,对最终效果影响很小,但显存压力能降不少。

2.2 分层重建的目标设定

分层重建要求编码器本身是多阶段的。3D ViT 可以在不同层引出特征,卷积骨干就在不同下采样层级引出。解码端我用了三条分支:

最浅的分支从编码器早期特征出发,重建高频分量,可以理解为把边缘和纹理画清楚。中间分支重建中等粒度特征,对应器官的局部形态。最深的分支从顶层特征重建低分辨率整体,让模型把全局布局和各器官相对位置搞明白。

这样做的好处是缓解了特征层的“责任不清”。单尺度掩码重建往往只在最后输出算损失,中间层特征缺少监督,底层有细节但缺少语义引导,高层有语义但容易忽略小目标。分层重建把责任明确分配下去,每一层都知道自己该学什么,特征表达能力自然更强。

实现时不需要真搞三套完整解码器,那样参数太多。我用的是共享权重的轻量 MLP 解码器,不同层之间只加不同的归一化层。重建目标也不是让每个分支都去复原原始图,而是让浅层分支预测高频残差,深层分支预测降采样后的低频结构。高频残差可以通过原图减去高斯模糊图得到,这样预训练任务被拆成了“学细节”和“学结构”两个子目标,和分割任务的一致性很高。

2.3 损失函数组合与权重考虑

损失函数不能只靠一个 MSE。MSE 太平滑,对小区域的误差不敏感;但也不用追求复杂。我最后留下来的是这样一组:

主重建损失用 L1 或者 MSE,给权重 1.0;中间分支加一个结构相似度损失,权重 0.2 到 0.5;如果显存允许,再加一个辅助对比项,权重 0.1 左右,用来拉近同一结构不同位置的局部特征。辅助项权重宁小勿大,加太大容易干扰主任务,让重建结果出现塌陷。

训练时要把几个损失曲线都打出来看。如果结构相似度在下降但主重建损失不降,说明辅助项权重过高,压过了主任务。如果主损失下得快但微调效果一般,往往是因为任务太简单,掩码比例偏低,或者自适应强度不够。损失是表象,背后的结构理解程度才是关键。

3. 从预训练到微调:GMIM 全流程实操与参数选择

3.1 数据准备与预处理要点

预训练阶段不需要标签,但数据整理比有监督训练更讲究,因为你要让模型从头建立结构认知,数据质量直接影响预训练特征质量。

第一步是统一格式。所有三维数据转成同一种存储格式,同时保留体素间距信息。CT 和 MRI 的 spacing 差异很大,尤其是 z 轴方向,CT 经常是 1mm 到 5mm 不等,MRI 更复杂。如果不统一,token 覆盖的空间范围在不同样本上不同,模型学到的结构就不是真实解剖比例。

第二步是重采样。我习惯把预训练数据重采样到各向同性,哪怕稍微降低分辨率,比如统一到 1.5mm。各向同性意味着 x、y、z 方向的分辨率一致,这样网络对三个方向的感受野才一致。如果计算资源有限,至少也要把 z 轴和 xy 轴的比例统一,否则三维卷积核很难处理各向异性的形变。

第三步是裁剪。用简单的阈值方法找出包含人体组织的包围盒,把这个区域裁出来,再去采 patch。这样能避免 batch 里混入大量纯空气样本。CT 的阈值可以用 -200 到 300 之间的体素范围做粗筛,MRI 可以用百分位截断后做粗筛。

第四步是归一化。CT 用窗宽窗位截断,把超出上下界的体素值拉回来,再做 z-score。MRI 没有标准窗宽,用 0.5% 到 99.5% 百分位截断可以压掉偏置场带来的极端值。最后做了个归一化后,还要确认体素值分布不会因为设备差异出现整体平移。

第五步是 patch 采样。随机从裁剪后的体数据里采 96×96×96 大小的 patch。如果目标器官偏小,可以做中心加权采样,提高器官区域被采中的概率。预训练阶段不需要做强的在线增强,偶尔做随机的镜像翻转就够了,因为掩码重建本身已经是强正则。

3.2 预训练参数与训练流程

给出一组我这边实测能稳定跑起来的配置参数,仅供参考,具体还要根据数据量和显存调整:

编码器选 3D ViT-Small 或者 Base 规模,token 尺寸 16³,可见 patch 96³。自适应强度 0.7,掩码比例 0.6 起步,训练过程中线性升温到 0.75。优化器用 AdamW,学习率 1e-4,前 10 个 epoch 做 warmup,后面接 cosine 衰减。总训练步数在 100k 到 200k 之间,200 例左右无标注数据时,100 个 epoch 基本够收敛。

batch size 是三维预训练最头疼的问题。96³ 的 patch,single GPU 能放下的 batch 往往只有 4 到 6 个。不要硬撑大 batch,我用梯度累积把有效 batch 模拟到 16。注意梯度累积时要用真实 batch 的平均而不是累加,否则学习率效应会被放大。

精度方面用自动混合精度。3D 卷积和注意力在 float16 下有时会有精度损失,尤其是反卷积上采样阶段。我会在损失计算和最后的几个解码层保留 float32,避免梯度不稳定。

预训练过程里要定期看重建效果。不是只看损失数值,而是把模型的预测结果可视化。如果重建出的图像边缘糊成一团,说明模型没有学会高频细节;如果整体布局错误,说明全局结构还没建立起来。可视化是发现训练异常最直接的方式。

3.3 下游分割微调与评估

微调时,保留预训练 encoder 的权重,随机初始化解码器。我习惯分两阶段:先冻结 encoder,只训练解码器 10 个 epoch,让新初始化的解码器先适配预训练特征的分布;然后解冻 encoder 全量微调。解冻时学习率降一个数量级,比如从 1e-4 降到 1e-5,避免大范围破坏预训练权重。

损失函数用 Dice 加交叉熵的组合。Dice 对类别不平衡更友好,交叉熵能提供更稳定的梯度。加权的比例可以从 1:1 开始调。如果小目标容易漏检,可以把 Dice 换成多尺度 Dice,在不同分辨率上分别计算,增强对小器官的监督。

评估时不能只看整体 Dice。医学分割里,整体指标会被大器官主导,肝和脾标得好一点,整体 Dice 就上去了,血管和小转移瘤的进步根本体现不出来。我习惯把指标拆到单个结构,分别统计 Dice、HD95 和标准化表面距离。HD95 对边界质量敏感,表面距离对小结构更严格。

同时要做样本效率曲线:分别在 5%、10%、20%、100% 标注比例下微调,对比从零训练、随机掩码预训练、GMIM 预训练三者的表现。这条曲线比单一实验更能说明方案的适用场景,也能用来判断到底是预训练本身有效,还是单纯的参数初始化带来的偏差。

4. 踩坑记录:显存、掩码比率与小结构漏检的排查清单

4.1 显存不够用怎么办

三维预训练几乎必然遇到显存问题。算一个 token 就需要把整个 3D 特征图存在显存里,掩码重建还要额外开解码器。我第一次跑的时候,batch 只要取到 8,刚进去就 OOM。解决起来有几个方向:

把 patch 尺寸从 96³ 降到 64³,显存直接少一半多。代价是视野变小,预训练学全局结构的能力变弱,所以能不降就不降。

对评估器用梯度检查点。自适应掩码的前向评估可以每两三个 block 存一次激活值,反向时重新计算,显存省下不少。

把高频和低频重建分支简化。如果两个分支都做标准卷积解码器,参数量和激活值都不小。我后来把高频分支换成了只有一个卷积层的轻量卷积头,效果没降,显存下来一截。

如果显存还是不够,就减少有效 batch 而不是减少 patch 尺寸。梯度的方向在小 batch 下虽然有噪声,但配合 AdamW 和 warmup,预训练阶段影响不大。

4.2 掩码比率和自适应强度怎么调

掩码比率太低,任务太简单,loss 降得快但特征学不到深层次结构。掩码比率太高,任务难度过大,模型只能恢复低频背景,高频细节一片模糊。我实测下来,3D 场景的合理区间在 0.6 到 0.8。低于 0.5,下游微调几乎没有提升;高于 0.85,预训练损失会明显不稳定。

自适应强度也需要跟着调。强度太大时,掩码集中在纹理区,模型学会的是“纹理区就是要重建的区域”,迁移效果反而差。我后来把自适应强度改成 schedule:预训练前期用 0.5,让模型先适应随机掩码的基础任务;后期升到 0.8,让模型更多地在难点区域上加强训练。这种渐进式设置比固定 0.7 更稳,最终微调结果有小幅提升。

不同器官结构对自适应掩码的响应也不一样。血管和胆管这类管状结构,边界细、在体素占比极小,复杂度评分很容易识别出它们,但重建时又容易因为体素太少而被忽略。如果发现这类结构分割效果差,可以在预训练中额外增加一个局部重建分支,专门随机选取 32³ 大小的迷你块,以更高分辨率重建,把管状结构单独强化一遍。

4.3 小结构漏检和类别不平衡

整体指标好看,小结构一塌糊涂,这是三维分割最常见的现象。第一阶段也别急着改模型,先确认是不是标签本身的问题。小结构标注的漏标率很高,医生在切片上画血管时,经常出现层间断裂,这种标签噪声会让模型无所适从。

排除了标签问题后,再做针对性处理。微调阶段要做小结构密集采样,每批数据里保证一定比例来自小器官中心区域。损失上,多尺度 Dice 加上边界加权。预训练阶段,可以小幅调高自适应强度,让模型把更多注意力放在边缘和细节区域。不过我后来发现,对小结构收益最大的其实是数据增强——在预训练和微调里把弹性形变和随机缩放加上,管状结构的扰动更接近真实变异,模型对这类结构的鲁棒性提升明显。

4.4 训练不稳定与复现问题

预训练 loss 突然跳高、重建图像出现花斑、甚至 loss 直接变成 NaN,这些问题都遇到过。排查顺序我整理成了表,遇到问题直接按这个顺序查。

问题的常见来源有两个:一是学习率过大,二是 BatchNorm 在 batch 很小时不稳定。前者看 loss 曲线,出现尖峰基本就是学习率问题,可以把 lr 降到 3e-5 重跑一段。后者更隐蔽,BatchNorm 在小 batch 上统计量波动很大,到后面可能出现 shift 不匹配,改成 LayerNorm 或者在预训练阶段用尽量大的 batch 会更稳。

此外,3D 数据的随机增强和随机裁剪会改变体素强度分布,如果数据加载顺序没有固定随机种子,同一批数据在不同运行时得到不同结果,复现就很困难。我后来统一了随机种子、数据加载顺序、增强参数,每次跑实验前把这三样固定下来。模型权重保存上也注意不要只看最后一个 epoch,最好保存验证重建指标最好的那个权重,微调时用那个权重初始化,效果往往会优于最后一个 epoch 的权重。

现象排查方向常用处理
Loss 中途飙高或 NaN学习率、梯度爆炸降低 lr,加梯度裁剪
重建图花斑、噪点密布高频分支学习不稳高频分支保留 float32,降低结构相似度权重
预训练正常但微调无提升掩码比例低或任务过简单提高 mask ratio,提高自适应强度
复现结果不一致随机种子、数据顺序、增强固定随机种子和增强队列,统一预处理
显存 OOMpatch 过大、batch 过大梯度检查点、降 batch、简化解码头

5. 用数据判断收益:样本效率曲线和适用场景

5.1 样本效率曲线怎么看

我强烈建议任何预训练项目都先做一条样本效率曲线。用同一份数据,分别取 5%、10%、20%、100% 的标注做微调,对比三种初始化策略:从零训练、随机掩码预训练、GMIM 预训练。曲线画出来以后,方案的收益一眼就能看出来。

在我做的模拟项目 X 中,5% 标注时从零训练的分割结果几乎不可用,某些结构 Dice 只有 0.1 到 0.2,而 GMIM 预训练之后还能保持在 0.4 到 0.5 的量级,差距非常明显。标注比例到 20% 时,差距缩小到两个百分点左右;100% 时差距几乎消失。这个规律很有代表性:预训练收益主要体现在低标注场景,标注越充足,收益越小。

所以做方案选型前先想清楚,你到底做的是低标注场景项目,还是已经有大量精细标注的项目。前者值得花时间做预训练,后者可能直接把训练时间花在数据增强和超参调优上更划算。

5.2 收益递减和不适用的场景

GMIM 这类预训练不是万能药。我踩过几次坑之后,总结出几个不太适用的情况:

如果预训练用的数据分布和下游任务差别很大,比如用 CT 预训练,下游任务却是 MRI,收益会明显缩水。三维医学图像信号来源差异很大,没有模态适配机制时,跨模态迁移要谨慎验证。

如果目标病灶极其罕见,预训练数据里几乎没有出现过类似结构,靠自监督重建学不到病灶的特征,此时预训练帮助有限,不如把有限精力放在数据增强和半自动标注上。

如果计算资源非常紧张,预训练的综合成本需要仔细核算。一个 96³ patch 的预训练通常要跑几天到几周,如果团队只有一块卡,要评估是不是值得为几个百分点的提升付出这么多时间。有时候直接做半监督训练或者用更强数据增强,投入产出比反而更高。

5.3 做 GMIM 预训练的一点个人心得

跑完整个流程后,我觉得最值得分享的经验有两条。第一条,预训练数据尽量和下游数据保持同一模态、同一部位。跨部位预训练的效果不算差,但同部位的效果明显更稳。第二条,mask ratio 做 schedule 非常有用,从低到高逐步升温,比固定比例稳定得多,最终效果也更好。

另外想提醒一点,做一次预训练的成本不低,但它可以复用到多个下游任务。我当时用同一个预训练权重初始化了肝脏分割、血管分割和病灶检测三个模型,每个都省下了不少从头训练的时间。如果项目要长期维护多个分割模型,花一次预训练的成本把公共骨干做好,整体是划算的。这个项目跑完之后,我最大的体会是:标注稀缺时,与其加班标数据,不如先让模型自己在无标注数据里多学点结构,GMIM 这类方案的价值就在于此。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询