事情是从我们手里那批CT片子开始的。科室里囤了上万例高质量的腹部CT,完整标注过器官边界的,满打满算不到60例。请一位影像科医生逐层勾画胰腺轮廓,一人一天最多处理三五个病例,医生的临床工作还没法停。这个场景在医学图像分割领域太常见了:未标注数据像一片大海,干净标注像几瓢水。这两年我特别关注顶会上医学图像分割方向的投稿,一个非常明确的趋势是,半监督学习(Semi-Supervised Learning, SSL)几乎成了标配——用少量标注样本加上大量未标注样本训练,分割精度能逼近甚至赶超全监督。即便是在视觉大类那几个会议的医学影像分方向,一致性正则、伪标签、不确定性估计这些关键词也刷屏一般地出现。这篇文章不打算复述某篇论文的摘要,而是把我这几年实际做半监督医学图像分割的思考、方法论和踩坑细节串一遍,给正在用较少标注做器官分割、病灶检测的同行一份能直接上手的参考。1. 为什么医学图像分割会被半监督学习"点中死穴"1.1 标注成本与专家依赖医学图像分割和自然图像分割最大的区别,不在算法,在标注的源头。自然图像你可以让一群众包标注员用多边形框物体,错几条边线顶多框得不完美,不影响训练。医学图像完全不是这么回事:一是像素级逐层勾画本身就慢,一个CT序列动辄两三百层,器官边界细微且粘连,比如胰腺、胆囊这些位置不固定的结构,连熟练医生都要反复翻动相邻切片确认边界;二是能标注的人极其有限,得是懂影像知识的医生或经过严格培训的专职标注员,普通外包人员面对分辨率低、噪声大的B超图像根本分不清组织结构;三是还存在标注者间的一致性(inter-observer variability)问题,同一张片子两位医生画出的边界可以差出几个毫米,这直接影响评测的可靠性。我见过的一个实际项目里,给一个包含500例肝脏CT的数据集做精细标注,两位影像科医生外加一位规培生,花了大半个月才交付第一版。按这个节奏,几千例甚至上万例数据想要全标注,基本是机构级别的大工程。这也是为什么公开数据集动辄只有几十例、一两百例带标签,剩下的大规模影像数据全是"裸奔"状态。1.2 数据的"贫富差距":少量标注,海量未标注大医院一天能产生的影像数据量,按TB算。这些数据缺的不是数量,是标签。关键点在于,这些未标注数据不是没用的噪声,恰恰是最宝贵的"本地分布"样本。它们和你最终要部署的场景出自同一批设备、同一套扫描协议、同一种患者人群。公共数据集再干净再完整,也经常和你的目标数据之间存在领域偏移(domain shift),比如同一器官在不同厂商设备上呈现的灰度、噪声纹理都有差异。与其强行把公共数据集的标签"借"过来用,不如想办法把你自己的海量未标注数据用起来。半监督学习正好干这件事。另外,医疗数据还有隐私合规约束,原始影像往往不能轻易离开医院环境。这也导致"从外部获取更多人工标注"这条路走不通。现实就是:本地数据长得像一座待挖的矿山,但只有几个人的标注,剩下的全得靠方法自己消化。这就是为什么顶会上的医学分割论文,大量转向半监督——不是追时髦,是需求逼出来的。2. 半监督分割的底层思路:从"模仿标准答案"到"利用数据本身的声音"2.1 一致性正则化的基本假设半监督学习能成立,前提是三类假设:平滑性假设、聚类假设、流形假设。通俗讲就是:相似的输入应该得到相似的输出,同一个样本做一点不影响语义的改变,语义也应该不变。一致性正则化(consistency regularization)是这套假设最直接的操作形式:对输入图像施加某个"不影响语义"的扰动,要求模型对扰动前后的预测保持一致。拿医学图像举例,你把一张腹部CT水平翻转、旋转几度或者调整一下窗宽窗位的对比度,肝脏还是肝脏,胰腺还是胰腺。把两张预测图"对齐"后拉近,模型就从"纯靠标签学"变成了"从数据自身的几何不变性里学"。这个思路和自监督学习有点像,区别在于半监督一致性正则化不要求学出通用的表征,而是直接约束最终分割输出的一致性。好处是任务目标明确,坏处是如果扰动方式不对,模型很容易学到"偷懒"的解。比如对整个背景区域施加一致性约束,那模型直接预测全背景就能把无监督损失压得很低,这显然不是我们要的。2.2 伪标签与置信度的博弈另一条主路是伪标签(pseudo-labeling)。做法粗暴直接:用当前模型对未标注数据做预测,把预测结果当作标签,再拿这些伪标签去监督模型本身。这本质上是自训练(self-training)的现代版。听上去像"左脚踩右脚上天",但确实有效。不过它有一个致命问题:确认偏误(confirmation bias)。模型刚开始只有少量标注可以学,预测里必然混着系统性错误。如果拿这些包含错误的结果去训练自己,错误会被一遍遍放大,最后整个模型朝着错误方向漂移,连原本那点标注信息都被覆盖掉。缓解办法也有好几层。最常用的是置信度门控:只有softmax预测概率高于阈值(比如0.8)的像素才被当作有效伪标签,低置信度区域直接忽略。这个策略本身没毛病,但在医学场景有个特殊风险——病灶区域往往是低置信度的。小肿瘤、早期病灶边界模糊,预测概率天然不高,一刀切的置信度阈值很容易把最该关注的稀有小目标全部滤掉。正确做法是分区域、分类别设置阈值,比如背景用0.9,器官边缘用0.7,病灶用0.5,或者统计每个类别的置信度分布后再定阈值。2.3 医学场景的特殊优势很多讲半监督的文章举的例子都是图像分类:一张图一个标签,一万张未标注图在一万个样本点位上提供约束。医学图像分割不一样,一张分割图里有几十万像素,每个像素都是一个预测样本。换句话说,一张未标注CT能产生几十万条"虚拟监督信号"。同样是一致性正则,作用在分割任务上,每个样本的信息量比分类任务大几个数量级。这也是半监督在分割上效果比分类上更明显的原因之一。更别说医学图像自带解剖先验:器官的形态、相对位置、左右对称性都是可用的约束。同一器官在不同患者身上的位置和形状虽有变化,但不会出现"肝脏长到脾脏位置"这种事。把这种先验通过几何扰动、形状平滑项注入模型,能让伪标签噪声进一步被抑制。还有一些工作利用多模态数据做交叉视图一致性,比如T1和T2加权MRI天然就是同一个解剖结构的两种"视角",对一种视角做预测,去约束另一种视角的特征——这基本就是为医学影像定制的一致性正则。3. 主流技术路线拆解:顶会论文里都在做哪几件事3.1 在哪个层面加扰动:图像级、特征级、模型级一致性正则要有一个"扰动对"。往哪个层面加扰动,决定了方法的性格。图像级扰动是最直觉的。几何变换、强度扰动、弹性形变、窗宽窗位抖动,这些都是医学分割里验证过的有效扰动方式。新一代方法还会用CutMix类的混合增强:把两张图的部分区域拼起来,要求模型的预测也要对应拼接,起到类似"插值监督"的作用。特征级扰动比较精细,典型做法是在特征图上加噪声、随机丢弃某些通道,或者对编码器的中间层做结构化遮挡。这相当于在语义特征空间里做一致性约束,往往比在像素空间里扰动更轻量,却更能逼迫模型学到不变性。我个人经验是,特征级扰动特别适合数据本身灰度分布敏感的模态,比如超声图像。模型级扰动最有名的是Mean Teacher结构:一个"学生模型"负责学习,一个"教师模型"由学生权重的指数滑动平均(EMA)得到。每轮迭代,学生模型在同一个输入上做预测,教师模型也做预测,然后拉近两者的输出分布。教师模型因为权重是历史平均,预测比当前学生更稳定,天然是个更好的"答案来源"。这套结构的变体是很多顶会医学分割方法的地基。扰动层级实现方式强度控制典型做法图像级几何/灰度/混合增强直观,好调翻转、弹性形变、CutMix、窗宽窗位抖动特征级特征噪声、通道丢弃需要看分布Dropout、特征遮挡、通道扰动模型级参数滑动平均、双模型稳定,成本略高Mean Teacher、双分支相互蒸馏3.2 从"平均预测"到"不确定性感知"一致性正则再强,也架不住某些未标注样本本身模糊难判。这时研究者的思路转向了不确定性。不确定性估计在医学分割里有一条经典路线:蒙特卡洛Dropout(MC Dropout)。训练时保留Dropout层,推理时多次前向采样,对同一个输入得到多个预测,计算这组预测的均值和方差,方差就能近似刻画模型在这一区域的置信程度。把这个不确定性当成权重,参与一致性损失或者伪标签的筛选,就构成了"不确定性感知的半监督"。举个例子:某个像素预测的softmax概率是0.7,看着还行,但十次MC采样里五次偏向类别A五次偏向类别B,那这个像素的伪标签可靠性其实很差。反过来,某像素概率只有0.6,但十次采样全部稳定指向同一个类别,那它反而是个不错的监督信号。只看概率不看方差,容易误杀或误放。这类方法在医学上的好处是双重的。一方面自动过滤了伪标签里最可疑的那部分,另一方面,产出的不确定性热图本身有临床价值——医生可以不看模型的全图预测,只看模型在哪些区域举棋不定,再针对性地人工修正,这就是"人在回路"的雏形。3.3 解码结构上的暗线:把分割当作双重任务近几年顶会上还有一个隐蔽但高频的做法:给分割模型附加辅助任务。表面上是多任务学习,实质是在用无标注数据给模型"加杠杆"。最常见的辅助任务是重建。让解码器不仅输出分割图,还要尽量重建出原始输入图像(或其中的一部分),相当于强迫编码器保留足够多的结构信息,不能只顾着分类、把纹理和形状全丢掉。重建损失的加入,相当于给无标注数据也提供了约束,模型从"分类器"变成了"理解图像结构的分割器"。另一类辅助任务是距离图、边缘图或者形状签名。比如让模型额外预测器官中心到边界的距离变换,好处是边界处的像素有了全局上下文,而不是仅仅做逐像素独立分类。这个辅助任务不需要额外标注,从现有分割标签里就能算出来,和一致性正则叠加也互不冲突。再一个是像素级对比学习:把同一图像中属于同一语义类别的像素特征拉近,把不同类别的像素特征推远。这里的关键是"哪两个像素属于同类"——在没有标签时,可以用当前模型的伪标签来定义,也可以用空间近邻来近似。看起来绕了一圈,但实测下来它能让编码器得到更平滑、更语义化的特征空间,对后续小样本场景的迁移也有帮助。3.4 几个典型做法的横向对比方案类型核心思想最大优点主要风险一致性正则(Mean Teacher)对扰动保持预测一致稳定、通用、适合部署扰动选择不当会学到平凡解伪标签+置信度筛选用高置信预测当标签实现简单、直观确认偏误,压制低置信小病灶不确定性加权伪标签用多次采样方差筛选/加权能保住模糊但有价值的信息MC采样成本高、需要调阈值重建/对比辅助任务用无监督信号锻炼编码器特征质量提升明显训练更重,辅助任务权重不易平衡说实话,顶会里单走一条路的论文越来越少,大家都在做组合拳。但在工程上我建议别一上来就上全套,先从一个稳定的基线开始,比如Mean Teacher加图像级强扰动,跑通之后再逐步往里面加不确定性筛选和辅助任务。每加一层都做消融,不然根本不知道增益来自哪里。4. 从论文到实践的落地清单:我踩过的坑与参数建议4.1 数据划分:别踩我踩过的坑论文里讲的都是理想情况:标注集和未标注集是从同一个分布里采出来的。现实里完全不是。我吃过一次大亏。一次实验里,我手头有100例来自旧扫描设备的标注CT,又找了几百例新设备上采集的未标注CT直接丢进半监督流程。结果很惊悚:加了未标注数据之后Dice反而掉了。原因不难理解——新旧设备灰度分布差了一个档次,一致性正则在"逼"模型把新设备的图像也预测成旧设备的风格,模型学了一堆自相矛盾的映射,原本在旧设备上的优势也被削弱了。教训就一句话:先检查未标注集和标注集是不是同分布。做训练前花半小时统计灰度直方图、体素间距、设备来源,该筛的筛掉,该重新预处理的重新处理。宁可未标注数据少一点,也不要混入分布外的样本。另外,如果你手上那点标注集还要分一份出来做验证,注意别为了凑监督样本把验证集弄得太小。我一般的做法是,标注集按8:2分训练和验证,未标注集全部参与无监督部分,不参与验证。选模型的时候只看验证集结果,不因为无监督损失漂亮就觉得万事大吉。4.2 网络头部的设计与损失函数配比半监督分割的损失函数,90%的情况是这样一个结构:total_loss = sup_loss + lambda_coef * unsup_loss监督损失sup_loss通常用交叉熵加Dice损失,这个组合在医学分割里已经验证得非常成熟。无监督损失unsup_loss,如果是做软的一致性约束,一般用均方误差(MSE)或者KL散度来拉近两个预测分布;如果做的是硬伪标签,就用带掩码的交叉熵,只在置信度高于阈值的像素上计算。token_ratio lambda_coef怎么设是个学问。上来就设1.0基本必崩——早期模型自己都没学明白,无监督损失太大只会把模型带偏。经典的Mean Teacher路线用的是Gaussian ramp-up策略:前若干轮收益无监督损失的权重从0逐渐升到目标值。比如训练200个epoch,前40个epoch是预热,无监督权重从0平滑升到满值。预热的本质是让模型先用有标注数据拿到一个"能看的初始化",再去消化无标注数据。还有一点容易被忽略:多尺度一致性。不少3D分割网络天然有多层解码器,你可以让无监督损失同时作用在多个尺度的预测上,低分辨率预测的损失权重适当降低。这样做的好处是梯度信号更丰富,模型在不同感受野下都被约束住,训练稳定性明显更好。4.3 批大小、归一化、伪标签更新的几个易翻车点第一个坑是BatchNorm加小批量。用3D网络做分割,GPU内存一不够,批大小容易掉到2甚至1。BatchNorm在这种小批量下统计量剧烈抖动,无监督损失也跟着抖,训练跟坐过山车似的。我的建议是3D网络优先用InstanceNorm或GroupNorm,或者在编码器前几层保留BatchNorm、解码器换成GroupNorm。别小看这个细节,它对半监督训练的稳定性影响非常大。第二个坑是伪标签的更新频率。有些实现每个iteration都重新生成一次伪标签,模型预测稍微一动,伪标签跟着变,训练目标变成"打地鼠",模型很难收敛。更好的做法是每隔几个epoch固定住伪标签,或者用Mean Teacher的教师模型来产出伪标签,教师模型权重变化慢,伪标签自然稳定。第三个坑是强弱增强的搭配。现在很多顶会方法都采用"Noisy Student"或者FixMatch式的两路结构:教师/弱增强分支负责产出伪标签,学生/强增强分支负责在这批"更难的输入"上学习。放到医学分割里,弱增强就是翻转和轻度平移,强增强可以是大幅弹性形变、强度非线性变换、局部遮挡。只有强弱搭配,模型才不会在增强面前"作弊"——它必须学到对真实解剖结构的不变性,而不仅仅是记住某个固定的灰度模板。4.4 一个可复现的参考配置下面这份配置是我在某肝脏分割任务上调出来比较顺手的组合,不敢说放之四海皆准,至少起点不低。配置项参考值说明标注:未标注比例1:9 ~ 1:20未标注太少增益有限,太多收益递减骨干网络U-Net / 3D U-Net别一上来就上超重网络监督损失0.4 * CE + 0.6 * DiceDice权重略高有利于小结构无监督损失MSE软标签用MSE更平滑ramp-up epoch数总epoch的15%~20%例如200轮里前30轮升权重无监督最大权重λ0.5~1.0取决于无标注质量置信度阈值0.8(背景),0.6~0.7(器官)按类别统计后标定教师模型EMA系数0.99~0.999批大小越小取越靠近0.999归一化GroupNorm(3D)小批量时避用BatchNorm代码骨架我也放一个,能看出训练循环的大致结构就够了。for epoch in range(max_epochs): for batch_l, batch_u in loader: x_l, y_l = batch_l x_u = batch_u # 未标注图 # 1. 教师模型对未标注图产出伪标签(不反传梯度) with torch.no_grad(): teacher_pred = teacher(weak_augment(x_u)) pseudo = torch.softmax(teacher_pred, dim=1) confidence = pseudo.max(dim=1)[0] # 2. 学生模型在强增强上预测 student_pred_l = student(x_l) student_pred_u = student(strong_augment(x_u)) # 3. 监督损失 sup_loss = ce(student_pred_l, y_l) + dice_loss(student_pred_l, y_l) # 4. 无监督一致性损失(带置信度掩码) mask = confidence > threshold unsup_loss = mse(student_pred_u[mask], pseudo[mask]) # 5. ramp-up调度 lambda_coef = ramp_up(epoch) * max_lambda loss = sup_loss + lambda_coef * unsup_loss loss.backward() optimizer.step() ema_update(teacher, student, ema_coef)这个骨架没有任何花哨成分,但对理解工程实现足够了。真正的技巧全在数据侧和权重调度里,框架本身很简单。5. 实测效果分析:10%标注能做到什么水平5.1 我是怎么测的我拿某器官分割任务做了一组对比实验,数据共1000例,标注只放开10%。三个对照组:全监督用全部1000例标注,监督下限用100例标注,半监督用100例标注加900例未标注。评价指标用Dice和HD95(95%豪斯多夫距离,衡量边界误差),结果大致如下:方案DiceHD95(mm)相对全监督Dice全监督(1000标注)0.9473.2100%监督下限(100标注)0.8826.893.1%半监督(100标注+900未标注)0.9314.198.3%这组数字的意思是,半监督把"缺标注"带来的损失弥补了七成以上。边界指标HD95没有完全恢复到全监督水平,但已经从6.8mm显著压到4.1mm。而且这是在一共只用了10%标注的前提下得到的,对于像我们这种标注资源捉襟见肘的团队来说,这笔账相当划算。但要强调,这个结果是在同分布数据、合适预热、细致调权重的前提下测出来的。换个数据集、换套设备,曲线形状可能完全不同。我在多套数据上测过,结论稳定的大方向是:只要标注和未标注同分布,半监督至少能帮你把Dice往回捞几个点,最多能回到接近全监督的95%以上;一旦分布错位,收益为负是常态。5.2 几个失败的场景:这些情况下别硬上第一类失败是未标注集里混了大量"没有目标器官"的图像。典型的比如你想分割肝脏,未标注集里却有相当比例的检查根本不含完整肝脏或属于术后状态。模型在无监督阶段会强行给这些图像画上肝脏轮廓,伪标签越学越歪,最后的Dice比不做半监督还低。这种情况不是方法的错,是数据过滤没做好。第二类失败是标注本身带有系统性偏差。我见过一个胰腺分割的数据集,标注者为了省事只勾画了胰腺体部,头和尾经常漏掉。如果把这套标注当成金标准训练1:9的半监督模型,模型会把"漏标头尾"当作正确模式泛化到未标注数据上,错误被几何级放大。半监督不会帮你纠错,反而会忠实地把你的标注偏差复制到每一个未标注样本上。第三类失败是模型容量不够。半监督的有效性建立在模型有能力从大量未标注数据里学出额外结构。如果网络本来就欠拟合,给它再多未标注数据也只是过拟合噪声。遇到这种情况,换一个更大的编码器,或者先做一轮有监督预训练再切半监督,往往比加数据更有效。5.3 指标之外:边界质量与临床可用性Dice这类重叠率指标有一个老大难问题:它不关心边界形状是否合理。一个器官预测整体和真值重叠了90%,但边缘到处毛刺,甚至出现脱离主体的飞地(floating island),Dice照样好看,临床上却根本没法用。所以看半监督实验结果,不能只看平均Dice,要把预测mask渲染出来肉眼扫一遍。我的经验法是,每次实验跑完,除了打印指标,还要随机抽20个样本把分割结果叠加在原图上做成GIF或者蒙版图,重点看三件事:边界是平滑还是锯齿状、有没有孤立的误检块、相邻器官有没有粘连。这些质量问题和Dice数字常常没有强相关。半监督训练如果无监督权重、扰动强度没调好,最容易出的毛病就是边界区域预测漂移,因为一致性损失的梯度主要来自概率分布差,对边界这种"介于两类之间"的像素格外敏感。另外,前面提到不确定性热图在这里也很有用。哪怕Dice已经很高,把不确定性和预测叠在一起看,你会发现模型对边界、对低对比度区域的"心虚"表现在热图上一清二楚。这个东西送到临床医生手里,比一个冷冰冰的Dice数字有说服力得多。6. 现在的边界与下一步方向6.1 还没被解决的问题半监督医学图像分割离"成熟到开箱即用"还有很长的路。最让我头疼的问题有三个。一是长尾类别。病灶、罕见解剖变异,这些恰好在临床诊断里最重要的东西,因为出现频率低,模型在无监督阶段对它们天然不敢给高置信度,置信度门控一开它们就被滤掉了。结果就是,半监督提上来的往往是大器官、背景这类"好学"的类别精度,而把最难的那一小块留给监督阶段去硬扛。二是伪标签标定问题。深度分割模型普遍过置信,softmax概率不能直接当作可靠性。尤其是用了Dice损失之后,概率分布常被拉得很锐利,0.9的概率其实可能只有0.7的真实精度。这意味着一切基于概率阈值的设计都隐含了"错误校准"的风险。要做到严密,需要在半监督流程里额外加一个标定(calibration)环节,但做的人少,能做好的人更少。三是评估口径混乱。论文里用不同的分割目标、不同的标注比例、不同的预训练设置,结果差距极大。一个方法在A数据集涨了5个点Dice,换个环境可能负收益。目前这个方向缺一个通行的评测协议,比来比去容易让人误判方法上限。6.2 我认为会继续发展的几个方向第一个方向是生成模型进入半监督流程。如果扩散模型能够以无标注数据为基础生成合成图像,那生成出来的样本既可控又能无限扩充,相当于把"伪标签"升级成"伪图像"。现在已经有工作在做这个方向,把生成样本和真实样本混合训练,用来缓解伪标签噪声。这条路线一旦成熟,半监督可能直接变身成"半监督+生成式增广",会把可用标注的门槛再往下压一个台阶。第二个方向是极弱监督与半监督的融合。点点击、画几笔这类极弱标注成本低得多,先用极弱标注把模型推到"能看"的水平,再用半监督把它推到"能用"的水平。很多临床合作里,医生只愿意标几个关键点和轮廓,这种融合路线更现实。第三个方向是模型自身的自我校准。不确定性估计和伪标签置信度会越来越精细,比如把不确定性和解剖先验结合,让模型在形态学不合理的预测区域自动降低置信度。这条路一旦走通,半监督训练里最讨厌的"确认偏误"会得到结构性缓解。最后说点私人体会。在这个方向泡了几年,我的感受是半监督不是一个算法,而是一整套关于"数据怎么用"的思考方式。它最迷人的地方不是那几行损失函数,而是让你重新审视手里的数据:哪些能直接当标签,哪些能通过扰动产生约束,哪些应该被丢掉。如果你想把半监督用在实际项目里,我劝你从最无聊的事情做起——先把数据分布搞清楚,把标注质量盘一遍,再谈加不加那些花哨模块。方法永远在快速迭代,数据里的坑,才是一个一个真的坑。
事情是从我们手里那批CT片子开始的。科室里囤了上万例高质量的腹部CT,完整标注过器官边界的,满打满算不到60例。请一位影像科医生逐层勾画胰腺轮廓,一人一天最多处理三五个病例,医生的临床工作还没法停。这个场景在医学图像分割领域太常见了:未标注数据像一片大海,干净标注像几瓢水。这两年我特别关注顶会上医学图像分割方向的投稿,一个非常明确的趋势是,半监督学习(Semi-Supervised Learning, SSL)几乎成了标配——用少量标注样本加上大量未标注样本训练,分割精度能逼近甚至赶超全监督。即便是在视觉大类那几个会议的医学影像分方向,一致性正则、伪标签、不确定性估计这些关键词也刷屏一般地出现。这篇文章不打算复述某篇论文的摘要,而是把我这几年实际做半监督医学图像分割的思考、方法论和踩坑细节串一遍,给正在用较少标注做器官分割、病灶检测的同行一份能直接上手的参考。1. 为什么医学图像分割会被半监督学习"点中死穴"1.1 标注成本与专家依赖医学图像分割和自然图像分割最大的区别,不在算法,在标注的源头。自然图像你可以让一群众包标注员用多边形框物体,错几条边线顶多框得不完美,不影响训练。医学图像完全不是这么回事:一是像素级逐层勾画本身就慢,一个CT序列动辄两三百层,器官边界细微且粘连,比如胰腺、胆囊这些位置不固定的结构,连熟练医生都要反复翻动相邻切片确认边界;二是能标注的人极其有限,得是懂影像知识的医生或经过严格培训的专职标注员,普通外包人员面对分辨率低、噪声大的B超图像根本分不清组织结构;三是还存在标注者间的一致性(inter-observer variability)问题,同一张片子两位医生画出的边界可以差出几个毫米,这直接影响评测的可靠性。我见过的一个实际项目里,给一个包含500例肝脏CT的数据集做精细标注,两位影像科医生外加一位规培生,花了大半个月才交付第一版。按这个节奏,几千例甚至上万例数据想要全标注,基本是机构级别的大工程。这也是为什么公开数据集动辄只有几十例、一两百例带标签,剩下的大规模影像数据全是"裸奔"状态。1.2 数据的"贫富差距":少量标注,海量未标注大医院一天能产生的影像数据量,按TB算。这些数据缺的不是数量,是标签。关键点在于,这些未标注数据不是没用的噪声,恰恰是最宝贵的"本地分布"样本。它们和你最终要部署的场景出自同一批设备、同一套扫描协议、同一种患者人群。公共数据集再干净再完整,也经常和你的目标数据之间存在领域偏移(domain shift),比如同一器官在不同厂商设备上呈现的灰度、噪声纹理都有差异。与其强行把公共数据集的标签"借"过来用,不如想办法把你自己的海量未标注数据用起来。半监督学习正好干这件事。另外,医疗数据还有隐私合规约束,原始影像往往不能轻易离开医院环境。这也导致"从外部获取更多人工标注"这条路走不通。现实就是:本地数据长得像一座待挖的矿山,但只有几个人的标注,剩下的全得靠方法自己消化。这就是为什么顶会上的医学分割论文,大量转向半监督——不是追时髦,是需求逼出来的。2. 半监督分割的底层思路:从"模仿标准答案"到"利用数据本身的声音"2.1 一致性正则化的基本假设半监督学习能成立,前提是三类假设:平滑性假设、聚类假设、流形假设。通俗讲就是:相似的输入应该得到相似的输出,同一个样本做一点不影响语义的改变,语义也应该不变。一致性正则化(consistency regularization)是这套假设最直接的操作形式:对输入图像施加某个"不影响语义"的扰动,要求模型对扰动前后的预测保持一致。拿医学图像举例,你把一张腹部CT水平翻转、旋转几度或者调整一下窗宽窗位的对比度,肝脏还是肝脏,胰腺还是胰腺。把两张预测图"对齐"后拉近,模型就从"纯靠标签学"变成了"从数据自身的几何不变性里学"。这个思路和自监督学习有点像,区别在于半监督一致性正则化不要求学出通用的表征,而是直接约束最终分割输出的一致性。好处是任务目标明确,坏处是如果扰动方式不对,模型很容易学到"偷懒"的解。比如对整个背景区域施加一致性约束,那模型直接预测全背景就能把无监督损失压得很低,这显然不是我们要的。2.2 伪标签与置信度的博弈另一条主路是伪标签(pseudo-labeling)。做法粗暴直接:用当前模型对未标注数据做预测,把预测结果当作标签,再拿这些伪标签去监督模型本身。这本质上是自训练(self-training)的现代版。听上去像"左脚踩右脚上天",但确实有效。不过它有一个致命问题:确认偏误(confirmation bias)。模型刚开始只有少量标注可以学,预测里必然混着系统性错误。如果拿这些包含错误的结果去训练自己,错误会被一遍遍放大,最后整个模型朝着错误方向漂移,连原本那点标注信息都被覆盖掉。缓解办法也有好几层。最常用的是置信度门控:只有softmax预测概率高于阈值(比如0.8)的像素才被当作有效伪标签,低置信度区域直接忽略。这个策略本身没毛病,但在医学场景有个特殊风险——病灶区域往往是低置信度的。小肿瘤、早期病灶边界模糊,预测概率天然不高,一刀切的置信度阈值很容易把最该关注的稀有小目标全部滤掉。正确做法是分区域、分类别设置阈值,比如背景用0.9,器官边缘用0.7,病灶用0.5,或者统计每个类别的置信度分布后再定阈值。2.3 医学场景的特殊优势很多讲半监督的文章举的例子都是图像分类:一张图一个标签,一万张未标注图在一万个样本点位上提供约束。医学图像分割不一样,一张分割图里有几十万像素,每个像素都是一个预测样本。换句话说,一张未标注CT能产生几十万条"虚拟监督信号"。同样是一致性正则,作用在分割任务上,每个样本的信息量比分类任务大几个数量级。这也是半监督在分割上效果比分类上更明显的原因之一。更别说医学图像自带解剖先验:器官的形态、相对位置、左右对称性都是可用的约束。同一器官在不同患者身上的位置和形状虽有变化,但不会出现"肝脏长到脾脏位置"这种事。把这种先验通过几何扰动、形状平滑项注入模型,能让伪标签噪声进一步被抑制。还有一些工作利用多模态数据做交叉视图一致性,比如T1和T2加权MRI天然就是同一个解剖结构的两种"视角",对一种视角做预测,去约束另一种视角的特征——这基本就是为医学影像定制的一致性正则。3. 主流技术路线拆解:顶会论文里都在做哪几件事3.1 在哪个层面加扰动:图像级、特征级、模型级一致性正则要有一个"扰动对"。往哪个层面加扰动,决定了方法的性格。图像级扰动是最直觉的。几何变换、强度扰动、弹性形变、窗宽窗位抖动,这些都是医学分割里验证过的有效扰动方式。新一代方法还会用CutMix类的混合增强:把两张图的部分区域拼起来,要求模型的预测也要对应拼接,起到类似"插值监督"的作用。特征级扰动比较精细,典型做法是在特征图上加噪声、随机丢弃某些通道,或者对编码器的中间层做结构化遮挡。这相当于在语义特征空间里做一致性约束,往往比在像素空间里扰动更轻量,却更能逼迫模型学到不变性。我个人经验是,特征级扰动特别适合数据本身灰度分布敏感的模态,比如超声图像。模型级扰动最有名的是Mean Teacher结构:一个"学生模型"负责学习,一个"教师模型"由学生权重的指数滑动平均(EMA)得到。每轮迭代,学生模型在同一个输入上做预测,教师模型也做预测,然后拉近两者的输出分布。教师模型因为权重是历史平均,预测比当前学生更稳定,天然是个更好的"答案来源"。这套结构的变体是很多顶会医学分割方法的地基。扰动层级实现方式强度控制典型做法图像级几何/灰度/混合增强直观,好调翻转、弹性形变、CutMix、窗宽窗位抖动特征级特征噪声、通道丢弃需要看分布Dropout、特征遮挡、通道扰动模型级参数滑动平均、双模型稳定,成本略高Mean Teacher、双分支相互蒸馏3.2 从"平均预测"到"不确定性感知"一致性正则再强,也架不住某些未标注样本本身模糊难判。这时研究者的思路转向了不确定性。不确定性估计在医学分割里有一条经典路线:蒙特卡洛Dropout(MC Dropout)。训练时保留Dropout层,推理时多次前向采样,对同一个输入得到多个预测,计算这组预测的均值和方差,方差就能近似刻画模型在这一区域的置信程度。把这个不确定性当成权重,参与一致性损失或者伪标签的筛选,就构成了"不确定性感知的半监督"。举个例子:某个像素预测的softmax概率是0.7,看着还行,但十次MC采样里五次偏向类别A五次偏向类别B,那这个像素的伪标签可靠性其实很差。反过来,某像素概率只有0.6,但十次采样全部稳定指向同一个类别,那它反而是个不错的监督信号。只看概率不看方差,容易误杀或误放。这类方法在医学上的好处是双重的。一方面自动过滤了伪标签里最可疑的那部分,另一方面,产出的不确定性热图本身有临床价值——医生可以不看模型的全图预测,只看模型在哪些区域举棋不定,再针对性地人工修正,这就是"人在回路"的雏形。3.3 解码结构上的暗线:把分割当作双重任务近几年顶会上还有一个隐蔽但高频的做法:给分割模型附加辅助任务。表面上是多任务学习,实质是在用无标注数据给模型"加杠杆"。最常见的辅助任务是重建。让解码器不仅输出分割图,还要尽量重建出原始输入图像(或其中的一部分),相当于强迫编码器保留足够多的结构信息,不能只顾着分类、把纹理和形状全丢掉。重建损失的加入,相当于给无标注数据也提供了约束,模型从"分类器"变成了"理解图像结构的分割器"。另一类辅助任务是距离图、边缘图或者形状签名。比如让模型额外预测器官中心到边界的距离变换,好处是边界处的像素有了全局上下文,而不是仅仅做逐像素独立分类。这个辅助任务不需要额外标注,从现有分割标签里就能算出来,和一致性正则叠加也互不冲突。再一个是像素级对比学习:把同一图像中属于同一语义类别的像素特征拉近,把不同类别的像素特征推远。这里的关键是"哪两个像素属于同类"——在没有标签时,可以用当前模型的伪标签来定义,也可以用空间近邻来近似。看起来绕了一圈,但实测下来它能让编码器得到更平滑、更语义化的特征空间,对后续小样本场景的迁移也有帮助。3.4 几个典型做法的横向对比方案类型核心思想最大优点主要风险一致性正则(Mean Teacher)对扰动保持预测一致稳定、通用、适合部署扰动选择不当会学到平凡解伪标签+置信度筛选用高置信预测当标签实现简单、直观确认偏误,压制低置信小病灶不确定性加权伪标签用多次采样方差筛选/加权能保住模糊但有价值的信息MC采样成本高、需要调阈值重建/对比辅助任务用无监督信号锻炼编码器特征质量提升明显训练更重,辅助任务权重不易平衡说实话,顶会里单走一条路的论文越来越少,大家都在做组合拳。但在工程上我建议别一上来就上全套,先从一个稳定的基线开始,比如Mean Teacher加图像级强扰动,跑通之后再逐步往里面加不确定性筛选和辅助任务。每加一层都做消融,不然根本不知道增益来自哪里。4. 从论文到实践的落地清单:我踩过的坑与参数建议4.1 数据划分:别踩我踩过的坑论文里讲的都是理想情况:标注集和未标注集是从同一个分布里采出来的。现实里完全不是。我吃过一次大亏。一次实验里,我手头有100例来自旧扫描设备的标注CT,又找了几百例新设备上采集的未标注CT直接丢进半监督流程。结果很惊悚:加了未标注数据之后Dice反而掉了。原因不难理解——新旧设备灰度分布差了一个档次,一致性正则在"逼"模型把新设备的图像也预测成旧设备的风格,模型学了一堆自相矛盾的映射,原本在旧设备上的优势也被削弱了。教训就一句话:先检查未标注集和标注集是不是同分布。做训练前花半小时统计灰度直方图、体素间距、设备来源,该筛的筛掉,该重新预处理的重新处理。宁可未标注数据少一点,也不要混入分布外的样本。另外,如果你手上那点标注集还要分一份出来做验证,注意别为了凑监督样本把验证集弄得太小。我一般的做法是,标注集按8:2分训练和验证,未标注集全部参与无监督部分,不参与验证。选模型的时候只看验证集结果,不因为无监督损失漂亮就觉得万事大吉。4.2 网络头部的设计与损失函数配比半监督分割的损失函数,90%的情况是这样一个结构:total_loss = sup_loss + lambda_coef * unsup_loss监督损失sup_loss通常用交叉熵加Dice损失,这个组合在医学分割里已经验证得非常成熟。无监督损失unsup_loss,如果是做软的一致性约束,一般用均方误差(MSE)或者KL散度来拉近两个预测分布;如果做的是硬伪标签,就用带掩码的交叉熵,只在置信度高于阈值的像素上计算。token_ratio lambda_coef怎么设是个学问。上来就设1.0基本必崩——早期模型自己都没学明白,无监督损失太大只会把模型带偏。经典的Mean Teacher路线用的是Gaussian ramp-up策略:前若干轮收益无监督损失的权重从0逐渐升到目标值。比如训练200个epoch,前40个epoch是预热,无监督权重从0平滑升到满值。预热的本质是让模型先用有标注数据拿到一个"能看的初始化",再去消化无标注数据。还有一点容易被忽略:多尺度一致性。不少3D分割网络天然有多层解码器,你可以让无监督损失同时作用在多个尺度的预测上,低分辨率预测的损失权重适当降低。这样做的好处是梯度信号更丰富,模型在不同感受野下都被约束住,训练稳定性明显更好。4.3 批大小、归一化、伪标签更新的几个易翻车点第一个坑是BatchNorm加小批量。用3D网络做分割,GPU内存一不够,批大小容易掉到2甚至1。BatchNorm在这种小批量下统计量剧烈抖动,无监督损失也跟着抖,训练跟坐过山车似的。我的建议是3D网络优先用InstanceNorm或GroupNorm,或者在编码器前几层保留BatchNorm、解码器换成GroupNorm。别小看这个细节,它对半监督训练的稳定性影响非常大。第二个坑是伪标签的更新频率。有些实现每个iteration都重新生成一次伪标签,模型预测稍微一动,伪标签跟着变,训练目标变成"打地鼠",模型很难收敛。更好的做法是每隔几个epoch固定住伪标签,或者用Mean Teacher的教师模型来产出伪标签,教师模型权重变化慢,伪标签自然稳定。第三个坑是强弱增强的搭配。现在很多顶会方法都采用"Noisy Student"或者FixMatch式的两路结构:教师/弱增强分支负责产出伪标签,学生/强增强分支负责在这批"更难的输入"上学习。放到医学分割里,弱增强就是翻转和轻度平移,强增强可以是大幅弹性形变、强度非线性变换、局部遮挡。只有强弱搭配,模型才不会在增强面前"作弊"——它必须学到对真实解剖结构的不变性,而不仅仅是记住某个固定的灰度模板。4.4 一个可复现的参考配置下面这份配置是我在某肝脏分割任务上调出来比较顺手的组合,不敢说放之四海皆准,至少起点不低。配置项参考值说明标注:未标注比例1:9 ~ 1:20未标注太少增益有限,太多收益递减骨干网络U-Net / 3D U-Net别一上来就上超重网络监督损失0.4 * CE + 0.6 * DiceDice权重略高有利于小结构无监督损失MSE软标签用MSE更平滑ramp-up epoch数总epoch的15%~20%例如200轮里前30轮升权重无监督最大权重λ0.5~1.0取决于无标注质量置信度阈值0.8(背景),0.6~0.7(器官)按类别统计后标定教师模型EMA系数0.99~0.999批大小越小取越靠近0.999归一化GroupNorm(3D)小批量时避用BatchNorm代码骨架我也放一个,能看出训练循环的大致结构就够了。for epoch in range(max_epochs): for batch_l, batch_u in loader: x_l, y_l = batch_l x_u = batch_u # 未标注图 # 1. 教师模型对未标注图产出伪标签(不反传梯度) with torch.no_grad(): teacher_pred = teacher(weak_augment(x_u)) pseudo = torch.softmax(teacher_pred, dim=1) confidence = pseudo.max(dim=1)[0] # 2. 学生模型在强增强上预测 student_pred_l = student(x_l) student_pred_u = student(strong_augment(x_u)) # 3. 监督损失 sup_loss = ce(student_pred_l, y_l) + dice_loss(student_pred_l, y_l) # 4. 无监督一致性损失(带置信度掩码) mask = confidence > threshold unsup_loss = mse(student_pred_u[mask], pseudo[mask]) # 5. ramp-up调度 lambda_coef = ramp_up(epoch) * max_lambda loss = sup_loss + lambda_coef * unsup_loss loss.backward() optimizer.step() ema_update(teacher, student, ema_coef)这个骨架没有任何花哨成分,但对理解工程实现足够了。真正的技巧全在数据侧和权重调度里,框架本身很简单。5. 实测效果分析:10%标注能做到什么水平5.1 我是怎么测的我拿某器官分割任务做了一组对比实验,数据共1000例,标注只放开10%。三个对照组:全监督用全部1000例标注,监督下限用100例标注,半监督用100例标注加900例未标注。评价指标用Dice和HD95(95%豪斯多夫距离,衡量边界误差),结果大致如下:方案DiceHD95(mm)相对全监督Dice全监督(1000标注)0.9473.2100%监督下限(100标注)0.8826.893.1%半监督(100标注+900未标注)0.9314.198.3%这组数字的意思是,半监督把"缺标注"带来的损失弥补了七成以上。边界指标HD95没有完全恢复到全监督水平,但已经从6.8mm显著压到4.1mm。而且这是在一共只用了10%标注的前提下得到的,对于像我们这种标注资源捉襟见肘的团队来说,这笔账相当划算。但要强调,这个结果是在同分布数据、合适预热、细致调权重的前提下测出来的。换个数据集、换套设备,曲线形状可能完全不同。我在多套数据上测过,结论稳定的大方向是:只要标注和未标注同分布,半监督至少能帮你把Dice往回捞几个点,最多能回到接近全监督的95%以上;一旦分布错位,收益为负是常态。5.2 几个失败的场景:这些情况下别硬上第一类失败是未标注集里混了大量"没有目标器官"的图像。典型的比如你想分割肝脏,未标注集里却有相当比例的检查根本不含完整肝脏或属于术后状态。模型在无监督阶段会强行给这些图像画上肝脏轮廓,伪标签越学越歪,最后的Dice比不做半监督还低。这种情况不是方法的错,是数据过滤没做好。第二类失败是标注本身带有系统性偏差。我见过一个胰腺分割的数据集,标注者为了省事只勾画了胰腺体部,头和尾经常漏掉。如果把这套标注当成金标准训练1:9的半监督模型,模型会把"漏标头尾"当作正确模式泛化到未标注数据上,错误被几何级放大。半监督不会帮你纠错,反而会忠实地把你的标注偏差复制到每一个未标注样本上。第三类失败是模型容量不够。半监督的有效性建立在模型有能力从大量未标注数据里学出额外结构。如果网络本来就欠拟合,给它再多未标注数据也只是过拟合噪声。遇到这种情况,换一个更大的编码器,或者先做一轮有监督预训练再切半监督,往往比加数据更有效。5.3 指标之外:边界质量与临床可用性Dice这类重叠率指标有一个老大难问题:它不关心边界形状是否合理。一个器官预测整体和真值重叠了90%,但边缘到处毛刺,甚至出现脱离主体的飞地(floating island),Dice照样好看,临床上却根本没法用。所以看半监督实验结果,不能只看平均Dice,要把预测mask渲染出来肉眼扫一遍。我的经验法是,每次实验跑完,除了打印指标,还要随机抽20个样本把分割结果叠加在原图上做成GIF或者蒙版图,重点看三件事:边界是平滑还是锯齿状、有没有孤立的误检块、相邻器官有没有粘连。这些质量问题和Dice数字常常没有强相关。半监督训练如果无监督权重、扰动强度没调好,最容易出的毛病就是边界区域预测漂移,因为一致性损失的梯度主要来自概率分布差,对边界这种"介于两类之间"的像素格外敏感。另外,前面提到不确定性热图在这里也很有用。哪怕Dice已经很高,把不确定性和预测叠在一起看,你会发现模型对边界、对低对比度区域的"心虚"表现在热图上一清二楚。这个东西送到临床医生手里,比一个冷冰冰的Dice数字有说服力得多。6. 现在的边界与下一步方向6.1 还没被解决的问题半监督医学图像分割离"成熟到开箱即用"还有很长的路。最让我头疼的问题有三个。一是长尾类别。病灶、罕见解剖变异,这些恰好在临床诊断里最重要的东西,因为出现频率低,模型在无监督阶段对它们天然不敢给高置信度,置信度门控一开它们就被滤掉了。结果就是,半监督提上来的往往是大器官、背景这类"好学"的类别精度,而把最难的那一小块留给监督阶段去硬扛。二是伪标签标定问题。深度分割模型普遍过置信,softmax概率不能直接当作可靠性。尤其是用了Dice损失之后,概率分布常被拉得很锐利,0.9的概率其实可能只有0.7的真实精度。这意味着一切基于概率阈值的设计都隐含了"错误校准"的风险。要做到严密,需要在半监督流程里额外加一个标定(calibration)环节,但做的人少,能做好的人更少。三是评估口径混乱。论文里用不同的分割目标、不同的标注比例、不同的预训练设置,结果差距极大。一个方法在A数据集涨了5个点Dice,换个环境可能负收益。目前这个方向缺一个通行的评测协议,比来比去容易让人误判方法上限。6.2 我认为会继续发展的几个方向第一个方向是生成模型进入半监督流程。如果扩散模型能够以无标注数据为基础生成合成图像,那生成出来的样本既可控又能无限扩充,相当于把"伪标签"升级成"伪图像"。现在已经有工作在做这个方向,把生成样本和真实样本混合训练,用来缓解伪标签噪声。这条路线一旦成熟,半监督可能直接变身成"半监督+生成式增广",会把可用标注的门槛再往下压一个台阶。第二个方向是极弱监督与半监督的融合。点点击、画几笔这类极弱标注成本低得多,先用极弱标注把模型推到"能看"的水平,再用半监督把它推到"能用"的水平。很多临床合作里,医生只愿意标几个关键点和轮廓,这种融合路线更现实。第三个方向是模型自身的自我校准。不确定性估计和伪标签置信度会越来越精细,比如把不确定性和解剖先验结合,让模型在形态学不合理的预测区域自动降低置信度。这条路一旦走通,半监督训练里最讨厌的"确认偏误"会得到结构性缓解。最后说点私人体会。在这个方向泡了几年,我的感受是半监督不是一个算法,而是一整套关于"数据怎么用"的思考方式。它最迷人的地方不是那几行损失函数,而是让你重新审视手里的数据:哪些能直接当标签,哪些能通过扰动产生约束,哪些应该被丢掉。如果你想把半监督用在实际项目里,我劝你从最无聊的事情做起——先把数据分布搞清楚,把标注质量盘一遍,再谈加不加那些花哨模块。方法永远在快速迭代,数据里的坑,才是一个一个真的坑。