☰
数据扩充实战:从数据增强到生成式方法,解决小样本训练难题
2026/10/6 1:33:46 网站建设 项目流程

简介:面对深度学习训练中数据集不足的常见困境,这份PDF提供了一套可直接落地的图像扩充方案。内容围绕亮度增强、对比度增强、水平翻转和随机方向旋转四种变换展开,基于PIL的ImageEnhance模块编写,给出了brightnessEnhancement、contrastEnhancement、flip、rotation及批量处理函数createImage的完整代码,可通过随机系数模拟不同光照与角度变化,将1406张原始图像一键扩展至7030张,有效缓解样本过少导致的过拟合与精度下降问题。程序可自动遍历指定文件夹并批量保存新图,增强图可与原图混放或单独存放,灵活适应不同整理需求。资料为单个PDF文件,压缩包约35KB,轻量易读,适合刚接触深度学习、需要快速扩充图像数据的图像分类或目标检测学习者参考。已有12659人学习浏览,实用价值获得广泛验证。下载后可直接按代码修改输入输出路径生成增强图像,节省自行摸索时间。

1. 数据集太少怎么办:先别急着生成,把“扩充”拆成三个层次

做目标检测或者分类任务时,标注好的数据只有几百张,模型一训练就过拟合,验证集 loss 像过山车,这是几乎每个入门者都会撞上的墙。很多人第一反应是上生成模型、找预训练大模型“无中生有”,但在工业落地里最高效的路径往往是反过来的:先做传统数据增强,再引入外部数据集做预训练或微调,最后才轮到生成式方法。这篇内容围绕数据集扩充的完整落地路径展开,覆盖从图像几何变换、MixUp/CutOut 这类经典增强,到如何用公开数据集(比如 CCPD、HRSC2016、PHM2012)做迁移,以及扩充后如何验证模型真的变强了而不是变“虚胖”。适合正在用 YOLOv8 或 MMDetection 训练自有数据集、但被数据量卡住的算法工程师和学生。

2. 数据增强不是“加噪声”:先搞清增强的数学本质和分类

2.1 增强为什么有用:从过拟合的成因说起

模型在少量数据上过拟合,本质是经验风险最小化遇到了“伪特征”。比如你的车辆检测数据集里所有轿车都是白色的,模型学到的是“白色块 + 轮子轮廓”的组合,而不是“轿车”这个抽象概念。数据增强做的事情,是通过对样本施加在真实世界中大概率出现的变换,迫使模型学到对变换不敏感的特征。

从数学角度看,增强是在估计数据的“等效先验”。你用随机裁剪、翻转、色彩抖动生成的新样本,等价于在原数据分布上做了一个邻域平滑。这个平滑半径如果太小,模型照样记住原样本;如果太大,生成样本偏离真实分布,反而污染训练。这也是为什么增强策略需要放在验证集上去调,而不是拍脑袋堆一堆变换。

另外一个常被忽略的点:增强不只是给训练集“加量”,它相当于在给模型做正则化。以图像分类为例,你用 CutOut 随机遮掉一块,模型就必须依赖更多的上下文区域去判断类别,这会显著降低对局部纹理的过拟合。研究结论也表明,像随机擦除、MixUp 这类增强在小数据集上的收益,比在大数据集上更明显,因为它起到了隐式模型集成的作用。

2.2 哪种模型吃哪套增强:检测、分类、分割和序列任务的差异

分类任务最简单,几何变换加色彩抖动基本够用。但要注意,翻转和旋转不一定总是安全的,比如 OCR 识别里的“6”和“9”,旋转 180 度就把标签改了;手写数字识别中旋转 90 度也可能改变语义。所以增强流程必须设计成“标签不变”或“标签跟随变换”两类。

目标检测最常用的是马赛克增强(Mosaic),它把四张图拼成一张,等于同时增加了样本数、引入了上下文多样性、平衡了 batch 内的目标分布。YOLOv8 里默认开启 Mosaic 和 MixUp,我在小数据集上测试过,单独关掉 Mosaic 后 mAP 掉了 3~5 个点,尤其对小目标影响明显。

语义分割要特别注意:几何变换必须作用在图像和 mask 上,而且是同一套变换参数。用 albumentations 库做分割增强时,它内部会处理好这个问题,但用 OpenCV 手写增强时很容易出现只变换了图、忘记变换 mask 的翻车操作。

