第一次在检索列表里看到 GLoRIA 的时候,我正被一批医学影像标注折腾得头大:找个能稳定读片的标注人员本来就难,标注费用不低,而且不同医生对同一张片子给出的描述可能还不完全一致。GLoRIA 的做法让我眼前一亮,它没有继续堆更多人工标签,而是把医学影像和对应的文字报告当成天然的多模态训练素材,用“全局加局部”的对比学习让模型自己学会看图和读报告。这个框架尤其适合做医学影像 AI、多模态预训练,或者单纯对标签高效学习感兴趣的人参考,今天就把我的学习笔记和复现体会整理出来。
1. 为什么需要 GLoRIA:从标签稀缺和多模态信号说起
1.1 标签高效不是一句口号
医学图像识别和普通的物体识别有个很大的差异:一张胸部 X 光片里,可能同时存在肺炎、胸腔积液、心脏增大,病灶边界模糊,还经常被骨骼和软组织遮挡。如果只用纯监督学习,想让模型真正理解这些细粒度特征,每类疾病都要准备几百到几千张严格标注的图,这不只是成本问题,更是时间问题。有些罕见病甚至很难凑齐足够数量的阳性样本。
所以我第一次看到“标签高效”这个词时,就意识到它背后的意思是:我们不想完全放弃有监督训练,也希望模型能在标注样本很少的情况下依然学到有价值的结构。GLoRIA 的解决思路是先用大量无标注的“图像-文本报告”对做自监督预训练,再在下游任务上只用少量标注微调。这样做的本质是把医学场景里本来就存在的报告文本变成免费监督信号。
1.2 多模态为什么天然适合医学影像
医学影像从来不是孤立的。放射科医生看一张 CT 或 X 光片,通常会结合检查申请单、既往病史、临床表现以及影像所见。报告中“右肺下叶可见斑片状高密度影”这句话,既描述了位置,也描述了形态和密度特征,这些信息恰恰是图像特征需要对齐的语义标签。
GLoRIA 充分利用了这一特点。如果只做图像本身的对比学习,比如把同一张图做不同增强后拉近,模型只能学到“长得很像的图像聚在一起”,很难学到“这种阴影代表炎症”这类医学语义。而引入文本报告后,模型有机会把图像区域和具体的语义描述绑定起来。这种绑定越细,模型对病灶的理解就越接近医生的读片逻辑。
2. GLoRIA 的完整设计拆解:全局与局部如何协同
2.1 全局分支:先让整张图和整份报告对齐
GLoRIA 的顶层思路是双塔结构,一个图像编码器,一个文本编码器。图像编码器通常用卷积网络或视觉 Transformer,文本编码器用类似 BERT 的预训练语言模型。全局分支做的事,就是把整幅图像的特征和整条报告文本的特征送到同一个对比学习空间里训练。
具体实现时用的是 InfoNCE 类别的对比损失。每一批里,图像和对应报告是正样本对,其他图像和报告则被视为负样本。训练目标是让正样本对的余弦相似度尽量高,负样本对的余弦相似度尽量低。我复现的时候发现,温度参数对训练稳定性影响特别大,论文里常见设置是 0.1 附近,但实际数据噪声大的时候,稍微调低一点比如 0.07,会让梯度更稳定。
全局分支解决的是“整体语义对齐”问题。比如报告第一句经常写“两肺纹理清晰,未见明显实质浸润”,这句话对应的是整张图没有明显病灶,而不是某个局部小框。有了全局对齐,模型一开始就建立起了图像整体和文本整体之间的桥梁。
2.2 局部分支:把注意力放在真正有意义的区域
但只做全局对齐有个明显弱点:一份长报告里往往包含多个发现,比如“左肺上叶小结节,右肺下叶磨玻璃影”,如果整段文本只在整图级别做对比,模型很难知道哪句话对应图中的哪个位置。GLoRIA 的局部分支就是为了解决这个问题。
局部分支的思路可以这样理解:图像编码器从中间层抽取一组局部区域特征,每一条局部特征对应图上的一块区域;文本编码器输出每个字的嵌入特征。然后通过注意力机制,计算每个文本词和每个图像区域之间的相关程度,把文本词作为“查询”,去图像区域中检索最相关的位置。最后用注意力加权的方式,把所有局部匹配的相似度汇总成一个局部对比损失。
我第一次读到这里时,最直观的感受是“这不就是跨模态注意力对齐”。这个设计比单纯把所有 patch 的特征做平均要聪明得多,因为它不会让“左侧胸腔积液”这个词去匹配一个完全无关的右下肺区域。它本质上是在训练模型产生一个注意力图,告诉视觉编码器哪些区域对语义描述更重要。
2.3 全局和局部如何结合
GLoRIA 的最终损失是全局对比损失和局部对比损失的加权和。我复现时最关注的参数是这两个损失的权重比例。如果局部损失权重太高,训练初期模型还没建立粗粒度的语义对齐,局部注意力会非常发散,几乎找不到可靠的对应区域;如果全局损失权重太高,又回到整图匹配,细粒度信息学不充分。
比较稳妥的做法是先用全局分支把模型拉到“基本能区分正负样本”的状态,再把局部分支的权重逐渐加进来。原设计里两者是同时联合训练的,但在学习率偏大的情况下,局部注意力确实容易震荡。我实际测试下来,全局损失权重保持在 0.5 到 0.7 之间,局部权重设置在 0.3 到 0.5 之间,收敛更平稳。
3. 实操中的关键细节与复现要点:数据、参数与训练
3.1 数据预处理:配对的文本质量决定上限
多模态模型的性能上限,很大程度取决于文本质量和配对关系。我发现很多复现效果不好,问题根本不在模型结构,而是报告文本太脏。医学报告经常包含“检查号”“患者姓名”“扫描序列”“设备参数”这类与影像诊断无关的内容,如果不做清洗,模型会把大量容量浪费在无意义的字符上。
我当时的清洗流程分四步:第一步抽取出报告里的“影像所见”和“诊断意见”两个部分,其余全部丢弃;第二步做英文小写化和数字归一化,把“1.5cm”统一成类似“ cm”的占位符;第三步去掉泛化的套话,比如“检查过程顺利,患者无不适”这类与影像特征无关的句子;第四步做长度截断,一般保留前 128 或 256 个 token,长报告从重要内容附近抽取核心句子。
这里有一条重要经验:不要贪心保留整份报告。报告里的病史、临床信息虽然可能有帮助,但很多内容对应不上影像特征,反而增加对比学习的噪声。而且文本编码器输入过长会显著增加显存开销,训练速度也会明显下降。
3.2 模型结构与损失函数配置
图像编码器我用了 ResNet 风格的卷积网络作为骨架,因为它在医学影像基础任务里仍然相当能打,训练起来也比大规模 Transformer 稳定。局部特征不直接取最后一层,而是从倒数第二层特征图获得,空间分辨率更高,局部表达更细。文本编码器用的是轻量级的 BERT 变体,输入长度限制在 128 到 256 token。
损失函数部分,全局对比损失和局部对比损失都采用对比学习的标准形式。这里需要特别注意温度参数。温度太高,所有样本对的相似度都会被压软,梯度区分度不足;温度太低,模型会过分关注困难负样本,训练容易崩。我以 0.1 为起点,每次下降 0.01,观察损失曲线是否出现突然飙升,最终停在 0.07 到 0.1 之间。
提示:如果你的 batch size 比较小,对比学习很容易因为负样本数量不足而退化成“记忆正样本”。我建议至少尝试 batch size 128 以上,如果显存不够,就保留较大的 batch 并使用梯度累积,累积步数不要超过 4 步,否则模型更新频率太低,局部注意力会变得不稳定。
3.3 训练策略与超参数经验
训练 GLoRIA 和训练普通分类模型最大的区别在于,批次构成直接影响对比学习效果。每个 batch 尽量确保正样本对是干净的,避免同一份报告被派给多张完全不同的图。因为医学影像数据集中同一患者可能有多个检查序列,如果错误地把同一患者的图像作为“负样本”,模型会学到非常混乱的相似度分布。
优化器方面,我用了 AdamW,基础学习率设为 3e-4 左右。图像编码器和文本编码器如果同时从零训练,收敛速度会很慢,所以我给文本编码器设置了更低的初始学习率,比如 1e-5 到 2e-5,保留预训练权重中的语言知识。骨干网络如果使用公开预训练权重,初始学习率也可以适当降低。
多尺度训练对我的任务有明显帮助。把图像随机缩放到不同尺寸再裁剪,可以增加局部区域特征的多样性,让局部注意力不那么容易聚焦到图像角落噪声。我还开了混合精度训练,显存占用直接降低约一半,训练速度提升明显。需要注意的是,对比损失在低精度计算下偶尔会出现 NaN,建议把损失计算部分保留 fp32。
4. 踩坑记录与常见问题速查
4.1 报告预处理不干净导致全局对齐失效
这个坑我印象最深。最开始我抽出来的报告片段没有过滤“患者配合良好”这类模板句子,结果全局分支很快就学崩了:模型输出的表示几乎只依赖文本里的高频词,图像信息基本被忽略。我后来统计了训练集文本中的停用词频率,把那些与影像语义无关的高频模板句子单独建表,在清洗时直接删除,问题才缓解。
4.2 局部注意力发散和显存爆炸
局部注意力机制如果直接实现,需要维护一个“文本 token 数乘图像区域数”的注意力矩阵。假设文本长度 128,图像区域大小为 14×14,那一共要算 128×196 个相关分数,这个量对单卡显存很不友好。我的做法是限制图像区域数量,例如取空间维度上响应最高的前 64 个区域参与局部对比,而不是全部区域都参与。
如果注意力图发散,一个很有效的调试办法是可视化局部注意力热图。训练初期热图大多是一团糊,但如果到了中期依然没有聚焦到任何结构区域,大概率是局部损失权重过高或者文本编码器学习率太大。把学习率调低后,热图会逐渐出现和病灶描述相关的聚集区域。
4.3 下游评价指标怎么选
预训练质量不容易直接评价,更多还是要看下游任务效果。我习惯用两种方式同时检查:一种是在冻结的视觉特征上训练线性分类器,看 AUC 能否在不微调模型的情况下有明显提升;另一种是直接对全模型做少量数据微调,观察小样本分类的 F1 值。如果一个模型的全局对齐做得很好,线性评测的 AUC 通常会比较稳定;局部对齐做得好的模型,在细粒度分类比如“左下肺和右下肺病灶差异”上会有更明显的优势。
| 常见问题 | 可能原因 | 我的处理方式 |
|---|---|---|
| 损失持续不下降 | 文本模板噪声太多 | 加强模板过滤,缩短文本长度 |
| 训练出现 NaN | 混合精度下的损失计算 | 损失计算使用 fp32 |
| 局部注意力全图发散 | 局部损失权重过高 | 下调局部权重,降低文本编码器学习率 |
| 下游小样本 F1 偏低 | 全局特征缺乏细粒度信息 | 增加局部对比损失权重,或加大图像区域采样 |
| 显存不足 | Attention 矩阵过大 | 限制参与局部匹配的区域数量 |
5. 扩展思考:标签高效还能往哪个方向走
5.1 从预训练到下游任务
GLoRIA 训练出的图像编码器可以直接用于分类、病灶检测或者分割任务的初始化。我做了一个简单实验,把预训练后的视觉编码器冻结,只用少量图像标签训练线性分类头,效果比从零训练高出不少。这说明即使没有进行全量微调,多模态预训练已经让视觉编码器获得了更丰富的语义空间。
如果要做图像分割,可以把局部注意力热图和图像的原始特征图结合,当作一种弱监督的注意力线索。这样一来,不需要像素级的密集标注,模型也能对疑似病灶区域给出一块响应。这不是 GLoRIA 的原始设计目标,但它提供的局部表示确实让这类扩展变得非常顺手。
5.2 多模态不是万能的
需要提醒的是,GLoRIA 依赖“图像-文本”配对的质量。如果报告描述不全、漏掉关键阳性征象,局部对齐就失去了正确监督。如果文本只是一句“未见明显异常”,那么模型学到的局部知识就很有限。在这种数据分布下,单纯加多模态分支不一定比纯图像自监督更好。我在实验中对比过,当报告平均长度小于 10 个字时,GLoRIA 相比 SimCLR 类方法几乎没有优势。
所以,标签高效的重点不是“越少越好”,而是“如何用最便宜的信号换取最有用的语义”。文本报告只是其中一种信号,未来完全可以加入结构化的诊断编码、解剖部位标注,甚至检查设备参数。信号之间的冗余和互补都值得仔细分析。
5.3 后续可以继续尝试的方向
我个人觉得 GLoRIA 的框架有一个自然延伸方向:把全局损失从“整图对整报告”升级成“分组图对分组报告”。比如先把报告按解剖区域拆分成“肺野、纵隔、胸膜”等小节,再让每个图像区域只和对应小节做软匹配。这种结构化对齐可能比目前的全局加局部双层结构更贴近医学读片逻辑,也能显著减少无关文本带来的噪声。
另外,当前多模态预训练在很多医学场景里还面临数据隐私和跨机构泛化问题。GLoRIA 这类方法的训练过程本身是自监督的,不太需要人工标注,如果能在多家机构内部训练后做特征聚合,也许能进一步提高模型的通用性。不过这涉及具体的数据安全方案,实际部署时还需要评估。
我在实际复现过程中最大的体会是:GLoRIA 的思想比实现细节更值得关注。它提醒我,医学图像里不是没有标签,而是标签被写在了一个不太容易被模型读懂的模态里。把报告和图像放在同一个学习空间里,等于让模型多了一双能看懂医生语言的“眼睛”。如果你也在做标签稀缺的医学影像任务,建议先用小规模数据把全局分支跑通,再慢慢加入局部分支,这个循序渐进的过程能帮你少走很多弯路。