做视觉模型这几年,有一个感受越来越深:数据增强策略才是许多项目里真正的“胜负手”。模型结构可以抄,损失函数可以换,但同样是 ResNet、同样是那几个公开权重,有些人训练出来就是能稳定涨点,有些人就是怎么调都过拟合,差别往往就藏在增强策略的细节里。这篇文章把我踩过的坑、试过的方案、以及最终沉淀下来的一套可复用的增强流水线完整梳理一遍,覆盖基础几何变换、色彩扰动、Mixup/CutMix 这类进阶策略、自动增强搜索,以及 PyTorch 与 Albumentations 的实际落地写法。不管你是刚接触图像任务的初学者,还是已经被过拟合折磨过几轮的从业者,应该都能从这里找到可以直接抄作业的东西。
1. 为什么说数据增强是性价比最高的正则化手段
1.1 数据增强解决的核心痛点:样本少与过拟合
图像深度学习任务最容易卡住的点,不是模型不够强,而是数据不够多。一个分类任务,如果每个类别只有几百张图,你用 ResNet50 去训,哪怕加了一堆 Dropout、Weight Decay,训练集准确率很快就能冲到 99%,验证集却可能停滞在 85% 上下。这就是典型的过拟合信号:模型记住了训练样本的“长相”,但没有学到真正的类别特征。
我在早期某次工业缺陷检测项目里就吃过这个亏。当时采集到的真实缺陷样本只有几百张,正品样本倒是有一万多张,类别极度不均衡。最开始我直接拿原始图训练,验证集上的召回率一直上不去,后来换成预处理阶段做随机旋转、平移、亮度扰动之后,同样的模型结构,F1 从 0.73 涨到了 0.81。这个提升完全没动模型结构,也没有增加任何标注成本,纯粹是让模型在同一批数据上看到了更多“变体”。
数据增强之所以能起效,本质上是给模型提供了更多“同分布但不同形态”的样本,相当于把有限的数据集在训练时虚拟地扩大了若干倍。它同时起到了两层作用:一是降低模型对训练集中偶然特征的依赖,比如某类样本恰好都带同一个水印、同一个拍摄角度;二是让模型学到真正的平移不变性、旋转不变性、光照不变性——这些恰好是视觉任务里最常见的干扰因素。相比换更大模型、上更多正则化手段,数据增强是投入产出比最高的一步。
1.2 增强的本质:先验知识的注入与数据分布的扩充
很多人把数据增强简单理解成“多生成点图像”,其实它的本质是你在训练时手动注入“人类对视觉任务的理解”。举例来说,真实的猫照片不会永远在画面正中央,所以训练时做随机平移,是告诉模型“目标可能出现在任何位置”;真实场景的光线不会恒定,所以做亮度扰动,是告诉模型“颜色和亮度不是判断类别的可靠依据”。
这个视角很重要,因为它决定了你应该怎么设计增强策略。如果一个任务里目标永远是正着拍的(比如门牌号识别),那旋转增强不仅没有帮助,反而可能把数字转成难以辨认的角度,教会模型记住错误模式。反之,如果你的数据来自无人机航拍,目标朝向完全随机,那旋转增强几乎是必须的。增不增强、增强到什么程度,不取决于“大家都在做”,而取决于你对任务的先验判断。
数据分布的扩充同样值得展开说。原始数据集其实是真实分布的稀疏采样,训练时如果不做增强,模型很容易把样本之间的“空隙”当作分类边界,泛化自然差。增强操作本质上是沿着真实分布的流形,生成了一批邻近样本,把那些空隙填上了。Mixup 这类操作更进一步,它不光在图像空间插值,也在标签空间插值,相当于把决策边界拉平,这在类别容易混淆的任务里效果尤其明显。
1.3 数据增强的适用场景与边界
并不是所有场景都适合无脑堆增强。我曾经在一个遥感影像分割项目里尝试过大幅度的随机裁剪和旋转,结果精度反而下降。后来定位到原因:遥感影像里的地物有明确的尺度含义,一个建筑在 512 像素裁块里和 256 像素裁块里,视觉语义完全不同,过度缩放裁剪破坏了这种尺度关系。同理,医学影像里的病灶往往占比很小,过强的随机擦除可能直接把病灶区域抹掉,导致模型学到错误的负样本。
我的经验是:数据增强的强度应当与标注质量、数据量、任务类型三者联动。数据量越少,增强强度可以越大,但要控制在“不破坏语义”的范围内;数据量充足时,增强的边际收益递减,重点则应转向模型结构和训练策略。另一个边界是标注密集的任务,比如目标检测、关键点检测,增强时必须同步处理标注信息(框、点、分割掩码),操作不当会造成标注错位的脏数据,比不做增强危害更大。这个我会在后面的实战部分专门展开。
2. 经典数据增强手段全拆解:从几何变换到色彩扰动
2.1 几何类增强:翻转、旋转、缩放、裁剪的选择与参数
几何类增强是门槛最低、见效最快的一类操作。常用组合包括:
- 水平翻转:适用于自然图像分类、检测,但不适用于有方向语义的任务,比如文字识别、左右不对称的医学影像。
- 随机旋转:角度范围需要依据任务设定,通用场景建议 ±15° 到 ±30°,超过 45° 一般要谨慎,因为图像会裁掉大量边缘信息。
- 随机缩放:配合裁剪使用,相当于模拟目标尺度变化,对检测任务非常关键。
- 随机裁剪:既是增强也是数据扩增的主流手段,分类任务里常用 RandomResizedCrop,先随机选区域再缩放到固定尺寸。
参数怎么定?我给你一个可以直接参考的起点:分类任务用RandomResizedCrop(scale=(0.08, 1.0), ratio=(0.75, 1.333)),这组参数来自训练 ImageNet 的标准配置,在很多中低分辨率任务里直接套用也能稳住。检测任务里我常用的组合是缩放因子 0.5 到 1.5 倍、旋转 ±15°、水平翻转,配合 Albumentations 的ShiftScaleRotate一步完成。这里有个关键细节:旋转和缩放都会产生无效区域,需要决定是填充像素还是裁剪掉。我的建议是优先使用border_mode=cv2.BORDER_CONSTANT配合灰色填充,或者cv2.BORDER_REFLECT_101边缘反射填充,前者训练稳定,后者在分割任务里对边界区域的语义损伤更小。
还有一个新手容易忽略的点:几何增强的随机种子作用域。你要确保同一张图的所有增强操作共享一个随机状态,否则在检测任务里,图像做了平移裁剪但标注框没有同步偏移,标注就废了。Albumentations 把图像和标注统一处理,这个问题天然规避了,这也是我用它的核心理由之一。
2.2 色彩与光照类增强:亮度、对比度、饱和度、HSV 扰动
色彩类增强解决的是模型对光线和颜色分布的过拟合。工业场景里,同一个产品的照片可能因为产线光照波动出现色差;户外场景里,一天之内色温变化极大。如果不做色彩增强,模型很容易把“偏暗”和“某类缺陷”绑定起来。
常见色彩操作和参数范围:
| 操作 | 常用范围 | 注意事项 |
|---|---|---|
| 亮度调整 | ±0.2 左右 | 过强会让模型忽略暗部细节 |
| 对比度调整 | 0.8–1.2 | 大幅提升对比度容易引入伪纹理 |
| 饱和度调整 | 0.8–1.2 | 对颜色分明的任务要保守 |
| 色相调整 | ±0.05 以内 | 超过这个范围会导致语义颜色错乱 |
| HSV 扰动 | 参考上面三个 | 注意是否在 RGB/HSV 空间操作 |
这里有一个实操心得:色彩增强最好以“组”为单位做,而不是单独调某一个通道。我习惯用 Albumentations 的ColorJitter或HueSaturationValue,确保亮度和对比度联动变化。另一个细节是,训练时做色彩增强,验证和测试时不要做,否则你无法评估模型在原始分布上的真实表现。这个原则同样适用于灰度化操作——如果你训练时随机灰度化,验证集最好保留原色彩,除非你确定线上推理输入一定是灰度图。
我对色彩增强的强度建议是:宁可保守,不要激进。原因是颜色信息在某些任务里本身就是判别特征,比如车辆颜色识别、皮肤病变分类。这时候你把饱和度扰动开到 0.5,等于人为抹掉了类别差异,模型就算再努力也学不到该学的特征。
2.3 噪声与模糊类增强:高斯噪声、椒盐噪声、模糊处理
加入噪声和模糊,是为了提高模型对低质量输入的容忍度。真实场景的图片很少像公开数据集那样清晰干净:监控摄像头有噪点、手机拍摄有运动模糊、压缩上传后有 JPEG 伪影。如果你只在干净图上训练,推理阶段遇到一点噪声,性能就可能明显下滑。
噪声增强的常见做法:
- 高斯噪声:模拟传感器噪声,标准差建议 0.01 到 0.05,过强会淹没高频特征。
- 椒盐噪声:模拟像素丢失或坏点,密度建议 0.01 到 0.02。
- 高斯模糊:模拟对焦不准,核大小 3×3 或 5×5,sigma 0.5 到 1.5。
- 运动模糊:模拟相机抖动,对视频抽帧任务特别有用。
需要注意的是,噪声增强的强度不能跟模型输入分辨率脱节。小分辨率图像(比如 32×32 或 64×64)本身的像素信息就少,加一点噪声可能就把关键纹理盖住了;大分辨率图像则相反,可以适当加大噪声强度。我在某个车牌识别项目里验证过:只在 224×224 输入上加了轻微高斯噪声,测试集里夜间模糊图片的字符准确率提升了约 2 个百分点。
2.4 经典的组合策略与训练时的“双阶段”应用
单一增强手段的效果在大部分任务里都有限,关键是把不同类型的增强组合起来,模拟真实世界中多因素同时变化的情形。我用过的比较稳定的组合方式分两阶段:
第一阶段是“结构不变”的轻量增强,包括翻转、小角度旋转、小范围平移、轻微色彩扰动,几乎任何任务都可以加,风险极低。第二阶段是“结构变化”的强增强,包括随机裁剪缩放、大角度旋转、擦除、Mixup 等,需要根据任务判断是否适用。
为什么要分阶段?因为很多增强操作是互斥的。比如你做了随机裁剪再做大角度旋转,图像的边缘信息损失会叠加,训练难度指数上升。阶段化组合可以控制增强后的图像不会偏离真实分布太远。我在组织流水线时,一般遵循“几何一组、色彩一组、噪声一组,每组内部可选,组间顺序固定”的原则,这样既保证了多样性,又便于排查到底哪一步出了问题。
3. 进阶策略:Mixup、CutMix、随机擦除与自动增强
3.1 Mixup:样本插值与标签平滑的协同作用
Mixup 的思想非常直接:把两张训练图按比例混合,标签也按同样的比例混合。
它的做法是:从训练batch里随机取两张图 x_i 和 x_j,按 λ 加权求和,得到混合图;对应的 one-hot 标签也按 λ 混合。λ 通常从 Beta 分布采样,论文里的推荐参数是 α=0.2 或 α=1.0。α 越小,λ 越靠近 0 或 1,混合程度越低;α 越大,两张图混合得越均匀。
我在分类任务里用它,最大的感受有两个。一是训练损失曲线会变得“难看”,因为每次迭代的 loss 不再反映某一个真实类别的分类错误,而是两个类别加权后的交叉熵。新手看到 loss 不降或者波动大可能慌,但其实这是 Mixup 的正常表现,你需要看的不是单步 loss,而是验证集准确率的趋势。二是 Mixup 对模型结构几乎没有要求,直接作用于数据流,切换模型时不用改任何代码,非常友好。
不过 Mixup 在目标检测和分割任务里有坑。图像的混合会导致标注信息交叉重叠,两个目标的框会叠在一起,标签语义互相污染。虽然有一些针对检测的 MixUp 变体,但工程复杂度高,我一般不建议新手直接上。
3.2 CutMix 与 Cutout:局部擦除带来的鲁棒性提升
Cutout(随机擦除)的思路是:随机遮住图像中的一块矩形区域,用中性色或噪声填充,强迫模型不要依赖局部特征。它和 Dropout 的思想是一脉相承的:Dropout 在特征图上随机丢弃神经元,Cutout 在输入图像上随机擦除区域。对遮挡物体、局部遮挡场景(比如行人被部分遮挡)尤其有效。
CutMix 则更进一步:它不是用灰色块填充,而是把另一张图的某个区域裁剪过来贴上去,标签也按面积比例混合。它同时结合了 Cutout 的局部擦除和 Mixup 的样本混合两个优点,在不少公开数据集上的表现都优于两者。
实际使用时有几个参数需要关注:
- Cutout 的擦除区域大小:一般控制在图像短边的 1/8 到 1/4,太大了会盖住目标主体。
- Cutout 擦除次数:1 到 3 次比较合适,多次擦除适用于多目标场景。
- CutMix 的裁剪区域比例:一般随机选取目标区域占全图比例的一半左右。
我在细粒度分类项目里做过对比:只加随机擦除,验证集 top-1 提高了约 1.5 个百分点,再加 CutMix,又提高了约 1 个百分点。这类操作对于“局部特征过强”的任务非常对症。
3.3 RandAugment 与 AutoAugment:自动搜索增强策略的原理
如果不想手动调增强组合,自动增强搜索提供了一个“让策略自己找最优解”的思路。AutoAugment 的做法是在一个预定义操作池里,用强化学习搜索出“哪种增强操作、哪种强度、哪种概率”的组合最优。这种方法效果不错,但搜索成本极高,需要在小模型上跑几百小时,普通项目几乎用不起。
RandAugment 是它的低成本替代。它把问题简化成两个超参数:全局强度 M 和操作数量 N。每个训练批次里从操作池随机抽取 N 个操作,按强度 M 依次作用到图像上。操作池包括旋转、平移、剪切、颜色抖动、对比度、锐化、反色等十几种策略,随机组合起来就形成了非常丰富的增强空间。
这带来了一个工程上的好处:你只需要调两个参数,而不是十几组参数。M 从 5 到 15 是个常见的搜索区间,我一般先用 M=10、N=2 起步,然后看验证集曲线微调。要注意 RandAugment 里包含反色、锐化这类强操作,对某些任务副作用很大。比如反色会让肤色、肤色相关特征完全错乱,所以在人脸任务里我会手动从操作池里去掉这一类。
3.4 几种增强策略的互补性与选型建议
Mixup、CutMix、Cutout、RandAugment 这几种策略并不冲突,可以组合使用。我常用的组合方式是:先做几何和色彩的基础增强,再按一定概率做随机擦除,最后在 batch 层面做 Mixup 或 CutMix。这个顺序有讲究:底层变换负责丰富样本形态,擦除负责增强局部鲁棒性,Mixup/CutMix 负责拉平滑决策边界。三者各司其职,叠加后的收益大于任意单一策略。
选型上我给出一个参考:
| 场景 | 首选方案 | 原因 |
|---|---|---|
| 小样本分类 | 基础增强 + Cutout + RandAugment | 覆盖多种形态,风险可控 |
| 类别混淆严重 | 基础增强 + Mixup | 拉平决策边界 |
| 目标检测 | 几何增强 + 尺度变化 + Cutout(注意框同步) | 保留标注语义 |
| 遮挡场景 | 局部增强 + CutMix | 模拟遮挡 |
| 细粒度分类 | 轻度色彩 + 随机擦除 | 避免破坏细微差异 |
这里的关键心态是:增强策略不是越多越好。每个操作都引入了分布变化,操作叠加过多时,训练数据的分布已经被“扭曲”到离真实分布很远的程度,模型学到的东西反而失去针对性。如果你加上某个增强后验证集掉点,先不要怀疑训练轮数太少,大概率是增强强度或操作本身不适合当前任务,果断去掉比硬调超参数更省时间。
4. 实操:用 PyTorch 和 Albumentations 落地一套增强流水线
4.1 工具选型:为什么我推荐 Albumentations
PyTorch 自带的torchvision.transforms简单直接,但有两个痛点:一是标注同步处理麻烦,二是操作丰富度一般。torchvision.transforms.RandomResizedCrop这类操作没法直接拿到变换参数去同步变换标注框。Albumentations 则专门解决了这个问题,它的Compose可以对图像和对应的 boxes、masks、keypoints 做统一变换。
我特意在某个目标检测项目里做过对比:同样在 CPU 上做增强,Albumentations 比 OpenCV 手写流程快大概一倍,因为它是用 Cython 和 NumPy 并行实现的。训练时增强速度直接影响到整体迭代速度,数据量越大的项目,这个差距越明显。
另外,Albumentations 支持从torchvision.transforms借道或者直接配合 PyTorch Dataset 使用,集成成本极低。我通常只在数据加载的__getitem__里调用它,输出转成 tensor 后再叠加上归一化操作即可。
4.2 一个可复用的增强配置:分类与检测任务的参数选择
下面这套配置是我在多任务里反复验证过的,分类和检测任务可以在此基础上微调。
分类任务配置:
import albumentations as A from albumentations.pytorch import ToTensorV2 train_transform = A.Compose([ A.RandomResizedCrop(size=(224, 224), scale=(0.08, 1.0), ratio=(0.75, 1.333), p=1.0), A.HorizontalFlip(p=0.5), A.ShiftScaleRotate(shift_limit=0.02, scale_limit=0.1, rotate_limit=15, p=0.5), A.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.05, p=0.5), A.CoarseDropout(max_holes=1, max_height=32, max_width=32, fill_value=0, p=0.3), A.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), ToTensorV2(), ])这里每个操作的 p 值代表应用概率。我的经验是,概率 0.3 到 0.5 是“温和有效”的区间,超过 0.8 意味着绝大部分样本都会被强变换,模型的输入分布会被过度改变。如果你希望增强更强,优先调 p 值和强度参数,而不是把概率抬到 1.0。
检测任务配置,重点在标注框同步:
train_transform_det = A.Compose([ A.RandomResizedCrop(size=(640, 640), scale=(0.5, 1.5), ratio=(0.8, 1.25), p=1.0), A.HorizontalFlip(p=0.5), A.RandomBrightnessContrast(brightness_limit=0.2, contrast_limit=0.2, p=0.5), A.HueSaturationValue(hue_shift_limit=10, sat_shift_limit=20, val_shift_limit=20, p=0.5), A.DomainAdaptation if False else A.NoOp(), # 占位 A.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), ], bbox_params=A.BboxParams(format='pascal_voc', label_fields=['labels']))bbox_params是关键参数,它告诉 Albumentations 同步处理框坐标。format='pascal_voc'表示框的格式是 [xmin, ymin, xmax, ymax]。不同检测框架的框格式不同,YOLO 要用'yolo'(中心点坐标加宽高),COCO 要用'coco'(左上角加宽高),搞错格式会导致训练时标注全部错乱。这类问题往往只在训练日志里看到 loss 不下降时才暴露出来,排查成本很高。
4.3 增强强度与训练轮数的平衡:什么时候该收敛强度
增强策略不是一成不变的。我的一个经验是:训练初期和后期对增强的需求不同。训练初期,模型还在学习基本结构,稍强一些的增强有助于快速建立泛化能力;训练后期,模型对增强后的数据越来越敏感,如果增强强度不变,loss 可能一直在一个平台期徘徊,这时适当降低增强强度,让模型在更接近真实分布的数据上微调,往往能带来最后的精度提升。
这种渐退(annealing)策略我常用两种实现方式。一种简单:按 epoch 线性降低 p 值或强度参数;另一种更常见:在不同训练阶段切换不同的增强配置,比如前 70% 轮数用强增强,后 30% 用轻增强。具体切换点需要根据验证集曲线决定,如果验证集在后期持续下降,说明增强强度或学习率还没协同好。
还要提一个很多人忽略的点:增强的随机种子。如果你开启了分布式训练或多次实验复现,增强操作的随机性会让每次实验的抖动变大。我一般在调试阶段固定增强的随机种子,确保两次实验的差异完全来自参数变化,而不是增强随机的干扰。正式训练时再放开随机性,以获得更好的泛化。
4.4 增强在推理阶段的一致性规则(test-time augmentation)
推理阶段的增强被称为 TTA(Test-Time Augmentation),思路是推理时对同一张图做多次增强变换,对多个预测结果取平均或投票,通常能带来 0.5 到 1 个百分点的收益。我通常会做水平翻转 TTA,有时叠加多尺度缩放。
举一个简单实现:
import torch import albumentations as A def predict_with_tta(model, image, device): model.eval() # 原图 + 水平翻转 images = [image, A.HorizontalFlip(p=1.0)(image=image)['image']] preds = [] with torch.no_grad(): for img in images: tensor = torch.tensor(img).permute(2, 0, 1).unsqueeze(0).to(device) pred = model(tensor) preds.append(pred) # 翻转后的预测需要翻回来再平均 preds[1] = torch.flip(preds[1], dims=[3]) return torch.stack(preds).mean(dim=0)TTA 的关键是“一致性”:训练时做了什么变换,推理时要对变换结果做逆变换再平均。翻转的预测要翻转回来,旋转的预测要旋转回去,否则平均结果不具任何意义。另外 TTA 会成倍增加推理耗时,工业部署时要评估延迟预算,实时场景一般不建议用,离线评测阶段倒是可以大胆使用。
5. 常见问题与排查技巧实录
5.1 增强过头导致训练不收敛怎么办
最典型的现象是:训练 loss 在初始值附近震荡,下降速度极慢,甚至越训练越差。这时候第一反应是检查增强强度。处理方式是把增强配置里的操作概率全部先归零,只留水平翻转,看 loss 是否能正常下降。
肯定能。然后你再逐步加回操作,每次只加一个,观察 loss 曲线变化。这个过程虽然麻烦,但比同时调十几个参数高效得多。我遇到过一次 Rotate 旋转角度加到 45°,加上 RandomResizedCrop 之后,网络迟迟不收敛,把旋转角度降回 15° 后马上正常。增强策略之间会互相放大,单独看每个操作都没问题,组合起来就可能失控。
另一个经验是:分辨率越低,增强越要轻。小尺寸输入图包含的信息本来就少,再叠加强几何变换,很多有效信息会被挤压到图像边缘之外,模型能学的东西就更少了。如果你的输入尺寸只有 96×96 或 128×128,建议把旋转角度限制在 10° 以内,RandomResizedCrop 的 scale 下界也不要低于 0.5。
5.2 目标检测中增强后标注框错位问题
标注框错位在目标检测训练里的表现通常是:训练 loss 前期正常,后期猛增,或者模型输出的框总是偏移固定方向。我遇到过的原因主要有三类。
第一类是 bbox 格式配置错误。Albumentations 的BboxParams里format参数设错,坐标解读就全错了。排查方法是打印一组增强前后的图片和框,直接可视化看,一眼就能发现错位。
第二类是增强操作没有传入正确的标签信息。很多人只传image=,忘了传boxes=和labels=,Albumentations 会安静地只处理图像,标注不动。代码不报错,但结果就是图变了框没变。
第三类是越界框的处理方式问题。裁剪或旋转后,部分框可能跑出图像边界,Albumentations 的默认策略是直接丢弃。如果一张 640×640 的图里小目标很多,丢弃比例过大,等于训练样本被大量削减。这时候可以把min_visibility参数降低,比如 0.3,让部分可见的小框也保留下来,模型才有机会学到小目标的部分特征。
5.3 分类任务里增强失效的几个隐蔽原因
增强没有带来任何收益时,先怀疑以下原因。第一,验证集没有被同等增强——这不是麻烦,恰恰是很多人的误解。验证集不应该用训练增强,但很多人为了“提升验证集分数”做了 TTA 或增强,这会让实验对比失真,真实模型在线上表现反而没变。
第二,增强操作和数据读取顺序不对。某些框架在解码图片后才做增强,但 JPEG 解码后图像的像素分布已经和增强假设不一致,虽然这种偏差通常很小,但在极端压缩的图片上会被放大。我的建议是尽量在增强前做归一化到 0 到 1 或 0 到 255 的标准区间,统一后再操作,避免色彩类增强在某些像素取值范围下失效。
第三,某些库默认配置不尽合理。Albumentations 的ColorJitter参数和 torchvision 的默认值有明显的幅度差异,从 torchvision 迁移过来时如果直接沿用推理阶段假设,可能增强强度根本不是你以为的那个值。换个工具之前一定要先打印几组增强后的图,用肉眼确认强度是否符合预期。
5.4 排查清单与快速验证方法
这里整理一份快速排查清单,我每次增强效果异常时都会按它走一遍:
| 排查项 | 检查方法 | 常见结果 |
|---|---|---|
| 增强可视化 | 保存增强前后图像对比 | 确认强度与语义保留 |
| 标注同步 | 叠加绘制增强后的框/掩码 | 发现错位与越界 |
| 训练曲线 | 单独跑 20 轮基础 vs 全增强 | 排除组合过强 |
| 分布一致性 | 对比训练集/验证集增强强度 | 发现验证集标准不一致 |
| 随机种子 | 固定种子重复两次实验 | 评估增强随机引入的方差 |
检查增强是否有效的快速方法:固定模型结构、优化器、学习率,只在增强配置上做 A/B。先跑一个无增强基线,再跑“基线 + 单个增强操作”,每个操作独立对比。看起来要花不少训练时间,实际上因为只有变量不同,20 轮以内就能看出趋势,比盲目堆增强高效得多。有一次我在某个细粒度分类任务上发现了一种增强操作单独几乎无效,但和另一个操作组合后收益接近 2 个百分点。这种协同效应不用 A/B 是发现不了的,很容易被误删掉一个本可保留的策略。
最后再说一个我反复碰壁后总结出的原则:数据增强准确说是“数据相关的模型正则化”,它需要和模型、数据一起调优,而不是一次性配置好就不管了。每次换数据集、换模型结构,都要重新审视一遍增强策略。那些在 ImageNet 上效果极佳的配置,直接迁移到小规模工业数据上可能适得其反;反过来,针对小数据精心设计的增强组合,在大量数据上也没有必要强行保留。数据增强没有银弹,最好的策略一定是基于对任务的深度理解,加上一次次的实验验证。这个思路,比任何具体的参数表都更值得带走。