ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

小样本玻璃脏污目标检测:数据集处理与YOLOv8训练避坑指南

小样本玻璃脏污目标检测:数据集处理与YOLOv8训练避坑指南 简介面向工业视觉检测与自动清洁系统该数据集提供玻璃表面脏污目标检测任务所需的完整标注数据适合算法工程师、研究人员及高校学生用于YOLO系列模型训练与算法验证。包体共1022个文件包含510张真实场景图片、510份YOLO格式标注文本以及类别配置文件与说明文档压缩包大小约29.64MB。数据按训练集452张、验证集58张划分单类别110GlassDirty边界框定位准确可直接适配主流深度学习框架。图片来自实际生产环境覆盖多种玻璃脏污形态有助于增强模型泛化能力中等规模设计便于快速完成训练迭代降低数据采集与标注成本。资源另附docx说明文档梳理标注规则与使用建议可支撑工业自动化清洁系统开发、智能环境监测及表面缺陷识别等应用场景的快速落地。目前已有240人学习下载适合需要实际工业样本进行目标检测实验与课题研究的读者。1. 110玻璃脏污目标检测数据集小样本缺陷检测的典型起点玻璃脏污检测在工业视觉里是个看着简单、做起来容易翻车的方向脏污对比度低、形态随机还经常混着反光一起出现。标题里这个「110玻璃脏污目标检测数据集.zip」一看就是那种「数量-类别-数据集」命名风格的压缩包110 大概率是图片张数或样本编号里面装的是玻璃表面脏污的图片和对应的目标框标注。这类小样本数据集恰恰是产线质检项目最常见的起点数据量不大、标注质量参差不齐但能不能用、怎么用决定了后续模型是能落地还是只在测试集上自嗨。这篇笔记就从解压开始把格式核对、标注转换、YOLO 训练、避坑和验证整个流程走一遍适合做视觉检测落地的工程师也适合刚接触目标检测数据集的同学照着跑通。2. 先拆包再谈训练110玻璃脏污数据集的标准解压与格式核对拿到任何 zip 格式的数据集我的习惯是先不急着解压而是把压缩包当成一个黑匣子做一次「入场检查」。这一步花不了两分钟但能省掉后面好几个小时的排错时间尤其是数据集来自同事拷贝、网盘中转或者课题交接时压缩包损坏、文件名乱码、伪加密这类问题出现的概率远比想象中高。2.1 解压前先看清单用 unzip -l 检查文件完整性与 zip 伪加密先看压缩包里到底有什么再决定怎么解压。Linux 或 macOS 下直接执行# 先查看压缩包内文件清单不实际解压 unzip -l 110玻璃脏污目标检测数据集.zip | head -50 # 查看总文件数和总大小 unzip -l 110玻璃脏污目标检测数据集.zip | tail -5 # 计算校验和和来源方提供的 md5 对比确认压缩包没在中途损坏 md5sum 110玻璃脏污目标检测数据集.zip如果unzip -l能正常列出文件说明压缩包结构完整。重点看两点一是目录层级是否清晰常见的数据集包内应该是images/和annotations/两个目录或者每张图对应一个同名标注文件二是文件名的编码。很多从 Windows 传出来的压缩包中文文件名到了 Linux 下会乱码直接解压会出现一堆_开头的乱码目录这时候要用-O参数指定编码# -O gbk 处理 Windows 中文文件名乱码-d 指定解压目录 unzip -O gbk 110玻璃脏污目标检测数据集.zip -d ./glass_dirty还有一个容易被忽略的问题zip 伪加密。有些压缩包在生成时被工具打上了加密标志位但文件内容实际上没有加密unzip 会误判为需要密码而拒绝解压。判断方法是用zipinfo或者 Python 的zipfile读取标志位import zipfile # 读压缩包内文件列表检查是否有伪加密标志 with zipfile.ZipFile(110玻璃脏污目标检测数据集.zip) as zf: for info in zf.infolist(): # flag_bits 0x1 为 1 表示标记了加密 print(info.filename, encrypted flag:, bool(info.flag_bits 0x1))如果显示 encrypted flag 为 True但文件本身实际没有加密内容直接用 Python 解压通常能绕过这个伪标志正常拿到文件。需要注意这里说的是处理自己拿到手的数据包如果文件确实被加密过就请找源作者要解压密码这不在技术讨论范围内。2.2 三种常见标注格式选 YOLO 还是 COCO取决于训练入口解压之后最要紧的事情是搞清楚标注格式。玻璃脏污数据集里最常见的标注格式是 VOC XML、COCO JSON 和 YOLO TXT 三种它们的组织方式和适用场景差很多我整理了一张对照表格式文件形态标注内容适用训练框架常用标注工具VOC XML每张图一个 xml左上角 xmin,ymin、右下角 xmax,ymax各类框架通用需转换后才可直接训练LabelImg、X-AnyLabelingCOCO JSON整个数据集一个 json用 segmentation 多边形或 bbox 矩形记录含图片信息和类别信息Detectron2、MMDetection 原生支持labelme、CVATYOLO TXT每张图一个 txtclass_id, x_center, y_center, width, height归一化YOLO 系框架直接训练LabelImg、Ultralytics 自带的标注工具做选择时我一般遵循一个原则如果最终想用 YOLO 系列快速验证效果就优先转成 YOLO TXT如果项目要复用 MMDetection 或者说要跑多种框架对比就保留 COCO JSON。不要迷信「哪个格式高级就转哪个」标注格式本身不产生精度只是训练的入口。110 张这种小数据集转换成本几乎可以忽略关键是格式一旦统一好后续扩数据时不会再折腾一遍。2.3 边界约定脏污是「框缺陷」还是「框污染区域」格式搞清楚后真正的技术活是核对标注边界。玻璃脏污检测的标注有一个很容易引发争议的约定目标框到底框的是脏污本体还是把脏污连同周边的污染区域一起框进去我见过不少数据集是拿「框污染区域」的方式标出来的尤其当标注者用的是语义分割工具时一个脏污点会连同周围的水渍晕染一起圈进去。这么做不是完全不能用但会给训练带来两个后果一是目标框面积虚大模型学到的特征是污染区域的渐变纹理而不是脏污本身的形状二是两个脏污点挨得近时框会粘连成一个大框检测结果看起来像「整个区域都脏了」。所以拿到数据集后务必做一次可视化检查把标注框画到原图上人眼过一遍。这一步能过滤掉百分之八十的标注质量问题import cv2 from glob import glob # 假设 YOLO 格式标注文件与图片同名 for img_path in glob(glass_dirty/images/*.jpg)[:20]: img cv2.imread(img_path) h, w img.shape[:2] txt_path img_path.replace(images, labels).replace(.jpg, .txt) if not os.path.exists(txt_path): continue with open(txt_path) as f: lines f.readlines() for line in lines: parts line.strip().split() if len(parts) 5: continue # YOLO 格式是归一化的中心点坐标和宽高 cx, cy, bw, bh map(float, parts[1:5]) x1 int((cx - bw / 2) * w) y1 int((cy - bh / 2) * h) x2 int((cx bw / 2) * w) y2 int((cy bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.imwrite(fcheck_{len(glob(check_*.png)) 1}.png, img)这段代码把 YOLO 格式的框画回原图输出的图片直接看一眼就能发现标注偏移、框选过大、类别错标等问题。检查的重点不是框得是否完美而是边界约定是否统一因为模型学的是标注里的规律标注乱训练结果一定乱。3. 把 110 张样本整理成可训练集格式转换与数据切分小数据集的整理比大数据集更需要精细因为 110 张样本里一旦混入十几张错标模型的精度损失是肉眼可见的。本章按我实际处理数据集的顺序来写先统计分布摸清家底再做格式转换最后做训练验证切分。3.1 用 Python 脚本统计标注分布判断脏污样本是否偏斜很多人在拿到数据集后直接开始训练结果训练到一半发现 loss 不降、验证集 mAP 为 0回头排查才发现标注文件里一堆空文件或者类别编号不连续。先跑一个统计脚本把家底摸清楚import os from glob import glob from collections import Counter # 统计图片总数、带标注图片数、标注框总数 img_paths glob(glass_dirty/images/*.jpg) glob(glass_dirty/images/*.png) label_paths glob(glass_dirty/labels/*.txt) labeled_imgs 0 total_boxes 0 class_counter Counter() box_area_list [] for img_path in img_paths: label_path img_path.replace(images, labels).replace(.jpg, .txt).replace(.png, .txt) if not os.path.exists(label_path): continue with open(label_path) as f: lines [ln.strip() for ln in f.readlines() if ln.strip()] if lines: labeled_imgs 1 for ln in lines: parts ln.split() if len(parts) 5: continue # 格式不完整的行直接跳过并计数 class_id int(parts[0]) class_counter[class_id] 1 # 计算归一化后的框面积用于判断目标尺度 bw, bh float(parts[3]), float(parts[4]) box_area_list.append(bw * bh) total_boxes 1 print(f图片总数: {len(img_paths)}) print(f有标注的图片数: {labeled_imgs}) print(f标注框总数: {total_boxes}) print(f类别分布: {class_counter}) print(f框面积最小值/中位数/最大值: {min(box_area_list):.5f} / {sorted(box_area_list)[len(box_area_list)//2]:.5f} / {max(box_area_list):.5f})这个脚本的输出会告诉你三件事。第一有没有图片被漏标如果 110 张图里只有 60 张带标注剩下 50 张是负样本还好如果是有物体但没框那就是漏标需要补标或剔除。第二类别是否只有一类玻璃脏污数据集通常只有一个类别但如果 class_counter 里出现多个 id要确认是不是把水渍、划痕、指纹分成了不同类这会影响后续 tuning 的类别数配置。第三框面积分布归一化框面积如果大量集中在 0.01 以下说明脏污目标很小训练时必须把 imgsz 调大或者考虑切图训练。3.2 VOC XML 转 YOLO 的转换脚本与参数说明确认标注格式是 VOC XML 后我一般会写一个转换脚本把它统一成 YOLO TXT。转换的核心逻辑很简单把 VOC 里的 xmin、ymin、xmax、ymax 像素坐标换算成 YOLO 需要的归一化中心坐标和宽高。这里的关键是必须读图片本身的宽高不能用 XML 里写的 width 字段就直接用因为有些标注工具的 XML 尺寸字段和实际图片不一致一旦不一致得到的归一化坐标全是错的。import xml.etree.ElementTree as ET import os def voc_to_yolo(xml_file, img_width, img_height, class_names): 将单个 VOC XML 转为 YOLO 格式的标注文本 Args: xml_file: VOC 标注文件路径 img_width: 对应图片的实际宽度像素 img_height: 对应图片的实际高度像素 class_names: 类别列表顺序决定类别 id tree ET.parse(xml_file) root tree.getroot() yolo_lines [] for obj in root.findall(object): name obj.find(name).text if name not in class_names: continue # 跳过未定义的杂散类别 class_id class_names.index(name) bndbox obj.find(bndbox) xmin float(bndbox.find(xmin).text) ymin float(bndbox.find(ymin).text) xmax float(bndbox.find(xmax).text) ymax float(bndbox.find(ymax).text) # 防止标注越界导致坐标超出 [0,1] xmin max(0, min(xmin, img_width - 1)) ymin max(0, min(ymin, img_height - 1)) xmax max(0, min(xmax, img_width - 1)) ymax max(0, min(ymax, img_height - 1)) # 转换为归一化中心坐标和宽高 box_w (xmax - xmin) / img_width box_h (ymax - ymin) / img_height cx (xmin xmax) / 2 / img_width cy (ymin ymax) / 2 / img_height yolo_lines.append(f{class_id} {cx:.6f} {cy:.6f} {box_w:.6f} {box_h:.6f}) return yolo_lines这个脚本里有两个细节值得注意。一是做了坐标越界裁剪因为实际标注中经常出现框超出图片边界的情况不裁剪的话归一化坐标会出现大于 1 的值YOLO 训练时虽然能跑但损失计算会异常。二是类别名称和 id 的对应关系class_names的列表顺序就是最终的类别 id 顺序比如[dirty]dirty 就是 0 类。训练配置里的names必须和这里保持一致否则会出现模型把第 0 类学成第 1 类之类的低级错误。3.3 按玻璃 ID 分组切分训练与验证集避免同源脏污泄漏切分训练集和验证集是小数据集最容易犯错的一环。直接随机切分看似公平但如果同一个玻璃样本拍了多张图片不同角度、不同光照下的图片被同时分进了训练集和验证集模型在验证集上的表现会被严重高估。因为验证集里出现了和训练图像特征高度相似的「近亲样本」模型记住了脏污的纹理特征换个真实场景立刻打回原形。正确的做法是按样本来源分组。如果文件名里有批次前缀比如batch1_01.jpg、batch1_02.jpg那就按 batch 前缀作为分组键做 GroupShuffleSplitimport os from glob import glob from sklearn.model_selection import GroupShuffleSplit img_paths sorted(glob(glass_dirty/images/*.jpg)) # 从文件名中提取样本组 ID这里假设前缀是 batch 序号 groups [] for p in img_paths: fname os.path.basename(p) group_id fname.split(_)[0] # 例如 batch1 groups.append(group_id) # 用分组切分保证同一组样本只出现在一个集合里 gss GroupShuffleSplit(n_splits1, test_size0.2, random_state42) train_idx, val_idx next(gss.split(img_paths, groupsgroups)) # 写 train.txt / val.txtYOLO 训练时可配合 txt 文件使用 with open(train.txt, w) as f: for i in train_idx: f.write(os.path.abspath(img_paths[i]) \n) with open(val.txt, w) as f: for i in val_idx: f.write(os.path.abspath(img_paths[i]) \n)这段代码的意义在于把「同源样本」隔离在训练集和验证集两侧。如果文件名里没有可用的前缀信息就需要人工看一眼图片内容做分组尤其是连续拍摄的序列帧宁可少分几张到验证集也不能让同源泄漏毁了评估结果。小数据集本身 mAP 波动就大如果评估基准再掺了水分后续做的所有模型对比都没有意义。4. 用 YOLOv8 训练自己的数据集小样本的模型选择与参数调整数据整理干净后接下来就是训练。现在这个时间点YOLOv8 和 YOLO11 是目标检测数据集落地最常用的框架尤其是 Ultralytics 生态对自建数据集的友好度很高数据格式对了一条命令就能开训。但小数据集不能直接照搬默认参数需要做几处关键调整。4.1 模型体积选哪档从 yolov8n 开始不要迷信大模型我先说结论110 张这类小数据集优先选 yolov8n最多试试 yolov8s不要一上来就跑 yolov8m 或 yolov8x。原因是这样的大模型的参数量大、拟合能力强但拟合能力在小数据上是双刃剑。模型能轻松记住训练集里那几十个脏污样本的纹理和位置却没有足够的多样性来约束它泛化。训练 100 个 epoch 后大模型的训练 loss 会降到很低验证 loss 反而往上走典型的过拟合曲线。而 yolov8n 因为参数量小、表达空间有限反而被迫去学脏污的共性特征在验证集上表现更稳。# 从 n 尺寸开始训练先建立 baseline yolo detect train \ dataglass.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch8 \ device0 \ patience20modelyolov8n.pt会用 COCO 预训练权重作为起点这对小数据集帮助很大。预训练模型已经学会了基础的特征提取能力比如纹理、边缘、局部对比度这些特征对脏污检测同样适用。千万不要从零训练110 张图从零训练出来的特征提取器基本什么都学不到。4.2 训练参数设置epochs、imgsz、batch 与学习率的关系小数据集调参核心矛盾在于「epoch 少了学不透epoch 多了必然过拟合」。我常用的参数组合如下参数小样本推荐值默认值调整理由epochs100-150100小数据集需要更多轮次让模型逐步收敛但超过 150 轮容易过拟合imgsz640 或 800640脏污多为小目标imgsz 调大可保留更多局部细节batch8-1616显存允许时尽量大batch 太小会放大 BN 层统计噪声patience20-30100小数据集验证集波动大早停耐心值要适当放宽lr00.001-0.0050.01预训练权重微调时学习率调小有助于保留已有特征这里重点解释patience。默认的 patience100 意思是验证集指标连续 100 个 epoch 不提升才停止小数据集上验证集指标波动剧烈有可能出现第 20 轮出现峰值、后面 30 轮都不再突破的情况这时候继续训练只会加剧过拟合。我一般设成 20-30让训练早点收敛到实际最优。但前提是验证集本身可靠如果切分时有同源泄漏patience 再小也救不了评估结果。imgsz的调整要和目标框面积配合。前面统计时如果发现大量框面积占比低于 0.02也就是脏污只占整张图的很小一块imgsz 尽量提到 800。显存不够时相比降低 imgsz我优先考虑切成小块训练让模型看到的是放大后的脏污局部而不是整块玻璃的小尺寸缩略图。4.3 数据增强对脏污检测的副作用亮度扰动比旋转更合适Ultralytics 训练默认开启的增强策略是为 COCO 这种大样本通用场景设计的直接用在 110 张小数据集上很容易把模型「增强」晕。原因是玻璃脏污有很强的方向性和光照敏感性水流痕迹是竖条状指纹是弧线状镜面反光和脏污在灰度分布上高度重叠。我在小数据集上会主动关掉一部分几何增强同时调大光度增强# 关闭旋转和水平翻转保留亮度、色调、缩放等光度增强 yolo detect train \ dataglass.yaml \ modelyolov8n.pt \ epochs120 \ imgsz640 \ batch8 \ patience25 \ degrees0 \ flipud0.0 \ fliplr0.0 \ hsv_h0.02 \ hsv_s0.6 \ hsv_v0.6 \ scale0.3参数解释degrees0关闭旋转因为玻璃表面的水流痕旋转 90 度后语义就完全变了flipud0.0关闭上下翻转产线相机安装角度通常固定翻转会让模型学到不存在的样本分布hsv_v0.6调大亮度扰动模拟现场不同时间段光照变化这是脏污检测增强里最有效的一招。scale0.3保留尺度扰动因为脏污大小本来就没有固定尺度。不要盲目叠加增强小数据集的增强原则是「模拟真实场景中正常会出现的变量而不是人为制造不存在的样本」。这些参数具体怎么调要看训练时的 loss 曲线训练 loss 震荡剧烈说明增强力度过大训练 loss 和验证 loss 同步下降且验证 loss 没有明显回弹说明当前参数合适。5. 玻璃脏污检测避坑记录5 条让模型在产线上翻车的细节这部分是血泪经验。前面几章讲的是怎么做对这一章讲的是我踩过的坑每一条都按「现象 → 原因 → 解决」来写。目标检测数据集训练这个环节踩坑的代价不是浪费时间而是让你误以为模型不行其实问题根本不在模型身上。5.1 模型把玻璃反光当成脏污误报满天飞现象训练完的模型在测试图上一口气框出几十个目标大部分落在玻璃边缘和光源反射区域。确认后发现训练集里标注员把玻璃边缘的反光也标成了脏污正样本里混入了大量假正例。原因反光和脏污在灰度特征上非常接近尤其是带水渍的脏污和镜面反射一样都有高亮区域。标注阶段没有做严格区分模型学到的特征里「高亮区域 脏污」。解决把标注数据里所有反光框筛选出来人工判断后删除或重新标注。同时调整数据增强里的hsv_v参数增加亮度扰动让模型对灰度绝对值不那么敏感。如果反光和脏污在采集图像里实在难以区分建议上偏振相机或在现场加偏振片物理上滤除反光后再检测。5.2 训练 loss 不下降指标一直趴在零附近现象训练 50 个 epochloss 几乎不变验证集 mAP 一直是 0。原因最常见的是标注文件为空或者标注框归一化坐标大于 1。比如 VOC 转 YOLO 时没有读实际图片宽高而是拿了 XML 里的 width 字段一旦 XML 尺寸和图片不一致中心点坐标和宽高就可能超出合法范围。YOLO 训练遇到非法坐标会直接跳过该样本等于 110 张图全部作废。解决训练前先跑一遍 3.1 节的统计脚本确认标注框数量不为零、坐标都在 0 到 1 之间。然后在 3.2 节的转换脚本里打印异常样本路径把坐标越界的样本单独拎出来看。这个坑排查只需要五分钟但足够让人怀疑人生。5.3 验证集 mAP 很高现场换一个角度就漏检现象验证集上 mAP50 达到 0.9部署到现场后漏检率夸张换个光照方向就检测不到脏污。原因训练集拍摄场景单一所有图片来自同一个工位、同一角度、同一光源。模型学到的不是「脏污」本身而是「这个角度、这个光源下的脏污」验证集又和训练集同源因此指标虚高。这是小数据集最常见的问题数据采集阶段就埋下的。解决采集阶段尽可能覆盖不同角度、不同光照、不同玻璃批次。如果数据集已经定了只能在训练时加入更强的光度增强另外在部署现场收集一批真实场景图人工标注后做二次微调。这也是我反复强调验证集要和训练集「不同源」的原因评估结果才有参考价值。5.4 zip 解压后图片打开报错cv2.imread 返回 None现象解压后图片文件都在但训练脚本读取时 cv2.imread 返回 None部分图片显示文件头损坏。原因第一可能是压缩包传输不完整文件虽然解压出来了但尾部数据缺失第二是图片扩展名和实际编码不一致比如明明是 PNG 格式却命名为 .jpg第三是 Windows 下用默认资源管理器解压带中文长路径的文件时路径过长导致部分文件写入失败。解决用file命令检查图片真实格式不要信任扩展名# 检查可疑图片的真实编码格式 file glass_dirty/images/*.jpg | head -20 # 用 Python 批量验证图片能否正常解码 python -c import cv2, glob for p in glob.glob(glass_dirty/images/*.jpg): img cv2.imread(p) if img is None: print(bad:, p) 压缩包完整性靠 2.1 节的 md5sum 校验解决路径过长的问题在解压时尽量用短目录名比如解压到./gd/而不是./glass_dirty_dataset_2024_版本2/。5.5 微调训练时猛然崩掉所有预测结果全为空现象训练结束后用 best.pt 跑推理一张目标都检测不出来输出为空。原因大概率是类别映射错位。比如标注文件里的类别 id 是 1而训练配置 names 只有 0 一个类别模型训练时把所有标注都当成忽略样本学了个寂寞。另一种情况是数据集中其实存在两类目标但 names 只写了一个类别第二个类别对应的标注在训练中被忽略。解决检查glass.yaml里的 names 是否覆盖了所有标注类别 id以及和转换脚本里的class_names是否一致。最直接的办法是把 best.pt 在训练集上跑一遍如果训练集都检测不出来基本就是标签和配置不匹配的问题而不是模型收敛问题。6. 验证一套「能上线」的脏污检测模型PR 曲线与置信度选择训练完模型不能只看 mAP 就结束。小数据集上 mAP 波动大同一个模型在不同置信度阈值下的表现差异巨大。我习惯先把验证指标跑出来然后专门做一步置信度阈值选择这步决定了模型到产线上是好用还是添乱。6.1 用 mAP50-95 看趋势用 PR 曲线定置信度阈值# 对训练好的最优权重做验证集评估 yolo val \ modelruns/detect/train/weights/best.pt \ dataglass.yaml \ imgsz640 \ conf0.25 \ iou0.5验证完成后Ultralytics 会在runs/detect/val/下生成PR_curve.png和confusion_matrix.png。PR 曲线图上有一个很直观的规律脏污检测这类低对比度目标曲线在 recall 接近 1 前会有一段明显下坠说明有几个难样本必须把置信度压得很低才能召回。这时候我要做一个取舍产线场景误报成本高的话把置信度阈值设在 precision 开始陡降之前比如 0.35 到 0.5 之间如果漏检成本更高比如脏污会直接导致产品报废就牺牲一些 precision 把阈值降到 0.2 左右。6.2 把训练好的权重接进实时检测脚本验证漏检和误报验证完阈值最后一步是拿现场图片或视频流实测。我习惯写一个最简单的推理脚本把相机采到的图片一帧帧喂进去from ultralytics import YOLO # 加载训练好的最佳权重 model YOLO(runs/detect/train/weights/best.pt) # 对单张图片推理conf 取 PR 曲线上选定的阈值 results model.predict( sourcefield_test_01.jpg, conf0.4, imgsz640, saveTrue, ) # 打印检测到的目标数量和位置 for r in results: boxes r.boxes print(f检测到 {len(boxes)} 个目标) for box in boxes: cls int(box.cls[0]) conf float(box.conf[0]) xyxy box.xyxy[0].tolist() print(f类别 {cls}, 置信度 {conf:.2f}, 位置 {xyxy})做这一步时我会故意混入一些训练集里没有的现场样本比如不同角度的指纹、不同批次的玻璃膜层甚至误检概率最高的镜面反光样本。如果一个模型在 PR 曲线上表现很好但在现场样本上一看就露馅那基本可以断定是数据采集和训练分布差异太大光调阈值救不回来。我在玻璃脏污检测这类小数据集项目上的习惯是不管算法多复杂先把数据流程固定住解压、校验、统计、转换、切分、训练、验证这七步每一步都留日志。这些日志在调试时就是后悔药哪个环节出了问题回去翻一下就能定位不用重新猜。希望这份流程对你处理手里的数据集有实际帮助。本文还有配套的精品资源点击获取
返回列表