**序列数据(如 PHM2012 轴承振动数据)**的增强思路完全不同,常用的有:时间轴加噪、幅值缩放、时间扭曲(Time Warping)、通道随机掩码。核心原则是增强后样本仍然来自同一个物理过程,不能把振动信号的频域特性改坏了。

2.3 经典代码实践:用 Albumentations 构建一个可复用的增强管线

下面是一个我在检测和小样本分类里常用的增强管线,可以直接替换到自己的训练脚本里,统一封装之后再喂给模型:

import albumentations as A from albumentations.pytorch import ToTensorV2 import cv2 def get_train_augmentations(img_size=640): """ 目标检测/分类通用增强管线 """ return A.Compose([ # 几何变换:随机缩放、平移、旋转,影响图像和 bbox A.RandomResizedCrop( height=img_size, width=img_size, scale=(0.5, 1.0), ratio=(0.8, 1.2), p=0.8 ), A.HorizontalFlip(p=0.5), # 光度变换:模拟光照和相机差异 A.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.1, p=0.5), A.RandomGamma(gamma_limit=(80, 120), p=0.3), # 遮挡类增强:让模型学会“就算挡住一部分也能认出来” A.Cutout(num_holes=8, max_h_size=32, max_w_size=32, fill_value=0, p=0.4), A.MixUp(reference_data=None, p=0.2), # 如果参考数据为空,该操作会被跳过 A.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)), ToTensorV2() ], bbox_params=A.BboxParams( format='pascal_voc', label_fields=['class_labels'], min_visibility=0.3 # 遮挡后 bbox 可见比例小于 0.3 的样本会被过滤 )) # 使用方式:读图之后直接调用 image = cv2.imread("sample.jpg") image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) boxes = [[100, 120, 300, 380]] # xmin, ymin, xmax, ymax class_labels = ["car"] augmented = get_train_augmentations()( image=image, bboxes=boxes, class_labels=class_labels ) aug_img = augmented["image"] aug_boxes = augmented["bboxes"]

这段代码里有几个参数需要认真调:RandomResizedCrop的scale范围决定了模型看到的目标尺度变化幅度,如果原始图像里目标本身就很小,scale下限不要低于 0.6,否则训练图像里会出现大量“目标只有几个像素”的样本,模型会学歪。Cutout的num_holes和块大小需要根据目标尺寸来,如果你检测的是行人这样的大目标,可以适当加大遮挡块;如果是小目标,遮挡块超过目标大小就会把目标完全抹掉,等于制造了一堆背景样本。min_visibility这个参数很多人忽略,它控制遮挡后 bbox 最小可见比例,设得太低会让模型在不可见的位置上也强行“预测”出框,设太高则失去了遮挡增强的效果,一般 0.3 是一个不错的折中值。

3. 开源数据集拿来即用:CCPD、HRSC2016 和 PHM2012 到底怎么帮到你

3.1 不同任务怎么选外部数据集:先看域差异再谈数据量

不要看到数据集就下载,扩充数据的第一步是判断“这个数据集的分布离我的任务有多远”。拿 CCPD 来说,它是中国车牌检测数据集,图像全部来自城市道路监控,视角偏俯视、光照变化大、背景复杂。如果你的业务是停车场出入口的车牌识别,CCPD 就是绝佳的预训练来源;但如果你是做高速公路卡口抓拍的车牌识别,CCPD 里那种多车牌、小尺度、密集场景就和你的域差异较大,直接微调反而起副作用。

HRSC2016 是遥感舰船检测数据集,图像来自 Google Earth 和航拍,目标在图像里占比很小、朝向任意。它最典型的用法是做旋转框检测的预训练数据,因为遥感场景和舰船目标的特点就是“多朝向”。用 MMrotate 训练 DOTA 数据集时,很多人会用 HRSC2016 先跑一个旋转检测预训练模型,然后迁移到 DOTA 上做微调,能明显加快收敛速度。

PHM2012 是轴承加速寿命试验数据,专门给故障诊断和剩余寿命预测用。它有 3 个工况、6 个轴承的健康状态数据,每类故障样本数量有限,因此很适合用来测试“小样本下怎么扩充”的方法。它的数据格式是 CSV,每列是振动加速度信号,采样率 25.6kHz。很多论文用它的训练集做少样本故障诊断实验,测试集做泛化验证。

3.2 预处理才是关键:把外部数据集转成自己的训练格式

下载完 HRSC2016 或者 CCPD 之后,面临的第一个问题是数据格式不统一。HRSC2016 的标注是 XML 格式,朝向用 rotated rectangle 四个顶点表示;CCPD 的标注直接写在文件名里,比如025-95_91-211&490_394&541-394&541_211&490_211&347_394&347-0_0_27_28_31_51_31_30-113-103,中间那段就是车牌的四个顶点坐标和角度信息。这种格式和 YOLO 的x_center y_center width height完全不兼容,所以要先写脚本做转换。

下面是我把 HRSC2016 转成 YOLO 旋转框格式的脚本核心部分,配合 MMrotate 使用:

import xml.etree.ElementTree as ET import os def hrsc2016_convert(xml_path, out_txt_path, class_map): """ 把 HRSC2016 的 XML 标注转成 DOTA 格式的 txt DOTA 格式: x1 y1 x2 y2 x3 y3 x4 y4 class_name difficult """ tree = ET.parse(xml_path) root = tree.getroot() # HRSC2016 的 object 节点里包含目标的类别和四个顶点坐标 objects = root.findall(".//HRSC_OBJECT") lines = [] for obj in objects: class_name = obj.find("Class_Name").text if class_name not in class_map: continue # 四个顶点坐标存在 Object_Box 下 box = obj.find("Object_Box") # 注意: 不同版本 HRSC2016 的 XML 结构略有差异,这里兼容两种常见结构 points = box.find("points") if box.find("points") is not None else box pts = points.findall("point") # 四个顶点按逆时针排列 coords = [] for p in pts: x = float(p.find("x").text) y = float(p.find("y").text) coords.extend([x, y]) # 追加类别名和难度标记 diff = obj.find("difficult") difficult = int(diff.text) if diff is not None else 0 lines.append(f"{coords[0]} {coords[1]} {coords[2]} {coords[3]} " f"{coords[4]} {coords[5]} {coords[6]} {coords[7]} " f"{class_map[class_name]} {difficult}") with open(out_txt_path, "w") as f: f.write("\n".join(lines)) # 类别映射根据实际任务调整 class_map = {"Ship": "ship"} # 遍历所有 XML 文件 xml_dir = "HRSC2016/Test/Annotations" out_dir = "HRSC2016/Test/labelTxt" os.makedirs(out_dir, exist_ok=True) for xml_name in os.listdir(xml_dir): if not xml_name.endswith(".xml"): continue xml_path = os.path.join(xml_dir, xml_name) out_txt = os.path.join(out_dir, xml_name.replace(".xml", ".txt")) hrsc2016_convert(xml_path, out_txt, class_map)

这段脚本里的核心逻辑是 XML 解析和坐标提取。有一个很坑的地方:HRSC2016 的 XML 中,points节点的结构可能在不同版本中不一样,有的版本直接放在Object_Box下,有的版本包了一层。所以我在代码里做了兼容判断,两个分支都试。另一个坑是difficult标签的取值,有些版本是布尔值,有些是 0/1 整数,转换时统一转成 int,否则 DOTA 评测时可能会读错。

转换完成之后还要做一件事:统计转换后的标注框坐标,看看有没有超出图像边界的。HRSC2016 的原始图像尺寸比较大(通常在 1000 像素以上),如果剪裁过训练图像,部分目标的四个顶点可能落在图像外面,需要做坐标裁剪或者直接丢弃该样本,否则训练时 loss 会异常跳变。

3.3 PHM2012 的扩充实践:时域信号怎么“增强”才不破坏物理含义

PHM2012 数据集的扩充方式和图像完全不同。振动信号里做简单的翻转,会直接改变信号的时序因果关系,这在轴承故障诊断里是致命的。常见的做法是加噪、幅值缩放和频率谱扰动。下面是一个基于 PyTorch 的时域信号增强代码:

import torch import torch.nn.functional as F def time_domain_augment(signal, mode="noise", noise_std=0.02): """ 对一维振动信号做时域增强 signal: tensor of shape (seq_len,) 或 (batch, seq_len) mode: noise / scale / time_warp / mask """ if mode == "noise": noise = torch.randn_like(signal) * noise_std return signal + noise elif mode == "scale": # 幅值缩放:模拟不同载荷下的振动强度变化 factor = torch.empty(1).uniform_(0.8, 1.2).to(signal.device) return signal * factor elif mode == "time_warp": # 时间扭曲:用插值把信号在时间轴上做非均匀拉伸 seq_len = signal.shape[-1] # 生成一个非线性的时间映射 t = torch.linspace(0, 1, seq_len, device=signal.device) t_warped = torch.clamp(t + 0.1 * torch.sin(t * 6.28), 0, 1) # 使用插值函数重新采样 idx = (t_warped * (seq_len - 1)).long() warped = signal[..., idx] return warped elif mode == "mask": # 随机遮掉一小段信号,模拟数据采集时的丢包 seq_len = signal.shape[-1] mask_len = int(seq_len * 0.05) # 遮挡 5% 长度 start = torch.randint(0, seq_len - mask_len, (1,)).item() masked = signal.clone() masked[..., start:start+mask_len] = 0 return masked else: raise ValueError(f"Unknown mode: {mode}")

使用时要特别注意噪声幅度noise_std。PHM2012 原始振动信号的幅值范围大约是 ±2g 左右,我测试下来噪声标准差在 0.02 时扩充效果最好,太大则会把信号的主要频率成分淹没,太小则起不到泛化作用。时间扭曲的参数0.1 * sin(t * 6.28)表示时间轴最大拉伸幅度是 10%,如果一个轴承从正常到故障的退化过程本身不是均匀的,这种增强方式有一定合理性。但注意不要在多分类故障诊断任务里用时间扭曲,我踩过坑:把不同故障类别的振动信号做同样幅度的扭曲,可能会抹掉类别之间的频谱差异。

4. 生成式数据扩充:什么时候该用 GAN / Diffusion,怎么评估生成质量

4.1 生成模型的适用边界:不是所有“缺数据”都该上生成

传统增强的上限是“围绕原样本做扰动”,它不能创造新的场景组合。比如你的数据集里只有白天的高速公路车辆图像,不管怎么翻转、调色,都变不出夜间车灯点亮的效果。这时候才轮到生成式数据扩充上场。

但生成式扩充有两个硬伤:一是训练生成模型本身需要足够数据,如果你连 200 张原图都没有,GAN 很容易训练崩坏,生成结果全是模糊色块;二是评估生成样本对下游任务是否有正收益,需要额外的实验验证,很多情况下生成样本是“看起来像真的,但模型学不到有用的特征”。我在车牌识别任务上做过对比实验:用扩散模型生成 1000 张车牌图混入训练集,最终 mAP 只提升了 0.8 个点,而用传统增强 + 外部数据集 CCPD 做预训练,同样增加数据量,mAP 提升了 3.2 个点。成本差异是数量级的。

4.2 用扩散模型生成训练图的实操:ControlNet + 局部重绘

如果你确实走到了生成这一步,当前最可控的方案是“真实样本局部重绘 + ControlNet 条件控制”。具体来说,拿到一批真实图像后,用 GroundingDINO 检测出目标位置,然后用 SAM 分割出目标掩膜,再用 ControlNet 以边缘为条件,只对目标区域做局部重绘。这样生成的图像背景完全真实,只有目标区域被替换,并且目标姿态和位置受边缘约束,不会出现“车飘在半空中”这类明显错误。

import cv2 import torch from diffusers import StableDiffusionControlNetPipeline, ControlNetModel from PIL import Image # 加载 ControlNet 模型,使用 canny 边缘作为条件 controlnet = ControlNetModel.from_pretrained( "lllyasviel/sd-controlnet-canny", torch_dtype=torch.float16 ) pipe = StableDiffusionControlNetPipeline.from_pretrained( "runwayml/stable-diffusion-v1-5", controlnet=controlnet, torch_dtype=torch.float16 ) pipe.safety_checker = None # 避免安全审核模块干扰正常的车辆/工业图像生成 pipe = pipe.to("cuda") def local_repaint(image_path, mask_path, prompt, output_path): """ 基于 ControlNet 的局部重绘 image_path: 原始图像路径 mask_path: 目标区域的掩膜路径(白色=需要重绘) prompt: 描述要生成的区域内容 """ image = Image.open(image_path).convert("RGB") mask = Image.open(mask_path).convert("L") # 从原图提取 canny 边缘,作为结构约束 img_cv = cv2.cvtColor(numpy_image(image), cv2.COLOR_RGB2BGR) edges = cv2.Canny(img_cv, 100, 200) edges_pil = Image.fromarray(edges).convert("RGB") # 局部重绘:只对掩膜区域内重新生成 result = pipe( prompt=prompt, image=edges_pil, mask_image=mask, num_inference_steps=30, guidance_scale=7.5, strength=0.75 # 关键参数:值越小越接近原始图像 ).images[0] result.save(output_path)

这里strength=0.75是关键参数。如果设成 1.0,生成区域完全由扩散模型重画,目标外观可能发生较大变化;设成 0.5 以下,基本上只是做了颜色微调。生成后一定要人工抽查结果,把“目标被生成成了奇怪形状”的样本剔除掉,不要让脏数据直接进训练集。另外强烈建议:生成样本和真实样本混合时,比例控制在真实样本的 50% 以下。生成样本占比过高会让模型偏向“生成风格”,真实样本上的表现反而下降。

4.3 评估生成数据质量的三个具体指标

不要看生成图像“顺不顺眼”,要看它能不能帮模型变强。我一般用下面三个指标筛选生成数据:

检测置信度:用当前已经训练好的模型去检测生成图像,如果置信度普遍低于 0.3,说明生成的目标外观和模型学到的特征偏差太大,要么生成失败,要么模型还没学会。这个指标能快速筛掉一批明显不合格的数据。

FID 分桶对比:把生成样本按场景分组(比如按背景、光照条件分桶),分别计算和真实样本之间的 FID。如果某一桶的 FID 明显高于其他桶,说明生成器在该场景下失真严重,那批样本优先丢弃。

训练收益验证:最可靠的方式是控制变量。把生成数据按 0%、20%、40%、60% 四个比例混入训练集,其他超参不变,训练并比较验证集 mAP。如果 40% 比 20% 的收益还在提升,说明生成数据质量不错,可以继续加;如果到某个比例后 mAP 开始下降,说明生成数据的分布开始“带偏”模型了。

5. 扩充后训练避坑指南:我在这 5 个坑里翻过车

5.1 增强和验证集“串通”:把增强后的重复画面泄进了评估集

现象:训练集 loss 一路下降,验证集指标却纹丝不动。

原因:在使用 Albumentations 做增强时,没有把验证集重置为原始图像,而是把同一个样本的多种增强版本同时出现在训练集和验证集里(比如水平翻转前后的图像都出现在两边),导致验证集失去独立性。

解决:验证集必须使用独立的、未经增强的图像。如果你是在同一个文件夹下随机切分训练/验证集,那么先做切分、再做增强,并且把增强后的图像直接写到另一个目录。用albumentations时,训练集用Compose(..., p=0.9)的增强,验证集只做Normalize + ToTensor。

5.2 旋转增强把语义标签改掉了

现象:OCR 或者带方向性的检测任务里,模型在训练集上收敛正常,真实场景下误检率突然飙升。

原因:对“6”和“9”这类字符做 180 度旋转,标签没有跟着改;对交通指示牌做旋转后,“向左转”的标志可能变成了“向右转”。

解决:在增强配置里关闭不安全的变换。我的习惯是,分类任务只保留水平翻转(大部分情况下垂直翻转也关掉),检测任务只在类别和方向无关时启用旋转。如果你确实需要旋转,使用Rotate(limit=15, border_mode=cv2.BORDER_CONSTANT)这种小角度限制,避免 90 度级别的突变。

5.3 外部数据集引入后反而让模型“变笨”

现象:用 CCPD 预训练然后在自己数据上微调,收敛速度变快了,但最终 mAP 比不用预训练还低 1 到 2 个点。

原因:预训练数据集和目标域的差异太大。监拍视角的车牌和 CCPD 的监控视角差异很大,模型在预训练阶段学到的特征对目标域帮助有限,微调时还需要花大量容量去“忘记”旧特征。

解决:不要盲目用大规模数据集做预训练。先用域相似度判断,跑一个简单的对比实验:用预训练模型做特征提取,在少量目标域数据上做线性探测,如果分类准确率低于 80%,说明特征迁移价值有限。这种情况下,优先在目标域数据上用传统增强 + MixUp 撑数据量,比硬上迁移学习靠谱。

5.4 数据扩充把样本量撑大了,但训练时间暴涨

现象:数据集从 500 张扩到 5000 张,每次 epoch 训练时间翻了 10 倍,迭代周期变得不可接受。

原因:增强操作在数据加载时实时执行,CPU 成了瓶颈。Mosaic 和 MixUp 这类操作本身计算量就不小。

解决:两个思路。第一,把增强后需要固定复用的样本(比如所有 Mosaic 样本)离线生成并缓存到磁盘,训练时直接读缓存,能省掉大量在线计算;第二,用DALI或者data.num_workers=8配合pin_memory=True把数据加载和增强放在子进程并行,确保 GPU 利用率不掉。我实际测试时,离线缓存 + 多进程加载的组合,训练吞吐量提升了 3 倍以上。

5.5 生成式扩充样本没有经过人工筛选,模型学到“生成痕迹”

现象:用扩散模型扩充后的数据集训练,模型在小规模测试集上 mAP 有提升,但推到大场景时误检率特别高。

原因:生成样本中目标纹理带有扩散模型特有的“涂抹感”,模型学到了这种纹理特征而不是真实的边缘和结构特征。

解决:生成 + 人工抽检是必须的。每批次生成的图像,抽样 20% 人工过目,剔除明显不合理的样本。工业界一个更稳妥的实践是:生成数据只用于预训练阶段,最终在真实数据上有监督微调时,把生成数据比例降到 10% 以下,让最后的微调阶段“矫正”模型对生成痕迹的依赖。

6. 验证扩充效果:两个必须做的实验和一个长期习惯

很多人把数据扩充做完,训练完模型,看一眼 mAP 涨了 2 个点就结束了。但你可能只是把“测试集也做了增强”而导致的虚高,或者只是随机种子带来的波动。我现在的做法是:每次数据扩充方案落地后,固定跑两个实验,才有底气和别人说“这套扩充真的有用”。

第一个实验是加数据 vs. 不加数据的干净对比。同一个小骨干网络(比如 YOLOv8n),同一个随机种子,分别用原始数据、增强数据、增强 + 外部数据集训练,其他超参完全一致。注意 checkpoint 要保留中间权重,每 10 个 epoch 存一次,最后用验证集上最优的 checkpoint 做测试,而不是用最后一个 epoch 的权重。这样做的好处是能区分“数据扩充让模型的收敛上限变高”和“只是收敛速度变快了”这两种情况。

第二个实验是跨场景泛化测试。如果你的原始数据集只有一个场景(比如晴天白天),在扩充数据时有意留出另一个场景(比如傍晚和阴天)的少量真实数据不做训练,只做测试。这样的对比才真正反映扩充数据有没有提升模型的泛化边界,而不只是提升了“记忆训练集”的能力。

长期习惯方面,我会维护一份“数据扩充实验记录表”,每次扩充方案记三行:用了什么方法、改动什么参数、验证集 mAP 变化多少。这张表用久了你会发现一个规律:很多增强操作在小数据集上是正收益,在大数据集上是负收益。以 Mosaic 为例,在 300 张的车辆检测数据上有明显提升;当数据量堆到 5000 张以上,关掉 Mosaic 后 mAP 几乎不变,训练还更快。所以不要把一套增强配置从一个小任务复制到另一个大任务里,所有参数都要重新用实验验证。

我遇到过最惨的一次翻车,是用了全流程扩充(Mosaic + MixUp + CutOut + 生成数据),训练集扩展到 2 万张,结果模型在夜间场景检测性能反而下降了,原因是增强配置里“亮度抖动”的范围太大,让模型把大量夜间图像喂成了“偏白的假夜间”,相当于无意中抹掉了白天/夜间的分布差异。后来我在增强配置里把亮度抖动限制在 ±10%,并单独对夜间图像做了一组灰度扰动,才把问题解决。从那之后我养成了“每加一种增强,先做一次消融实验”的习惯,而不是把所有增强叠在一起一把梭。

希望今天的这些经验和踩坑记录能帮到你。数据扩充的方向比大多数人想得更宽:传统增强管住基础泛化,外部数据集负责跨场景迁移,生成式方法是最后的大招但必须有验证兜底。先把这三个层次想清楚,再动手写配置,你会发现“数据集太少”这个问题的解法其实非常具体,每一步都可以用数据说话。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询