B 模式超声(B-mode ultrasound)是临床最常见的二维灰阶成像方式,这类影像的 AI 分析一直比 CT、MRI 更棘手。UltraPIPS 这个方向的核心,就是用基础模型(foundation model)去改善模型对 B 超影像的“感知能力”——也就是让 AI 能准确识别病灶边界、器官位置、组织层次,而不是只会给一个“正常/异常”的粗标签。文章主要写给两类人:做医学影像 AI 的学生或工程师,以及想评估这类方法是否值得投入的临床科研人员。
先给一个核心判断:这类“基础模型 + B 超感知”的流程,价值不在于换一个更大的主干网络,而在于把基础模型已经学到的视觉先验迁移到超声领域,缓解小样本、噪声重、设备差异大的问题。真正落地时要盯住的不是模型名气,而是输入图像质量、提示词(prompt)设计、显存开销和输出后处理。下面按我实际跑这类流程的顺序拆开讲。
1. 先搞清楚 B 超影像里的“感知”到底难在哪
1.1 B 超图像和自然图像不是一回事
很多人第一次接触 B 超数据时,会很自然地把它当成“灰度自然图”丢进分割模型里,结果往往不理想。原因在于 B 超成像本身有很强的特殊性。
第一是噪声特性不同。B 超图像带有明显的斑点噪声(speckle noise),这种噪声不是简单的随机噪声,而是由声波与组织微结构相互作用产生的,和图像内容高度耦合。你用自然图像上常见的增广方式去处理它,比如随机亮度抖动、高斯模糊,很可能把有用的组织纹理也一起抹掉。
第二是成像参数对图像影响极大。增益、深度、探头频率、聚焦位置、时间增益补偿(TGC)都会改变图像的灰阶分布和细节表现。同一个病灶,用不同设备、不同参数扫出来,视觉上可能差别很大。这是 B 超 AI 模型跨设备泛化难的根本原因之一。
第三是标注存在天然模糊性。超声图像中病灶边界常常不像 CT 那样有清晰的解剖对比,医生勾画时也存在主观差异。同一个切面,不同医生标注的边界可能相差几个像素到十几像素。这会让模型训练时的“标准答案”本身就不稳定。
所以,所谓“感知能力提升”,在 B 超场景下首先不是模型结构问题,而是能不能从这些有噪声、有歧义、有跨设备差异的图像里提取出稳定且可判别的特征。
1.2 基础模型为什么能帮上忙
基础模型的定义比较宽泛,常见的有两大类。一类是像 SAM、SAM2 这样可以直接输出分割掩膜的模型;另一类是像 CLIP 这样以图文对比学习预训练出来的视觉编码器,可以提取通用视觉特征。医疗领域也有不少在公开医学影像上继续预训练的基础模型,比如 MedSAM、不同版本的医学 CLIP 模型等。材料里没有给出 UltraPIPS 具体用了哪一类,但从标题看,它走的就是“把基础模型引入 B 超感知”这条路。
基础模型能改善 B 超感知,主要有三个原因。
一是预训练带来了强大的底层视觉能力。基础模型在海量图像上学过边缘、纹理、形状这些通用视觉概念,而 B 超图像里的组织边界虽然模糊,但本质上仍然是边缘和纹理的组合。用预训练权重初始化,比从零开始训练更容易收敛,尤其在标注数据很少的时候。
二是提示机制让模型可以“按需感知”。你给它一个点、一个框、甚至一句描述,它就能围绕这个提示生成相应的分割或识别结果。这对 B 超非常实用,因为临床上医生通常知道病灶大致在哪里,需要 AI 做的是精细勾画和测量,而不是从零开始全图搜索。
三是迁移性。基础模型的特征空间相对通用,即使只在自然图像或 CT、MRI 上预训练,迁移到 B 超后也可以通过少量微调获得可用的效果。这种迁移能力,正是小样本场景下最需要的。
但这里要提醒:基础模型能带来帮助,不代表拿来就能直接用。B 超图像的灰阶分布、噪声模式和组织形态,和基础模型见过的自然图像差别很大。如果不做适配,直接用零样本推理,往往会出现“全图都被分成前景”或者“病灶完全漏掉”这类问题。后面会讲怎么处理和验证。
2. 跑通前,环境与数据要按这个标准准备
2.1 硬件和依赖条件
先看硬件。基础模型的体积通常不小,一个 SAM ViT-H 级别的模型光权重就有几百 MB,加载后显存占用明显高于常规 U-Net。我一般会建议把显存门槛设在 16GB 以上,这样单卡能做基础微调和推理。如果只有 8GB 显存,也不是不能跑,但要把输入尺寸、批量数、模型变体都调小,或者使用 LoRA 这类参数高效微调方式。
内存方面,16GB 到 32GB 通常够用。磁盘空间反而不是主要瓶颈,因为超声数据一般不会像病理切片那样动辄几个 GB 一张。真正要留意的是数据 IO:如果数据集是很多小文件,建议提前打包为 npy、h5 或者 tar 格式,避免训练时反复做小文件随机读取,这个很影响训练速度。
软件环境上,PyTorch 基本是标配。如果你要用 SAM 系模型,需要安装 segment-anything 对应的版本;如果你要用 MedSAM,需要留意它的推理代码和权重版本。MONAI 可以用来做医学影像的预处理和评估指标计算,比较方便。CUDA、cuDNN 版本要和你选的 PyTorch 版本匹配,这个坑很常见,后面排查部分会提。
2.2 数据格式与预处理
B 超数据来源通常有两种:DICOM 格式和导出后的图片格式。DICOM 里包含很多扫描参数和患者信息,对于正式科研项目,建议保留 DICOM 原始文件,不要一开始就全部转成 JPG。因为 JPG 压缩会损失灰阶细节,而且很多设备导出的 JPG 已经做过对比度增强,不同设备之间根本无法对齐。
预处理建议按下面的顺序来:
| 步骤 | 操作 | 说明 |
|---|---|---|
| 1 | 从 DICOM 读取像素值 | 保留原始灰阶范围,不要为了显示效果做过大的窗宽窗位调整 |
| 2 | 灰度归一化 | 统一到 0-1 或标准化的数值范围,避免不同设备亮度差异过大 |
| 3 | 裁剪感兴趣区域 | 去掉 B 超图像周围的文字、刻度、探头标记等信息 |
| 4 | 统一分辨率 | 常见做法是调整到 512、768 或 1024,具体取决于模型输入要求 |
| 5 | 数据划分 | 按患者划分 train/val/test,绝对不要按图像划分,否则同一患者的相似切面会造成信息泄漏 |
| 6 | 掩膜格式转换 | 如果标注是 RLE 或多边形,统一转成二值 mask 并和图像分辨率保持一致 |
归一化这里我要多解释两句。基础模型通常期望输入是“接近自然图像”的 RGB 格式,但 B 超原图是单通道灰度。一种做法是把灰度复制成三通道喂给模型,另一种做法是继续使用单通道输入但调整预训练模型的第一层。前者更省事,后者需要改模型结构。实测中,如果只是做推理或者轻量微调,复制三通道是最常见、最不容易出错的方案。
另外,如果你的数据来自多个品牌或型号的超声设备,建议在训练前先做一次灰度分布对比。如果差异很大,可以考虑直方图匹配或限制对比度直方图均衡(CLAHE),但我个人建议先不做复杂增强,先用最朴素的归一化跑一版基线,再根据验证集表现决定要不要加预处理手段。上来就把预处理做复杂,往往分不清效果提升到底来自模型还是来自预处理。
3. UltraPIPS 类流程的完整操作顺序
3.1 先把 PIPS 看成一条流水线,而不是一个黑盒
很多同学看到 PIPS 会猜测它是哪几个英文单词的缩写,但原始材料里没有明确展开。我更建议把它理解成一条流水线:输入 B 超图像,借助基础模型提取语义特征或生成候选掩膜,通过提示信息逐步校准感知结果,最后输出可用的分割、测量或识别结果。
这条流水线一般包含四个环节:
- 骨干特征提取:用预训练基础模型对图像编码。
- 候选区域生成:自动或半自动地给出病灶的位置提示,比如一个框或几个点。
- 提示引导分割:把位置提示送入 SAM 这类模型,生成精细掩膜。
- 后处理与验证:把粗糙掩膜变成干净的临床可用输出。
我在实战中一般会把第一版实现做得越简单越好:不用复杂的多阶段网络,先看基础模型在单张图像上能不能给出合理的候选掩膜。能跑通之后,再逐步加入自动提示生成、多帧融合、批量处理这些环节。
3.2 选择基础模型:要看你需要的是“分割”还是“特征”
不同基础模型解决的是不同层面的问题,选择前先想清楚你要的最终输出是什么。
如果最终任务就是病灶或器官分割,SAM、SAM2、MedSAM 这类的模型比较直接,它们的输出就是掩膜。优点是上手快,零样本或少量提示就能出结果。缺点是你很难控制它“分割得很准”,因为超声边界模糊,SAM 往往会沿着它认为的边界走,而这个边界不一定符合临床标准。
如果你的最终任务是多模态识别、分类或者需要把超声图像和文本描述对齐,CLIP 类模型更适合做特征编码器。它可以把图像映射到一个语义空间中,然后通过相似度计算完成分类或者检索。这类模型在超声上的迁移成本比 SAM 高,因为超声图像和文本描述之间的对应关系需要重新构建。
还有一类做法是把基础模型当作特征提取器,后面接一个小型任务头。比如用 SAM 的 encoder 输出特征,再接到一个轻量分割头上。这种做法在标注数据少、任务单一的情况下效果不错,而且显存开销比端到端微调整个 SAM 小很多。
我的建议是:第一版不要贪多。如果你的核心任务是“医生点一下、模型把边界勾出来”,直接上 SAM 系零样本测试;如果任务是“自动识别某类病灶并把位置框出来”,先做候选区域生成,再把框当作提示送入分割模型。两个环节分别验证,不要一上来就拼一个端到端大模型。
3.3 提示设计是最容易出效果、也最容易出问题的地方
提示(prompt)是基础模型分割能力的“操纵杆”。在 B 超声场景里,提示通常有三种形式。
第一种是点提示。用户点击病灶内部一个点,模型围绕这个点生成分割。优点是操作简单,缺点是只给一个点很容易产生过分割或欠分割,尤其是病灶和周围组织灰度接近时。实践中可以给两个点,一个正点(病灶内)、一个负点(背景区域),模型会把这层信息当作分割约束。
第二种是框提示。用一个矩形包围框住病灶,SAM 在框内寻找目标边界。框提示比点提示稳定,因为它划定了搜索范围。框如果太小会切掉病灶边缘,框如果太大又会包含大量背景,所以框的生成质量直接影响分割结果。
第三种是文本提示。理论上可以输入“甲状腺结节”“囊肿”这样的描述,但这需要模型具备医疗语义理解能力。一般自然图像基础模型做不到这一点,除非你用医疗领域的 CLIP 类模型。B 超场景下文本提示目前更多用于检索和粗分类,用于精细分割还不太成熟。
在 UltraPIPS 这类流程里,提示很多时候不是靠人手动给的,而是由一个前置检测模型自动生成。比如先用 YOLO 检测出疑似病灶区域,把检测框作为 SAM 的框提示,再让 SAM 精细分割。这种“检测器 + 分割器”的组合在两阶段方法里很常见。实测要注意:检测器漏检时,SAM 再强也拿不到输入;检测器框偏了,SAM 分割也会跟着偏。所以两阶段方法的瓶颈往往在检测器,不在分割器。
如果你做的是视频序列或多帧超声,还可以用上一帧的分割结果作为下一帧的提示来源。比如把上一帧掩膜的质心作为点提示,或者把上一帧掩膜的外接框稍微扩大作为框提示。这样比每帧重新检测稳定得多,但要注意帧间位移较大时,旧提示可能已经偏离目标,需要设置提示失效检测或周期性地重新检测。
3.4 微调还是免微调,取决于数据量和任务差异
基础模型不是拿来就能直接用在所有 B 超任务上的。先做零样本测试,如果效果不够好,再考虑微调。微调方式主要有三种。
| 方式 | 做法 | 适用场景 | 资源消耗 |
|---|---|---|---|
| 零样本推理 | 不更新权重,直接输入图像和提示 | 快速验证、粗筛病例、病灶明显 | 低 |
| 冻结编码器,微调任务头 | 只训练分割头或分类头 | 标注数据 50-200 例、任务相对简单 | 中 |
| LoRA/适配器微调 | 只训练少量新增参数 | 标注数据 200 例以上、需要提升细粒度效果 | 中高 |
| 全量微调 | 更新整个模型或大部分权重 | 数据量大、任务域差别大 | 高 |
我遇到过不少同学上来就直接全量微调 SAM,结果显存不够、训练很慢、效果还比不上冻结编码器加任务头的方案。原因在于 B 超声数据集通常只有几十到几百例,远不足以重新校准一个亿级参数模型的全部权重。LoRA 这类参数高效微调方式更适合小样本场景,它只改一小部分低秩参数,既节省显存,又能把基础模型的先验保留下来。
微调时的数据量和任务难度也要匹配。如果只是区分囊肿和实性结节,几十例可能就够;但如果是甲状腺结节的精细边界分割,没有两百例以上,LoRA 也不一定能稳定出效果。这个没有固定标准,建议从最轻量的微调开始,先在验证集上看 Dice 和 IoU 是否明显提升,再决定是否加重微调力度。
4. 关键参数与效果验证:不能只看一张图好不好看
4.1 需要重点关注的参数
跑这类流程时,我建议把下面这些参数单独记录下来,并在实验记录里形成一组“固定配置”。
| 参数 | 初始建议 | 说明 |
|---|---|---|
| 输入图像尺寸 | 512 或 1024 | SAM 默认输入 1024,但 B 超原图不一定需要这么大,512 可以省显存 |
| 批量大小 | 1-4 | 基础模型显存占用高,批量调大前先看显存余量 |
| 提示类型 | 框提示优先 | 比点提示稳定,容易复现 |
| 正负点数量 | 1 正 1 负 | 点提示增强时使用,负点放在病灶外附近区域 |
| 学习率 | 1e-5 到 5e-5 | LoRA 微调时常用较小学习率 |
| 训练轮数 | 20-50 | 小样本数据训练轮数不要太多,容易过拟合 |
| LoRA rank | 8-16 | rank 越大可学习参数越多,但显存和过拟合风险也增大 |
| 损失函数 | Dice Loss + BCE | 超声分割场景下 Dice Loss 对类别不平衡更友好 |
这里有个容易忽视的参数是“提示扰动”。做推理时,如果你对同一个病灶稍微移动一下提示点或提示框,分割结果会跟着变化。要验证模型稳定性,就要在多个提示位置下重复推理,看掩膜的波动幅度。如果掩膜对提示位置极为敏感,那这个模型在真实场景中很难用,因为医生每次点击位置不可能完全一致。
另外,推理时的置信度阈值和后处理参数也很重要。SAM 会输出多个掩膜,通常默认取第一个掩膜,但有些情况下第二个掩膜可能更贴合病灶。建议保存前 3 个候选掩膜,并加一个简单的面积筛选和边界平滑,而不是直接取索引 0 的结果。
4.2 用什么指标判断模型真的“感知”更好了
很多文章只放两张“看起来不错”的分割效果图,但做科研或做实际项目,单张图片说明不了问题。指标怎么选,取决于你的任务。
分割任务常规看 Dice、IoU、Hausdorff 距离(HD95)和平均表面距离(ASD)。Dice 和 IoU 衡量区域重叠程度,HD95 和 ASD 衡量边界距离。B 超边界模糊,仅仅看 Dice 不够,边界类指标更能反映“勾画得是否贴合”。
“感知”类任务如果包含分类识别,还要看准确率、召回率、F1。但更关键的是接收者操作特征曲线下的面积(AUC),它能反映模型在不同阈值下的整体判别能力。超声场景下,漏诊比误诊更严重,所以我会特别关注召回率,并在报告中同时给出不同阈值下的表现。
多读一遍验证集设计。数据划分必须按患者、按设备、按病例分开。你的训练集和验证集如果来自同一个设备、同一个患者的不同切面,指标会虚高。更严谨的做法是 cross-site 验证:用 A 设备训练,B 设备测试,看泛化能力。这个做法虽然残酷,但能真实反映模型在临床环境中的表现。
还有一个容易被忽略的验证点:对比实验的基线设置。不要只跟“从零训练的 U-Net”比,还要和“基础模型零样本”“基础模型 + 任务头”“完整微调”这几个版本比。这样才能看出 UltraPIPS 类流程的每一步到底贡献了多少提升。如果基础模型零样本已经很好,那你的流程复杂度就要谨慎了,别为了流程而流程。
5. 常见问题与排查顺序
5.1 分割结果为空或明显不对
这类问题排在第一位,现象通常是:推理不报错,但输出掩膜是全零,或者掩膜把整张图都覆盖了。
我的排查顺序是:先看输入,再看提示,再看模型,最后看后处理。
第一步,确认输入图像真的能被模型正常读取。很多次问题出在图像是 16 位深度,而模型期望 8 位;或者图像本来是灰度图,被某些库读成了 RGBA;又或者像素值范围是 0-2000 而不是 0-255。可以先打印输入张量的 shape、dtype、min/max,确认数据进入模型前是合理状态。
第二步,确认提示坐标是否落在有效区域内。如果你用的是点提示,点的坐标可能因为图像 resize 或裁剪而偏移,点击坐标 100,100,但模型内部输入尺寸是 1024,坐标没换算,提示就落在了背景里。类似地,框提示如果坐标变换不正确,模型只能看到无效区域。这里建议把提示和图像一起可视化,直接看提示位置对不对。
第三步,检查模型权重。基础模型不同版本之间差异很大,比如 MedSAM 的权重和原版 SAM 的权重不能混用。加载权重时如果 log 里出现键名不匹配的警告,一定要重视,不要忽略。
第四步,检查后处理。二值化阈值过高、连通域分析把小块全部删掉、孔洞填充算法把病灶区域也填掉了,都会造成输出异常。后处理问题最好通过对比“模型原始 logits”和“处理后的掩膜”来定位。
5.2 显存不足或推理速度太慢
显存不足的常规解法是减小输入尺寸、减小批量、使用混合精度。SAM 的 ViT-H 在 512 尺寸下比 1024 尺寸省不少显存,多数 B 超任务用 512 也能获得可接受的效果。如果还不行,就换更轻的模型变体,比如 SAM ViT-B,或者使用另一个更轻量的分割基础模型。
推理速度慢还有一个常见原因:没有用 GPU 推理,或者模型被放在了 CPU 上。这种情况多发生在代码里漏写了.cuda()或.to(device)。可以先用一条命令行判断模型是否真的加载到了 GPU 上,看看torch.cuda.memory_allocated()有没有明显变化。如果模型确实在 GPU 上还是很慢,再看是不是单张图推理时存在大量冗余计算,比如把所有候选框都送入模型而不是做批量化。
批量推理时,速度提升通常不是线性的,因为基础模型的编码器计算量大。如果你有 100 张图要处理,不要写一个 for 循环逐张塞给模型,尽量把图像打包成 batch。但要注意,每张图的提示框数量可能不一样,SAM 分割头支持多提示,但 batch 维度上需要统一处理方式。
5.3 微调后不升反降
这类情况也很常见。微调前零样本分割效果还行,微调后验证集指标反而更低,或者训练集指标很高、验证集很差。
先看是不是过拟合。B 超数据集小,微调轮数一多,模型很容易记住训练图像的噪声和标注风格。解决办法是减轮数、加正则化、用早停。LoRA 的 rank 调小一点也有帮助。
再看是不是学习率太大。基础模型内部的特征空间已经很稳定,微调时学习率过大,会破坏预训练权重中的通用视觉知识。我自己会从 1e-5 起步,而不是用常规分类任务的 1e-3 或 1e-4。
还要检查标注质量。超声标注的主观性很强,如果训练集中存在明显错误的标注,模型会把这些错误也学进去。此时宁可先做一次标注清洗,也不要把所有标注都直接喂给模型。可以画几张训练样本的标注重叠图,看边界标注的分布是否合理。
5.4 跨设备或跨场景泛化差
模型在一个设备上效果很好,换一个设备效果断崖下跌,这是超声任务最常见的现实问题。排查时先做灰度分布对比,看两个设备图像的直方图差异有多大。如果不一致,第一步先做标准化,比如统一归一化方式、统一裁剪区域。如果还是不行,就需要在训练集里加入多设备数据,或者用域适应思路做特征对齐。
这里要说一个心态问题:不要指望靠单纯增加数据增强解决所有跨设备问题。B 超图像差异来自成像物理过程和设备参数,保持图像真实信息完整比做花哨的增强更重要。在实际项目中,多收集几个设备的小样本数据,比在单设备数据上堆增强更有效。
6. 从实验到落地:最后几条实际建议
如果 UltraPIPS 这类方法只是用来做学术验证,那么上面这些已经够用了。但如果你打算把它放进一个更完整的工具链,比如医生工作站、报告系统、批量阅片流程,我建议再考虑几件事。
第一件,把“单张跑通”和“批量跑通”分开。单张跑通只代表算法流程没有大问题,不代表批量稳定。批量处理时要考虑输出命名、失败重试、日志记录和中间结果保存。如果 500 张图像里第 300 张突然报错,没有日志和断点续跑机制,前面的算力就浪费了。
第二件,把输入质量检查放在流程最前面。超声图像的采集质量差异很大,脱气、伪影、低质量切面都会影响模型输出。与其费力设计模型去适应所有坏图,不如在输入端加一个质量过滤或提示“图像质量差,结果仅供辅助参考”。这在实际使用中能减少大量无效输出。
第三件,项目初期就把版本记录做好。基础模型权重、微调权重、预处理代码、后处理参数、验证集划分方式,这些都要记录下来。我见过太多次因为“忘了当时用的哪个版本”而导致结果无法复现的情况。超声研究本来就难以完全复现,如果连模型和权重都对齐不了,后续分析全是空谈。
第四件,对输出结果建立人工复核机制。目前基础模型在 B 超上的感知能力,还达不到完全替代医生的水平,尤其是在边界模糊的病灶上。更稳妥的做法是让模型先给出候选分割和测量值,医生在界面上做确认或修正。这个模式既降低了模型压力,也更容易被临床接受。
最后回到题目本身。UltraPIPS 这类研究的真正价值,是它示范了一条“用基础模型的先验能力,去补足超声任务标注少、噪声重、边界模糊短板”的路径。你在复现或改造这类流程时,不需要把它想得太神秘。先把骨干模型、提示策略、微调方式、验证指标这四块分别跑明白,再合到一起看整体效果。这样即使原论文里的某个细节没有公开,你也能用自己的实验数据把每个环节的贡献量化出来。
踩过几次之后我发现,很多问题不是基础模型能力不够,而是输入图像、提示坐标、数据划分这些前置环节没有处理干净。如果你现在正准备在自己的超声数据集上尝试 UltraPIPS 类方法,我建议先拿 20 张图做一轮完整的零样本推理,把输入、提示、输出、指标的链路全部走通,再决定要不要进入微调和批量阶段。基础模型给你的是一个很高的起点,但真正决定上限的,还是你对数据和任务本身的理解。