4. 医学影像数据增强策略

医学影像数据往往存在标注成本高、样本量小、类别分布不均衡等问题,数据增强因此成为训练流程中不可省略的一环。MONAI 的增强算子与通用视觉库最大的不同,在于它把“空间变换”和“强度变换”严格区分开,并且要求图像与标签(分割掩膜、关键点、边界框)在几何变换中保持同步。理解这一点,是选择与调优算子的前提。

先分清两类算子:几何变换与强度变换

几何变换改变体素的空间位置,必须对图像和标签施加同一套仿射参数,否则分割掩膜会与图像错位。MONAI 通过字典式变换(如 RandAffined、RandFlipd、RandCropByPosNegLabeld)自动把同一随机参数应用到 keys 中列出的所有字段,这是它相对手工实现的核心优势。强度变换只改变像素值,不改变位置,因此通常只作用于图像键,不作用于标签键。

常见的四类算子定位如下:RandFlipd 做镜像翻转,成本极低,用于扩充左右/上下对称性;RandAffined 做旋转、缩放、剪切、平移的复合仿射,用于模拟摆位差异与解剖形变;RandGaussianNoised 注入高斯噪声,用于模拟低剂量、低信噪比采集;RandCropByPosNegLabeld 按正负样本比例裁剪图像块,用于处理前景占比极小的分割任务,同时控制显存占用。

MONAI 增强算子:作用对象、参数与标签同步关系 输入样本字典 image label 几何变换(image + label 同步) RandFlipd prob=0.5,spatial_axis=0/1/2 RandAffined rotate_range / scale_range / shear_range RandCropByPosNegLabeld pos / neg / spatial_size / num_samples 强度变换(仅 image) RandGaussianNoised prob / mean / std RandScaleIntensityd / ShiftIntensityd 不同步 Compose 串联 → 输出增强后的 image / label 对 几何变换保证 image 与 label 使用同一随机参数,强度变换只改 image 调优要点 • 翻转/仿射幅度过大 → 解剖结构失真,需按器官对称性设上限 • 噪声 std 与采集剂量相关,过强会淹没病灶边缘;裁剪需保证前景比例与块尺寸匹配

RandFlipd:最便宜也最容易用错的算子

翻转的调优空间很小,关键在“是否允许”。以轴位脑部 MRI 为例,左右翻转(spatial_axis=0)通常可接受,因为大脑近似左右对称;但上下翻转(spatial_axis=1)会破坏解剖学上的头脚方向,一般禁用。对于肝脏、心脏等存在明确左右叶或腔室结构的器官,翻转前要确认标签语义是否随之改变。典型配置为 RandFlipd(keys=["image","label"], prob=0.5, spatial_axis=0),概率取 0.5 即可,过高会让模型过度依赖镜像不变性。

RandAffined:参数范围决定形变合理性

仿射是四类算子中最需要谨慎调参的。MONAI 中旋转、缩放、剪切、平移都以“范围”形式给出,实际值在范围内均匀采样。以 1mm 各向同性、尺寸 128×128×64 的 CT 为例,一个相对稳妥的起点是:rotate_range=(0.17, 0.17, 0.17)(约 ±10°)、scale_range=(0.1, 0.1, 0.1)(±10%)、shear_range=(0.05, 0.05, 0.05)、translate_range=(8, 8, 4)(体素单位)。旋转范围超过 ±15° 时,插值带来的边缘模糊会明显增加,且可能把病灶转出视野。

另一个关键参数是 mode 与 padding_mode。图像建议用 mode="bilinear",标签必须用 mode="nearest",否则会出现非整数类别值;边界填充常用 padding_mode="zeros",但对 CT 这类有明确背景值的模态,用 "border" 可减少边界伪影。若希望每次迭代重新采样,需设置 cache_grid=False 或使用 RandAffined 的随机采样行为,而不是固定一个网格反复使用。

RandGaussianNoised:强度增强要贴合成像物理

高斯噪声模拟的是电子噪声与低剂量采集。参数 mean 一般取 0,std 需要结合图像归一化方式确定。若图像已归一化到 [0,1],std=0.05 属于温和增强,std=0.15 以上就可能掩盖小病灶。更贴近实际的做法是把它与 RandScaleIntensityd、RandShiftIntensityd 组合,模拟不同设备的对比度与亮度差异。注意噪声只加在 image 上,绝不能加到 label 上。

RandCropByPosNegLabeld:解决前景稀疏与显存瓶颈

在 3D 分割中,若整幅图像直接送入网络,显存往往不够,而随机裁剪又可能长期采不到病灶。该算子通过 pos 与 neg 控制正负样本比例:pos=1, neg=1 表示约一半的块包含前景,pos=1, neg=3 则偏向背景。参数 spatial_size 决定块尺寸,num_samples 决定每幅图产出多少个块。例如 spatial_size=(96,96,48)、num_samples=4、pos=1、neg=1,可在保证前景覆盖的同时把单次显存占用压到可控范围。若前景极小,可适当提高 pos 或增大 num_samples,但要注意类别平衡,避免背景样本过少导致假阳性上升。

组合顺序与一个可复用的配置样例

增强通常按“几何 → 强度 → 裁剪”的顺序组合,因为裁剪会改变空间尺寸,放在几何变换之后更符合实际。下面给出一个可直接参考的 MONAI 字典式增强链示例,参数为教学示例值,需按具体数据集调整:

from monai.transforms import (
    Compose, RandFlipd, RandAffined, RandGaussianNoised,
    RandCropByPosNegLabeld, RandScaleIntensityd, RandShiftIntensityd,
)

train_transforms = Compose([
    RandFlipd(keys=["image", "label"], prob=0.5, spatial_axis=0),
    RandAffined(
        keys=["image", "label"],
        prob=0.3,
        rotate_range=(0.17, 0.17, 0.17),
        scale_range=(0.1, 0.1, 0.1),
        shear_range=(0.05, 0.05, 0.05),
        translate_range=(8, 8, 4),
        mode=("bilinear", "nearest"),
        padding_mode="border",
    ),
    RandGaussianNoised(keys=["image"], prob=0.2, mean=0.0, std=0.05),
    RandScaleIntensityd(keys=["image"], factors=0.1, prob=0.3),
    RandShiftIntensityd(keys=["image"], offsets=0.1, prob=0.3),
    RandCropByPosNegLabeld(
        keys=["image", "label"],
        label_key="label",
        spatial_size=(96, 96, 48),
        pos=1, neg=1,
        num_samples=4,
    ),
])
调参时建议先固定随机种子,单独可视化一批增强结果,确认标签与图像始终对齐、解剖方向未被破坏,再逐步放大变换幅度。若验证集 Dice 波动明显增大,往往是几何变换过强而非模型容量不足。
不要把强度变换的 keys 写成 ["image","label"],也不要把仿射的标签插值模式设为双线性。这两类错误不会报错,但会静默污染标签,导致训练指标虚高而推理效果很差。

总体而言,翻转负责低成本扩充,仿射负责形变鲁棒性,噪声负责成像差异,裁剪负责显存与类别平衡。四者并非越多越好,而应围绕数据规模、模态特性和任务类型做取舍:数据量充足时可降低增强强度,小样本或类别极不均衡时则优先保证裁剪策略与几何变换的合理性。