钢材表面缺陷数据集YOLOv8训练实战:从数据清洗到模型调参
简介这是一份面向计算机视觉与目标检测学习者的钢材表面缺陷已标注数据集包含1800张真实工业图像与对应标注文件覆盖crazing、inclusion、patches、pitted_surface、rolled-in_scale、scratches六类典型缺陷可直接用于YOLO等模型的训练与验证。资源包共3608个文件以jpg图像和txt标注为主体另含YOLO训练所需的py脚本与yaml配置文件压缩包仅25.95MB结构清晰、即下即用适合高校学生课程设计、期末大作业及毕业设计场景。目前已有1592人学习下载数据集标注格式统一配合参数化编程思路与注释明细能帮助初学者快速上手目标检测全流程也方便研究者复现实验或进行算法调优。1. 已标注的钢材缺陷数据集不等于可以直接训练的 YOLO 数据拿手机里这份“钢材表面缺陷数据集”举例解压后是1800张图像每张图对应一个已标注文件压缩包名字还特意写明“可以直接使用”。大多数人拿到它的第一反应是丢给YOLO训练脚本然后发现所谓的可直接使用只是把标注这件事做完了。后续的目录体检、标注格式对齐、类别映射核对、训练集验证集划分还缺一整套工序。这篇笔记要做的就是把“zip包已标注”到“模型能收敛出可用mAP”之间那段隐形路径摊开先读目录、查标注、再训练最后针对钢材缺陷这种小目标、类别不平衡场景的故障点做规避。适合手里正好握着同类数据集的初学者也适合准备用工业缺陷图像做毕业设计或横向项目的人照着复现。2. 解压与目录体检把 1800 张图里的标注文件读明白2.1 解压先解命名中文文件名的坑与纯英文目录改造钢材表面缺陷数据集这类包通常是从产线或者公开渠道收集后打包分发的压缩包内目录经常带着中文名或者直接以“train_data最终版”这类命名散落几十个文件。如果只在Windows下用右键解压问题不会立刻暴露一旦把目录传到Linux服务器上训练用unzip解出来全是乱码YOLO按名字找标注文件时会直接找不到对应关系。我一般建议用7-Zip或者命令行7z解压对中文编码的兼容性比unzip好很多。解压之后也别急着写训练脚本先把目录名和文件名全部改成英文字母。在那之前先用一条命令把jpg和txt的配对情况摸清楚mkdir -p steel_defect cd steel_defect # 用 7z 解压中文文件名乱码概率比 unzip 低 7z x ../钢材表面缺陷数据集已标注可以直接使用1800张图像对应已标注文件.zip # 看顶层目录结构 find . -maxdepth 2 -type d | head -20 # 统计图片数和标注文件数 find . -name *.jpg | wc -l find . -name *.txt | wc -l如果wc -l统计出来两边数字明显不等比如1800张图只有1700个txt先别怀疑数据集被截断优先检查是不是有些文件名带空格、全角括号导致find的匹配落空或者确实有几个空标注文件被跳过。此时把find换成find . -name *.txt -size 0把零字节的空文件单独列出来这往往是标注工具在保存时生成的坏文件。提示拿到任何zip数据集第一件事是核对“图片数:标注数”比例不是1:1时后面训练出的指标没有任何参考价值。在正式解压前我还习惯用Python的zipfile看一眼压缩包内部结构# inspect_zip.py # 列出 zip 内容判断是否所有文件都在同一个根目录下 import zipfile z zipfile.ZipFile(钢材表面缺陷数据集已标注可以直接使用1800张图像对应已标注文件.zip) for name in z.namelist()[:30]: print(name)这一步能看出两个信息包内有没有单一根目录决定了解压后要不要多套一层路径包内图片与标注是否分散在多个子目录如果结构很乱解压后第一件事就是统一收拢成images/和labels/两个平铺目录。很多zip包下载下来以后文件是散在十几个文件夹里的不先做目录归一化后面写data.yaml时会非常痛苦。2.2 目录组织方式YOLO txt 还是 VOC xml决定你要不要多写一步转换这类“已标注”钢材数据集的标签文件常见落盘格式有两种。一种是YOLO格式的.txt每行一条缺陷框直接能被ultralytics读取另一种是Pascal VOC的.xml框坐标是像素值得先转成YOLO归一化格式再进训练。区分方法很简单在标签目录下执行ls看后缀再随便cat一个文件看内容。ls labels | head -5 cat labels/00001.txt如果看到的是annotation开头的一堆尖括号说明还停留在XML阶段需要转换。常见做法是写一个Python脚本把bndbox里的xmin、ymin、xmax、ymax读出来除以图片宽高得到归一化值再按类别名映射成数字id# voc2yolo.py # 将 Pascal VOC xml 标注转换为 YOLO txt 归一化格式 import xml.etree.ElementTree as ET from pathlib import Path xml_dir Path(annotations) txt_dir Path(labels) txt_dir.mkdir(exist_okTrue) class_map {crazing: 0, inclusion: 1, patches: 2, pitted_surface: 3, rolled-in_scale: 4, scratches: 5} for xml_path in xml_dir.glob(*.xml): tree ET.parse(xml_path) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) lines [] for obj in root.findall(object): name obj.find(name).text if name not in class_map: print(f未知类别 {name} 在 {xml_path.name}跳过) continue bnd obj.find(bndbox) xmin float(bnd.find(xmin).text) ymin float(bnd.find(ymin).text) xmax float(bnd.find(xmax).text) ymax float(bnd.find(ymax).text) cx (xmin xmax) / 2 / img_w cy (ymin ymax) / 2 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{class_map[name]} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) (txt_dir / f{xml_path.stem}.txt).write_text( \n.join(lines), encodingutf-8) print(f共转换 {len(list(xml_dir.glob(*.xml)))} 个 xml 文件)脚本里class_map的键名必须和xml里name的文本完全一致一个空格都不能差。钢材缺陷数据集的类别名在不同版本里可能有差异写脚本前先全局搜一遍xml里出现过的所有name值再补映射表别拍脑袋写六个。转换完成后用图片数量对一遍txt数量确认100%配对再继续。如果标签已经是0 0.321 0.544 0.110 0.070这种纯数字行说明标注已经是YOLO格式可以直接进入第3章做质量校验。此时还要看目录有没有把train和val分开。很多压缩包给的是直出式结构images/和labels/各一个目录全部1800张图不分验证集也有少数包已经把train、val铺好了。两者的后续处理差别很大已经分好的可以直接写data.yaml没分好的就得自己按第4章的办法做一次划分。不要迷信zip名称里的“带标注”先列出真实结构再说。2.3 坐标换算与类别映射读懂一行 label后面才不会被数据“背刺”随便打开一个YOLO标注文件典型的一行是0 0.321 0.544 0.110 0.070五个数字依次是类别id、框中心x坐标、框中心y坐标、框宽、框高。后四个值全部是相对图片宽高的归一化比例范围在0到1之间。也就是说如果原图是640×480像素这一行标注对应的实际像素框为中心点在(0.321×640, 0.544×480)框宽0.110×640框高0.070×480。钢材表面缺陷分布密集且面积小这个框在像素层面往往只有几十像素宽训练时选输入分辨率就要格外留意640×640输入下可能直接把小缺陷缩没了。类别id本身没有语义它代表第几类由训练配置里的names列表决定。公开的钢材表面缺陷集通常命名六类crazing裂纹、inclusion夹杂、patches斑块、pitted_surface麻点、rolled-in_scale氧化铁皮、scratches划痕。但具体到你手里的包类别映射可能不同而且不少压缩包里不会主动附一份classes.txt。此时用Python把数据集里出现过的所有标签id连同数量打出来比对标注文件里的最大id再反推names定义这是我把“训练前必做清单”里的固定一项。还有个小细节如果标注文件里出现的是x_min y_min w h这种组织方式说明它并不是标准YOLO中心点格式坐标原点、是否归一化都要重新确认直接喂给训练脚本会得到一堆离谱的预测框。3. 标注质量校验用脚本找出训练前必须处理的脏数据3.1 先核对配对关系再检查格式图片名与标签名必须完全一致“已标注”三个字只说明标注动作完成了不说明标注质量过关。钢材表面缺陷图像里有些框把整块钢面连背景一起框住有些坐标写到了1.2这种越界值有些txt文件里是一行空数据。这些问题不清理训练时要么loss曲线乱跳要么mAP永远卡在零。第一步先做文件级配对把缺标注、多余标注全部扫出来# check_missing.py # 检查 images 与 labels 的文件茎是否一一对应 from pathlib import Path images_dir Path(images) labels_dir Path(labels) image_stems {p.stem for p in images_dir.glob(*.jpg)} label_stems {p.stem for p in labels_dir.glob(*.txt)} missing image_stems - label_stems extra label_stems - image_stems print(f图片数: {len(image_stems)}, 标注数: {len(label_stems)}) print(f缺标注的图片: {len(missing)}) for name in sorted(missing)[:20]: print( , name) print(f缺图片的标注: {len(extra)}) for name in sorted(extra)[:20]: print( , name)这里用p.stem取文件名主干天然避开了.jpg与.JPG大小写不一致的问题。如果输出里missing不为空就要看是不是文件名中混入了空格或全角符号。钢材缺陷数据集里常见的命名形式是00001.jpg配00001.txt一旦某个文件名是00001 (1).jpg配对就断了。不要试图在训练脚本里做模糊匹配直接把文件名统一改成img_00001.jpg这种规范格式成本最低。3.2 格式合规检查坐标越界、字段缺失、空标签一网打尽配对完成后逐个打开txt检查内容。我在拿到标注后第二件事是跑一段格式体检脚本把三个核心问题一次性查出来字段数不是5、坐标范围超出[0,1]、宽或高为负。# check_labels.py # 检查 labels 目录下的所有 YOLO 标注文件是否格式合规 from pathlib import Path labels_dir Path(labels) bad_files [] for txt in labels_dir.glob(*.txt): for i, line in enumerate(txt.read_text(encodingutf-8).strip().splitlines()): if not line.strip(): continue parts line.split() if len(parts) ! 5: bad_files.append((txt.name, i 1, f字段数{len(parts)})) continue cid, x, y, w, h map(float, parts) if not (0 x 1 and 0 y 1 and 0 w 1 and 0 h 1): bad_files.append((txt.name, i 1, f坐标越界 {parts})) if w 0 or h 0: bad_files.append((txt.name, i 1, 宽高为负)) print(f共检查 {len(list(labels_dir.glob(*.txt)))} 个文件) for item in bad_files[:50]: print(item) print(f异常文件数: {len(bad_files)})这段代码用line.split()把每行拆成五段前两个判断覆盖了绝大多数脏数据场景。注意w和h严格大于0因为一个缺陷框宽度为0在数学上没有意义多数是标注工具误操作留下的坏框训练时会让模型学到一条不存在的线段。跑完后如果异常文件数超过全部文件的5%我一般不会继续训练而是先把有明显问题的标注手工剔除或重新标注。3.3 类别分布统计别让六个类别里有一类“隐身”钢材缺陷数据集的类别均衡性通常很差这也是工业质检数据的老毛病。形态相近的类别会互相抢占样本而某类严重缺陷因为出现频率低标注文件里可能总共只有几十个框。最终训练结果很容易出现某一类mAP高达0.9、另一类却完全没被模型“看见”的情况。跑一遍类别统计脚本把每个类的框数量拉出来# class_dist.py # 统计每个标注类别的框数量并输出占比 from collections import Counter from pathlib import Path labels_dir Path(labels) dist Counter() total_boxes 0 for txt in labels_dir.glob(*.txt): for line in txt.read_text(encodingutf-8).strip().splitlines(): if line.strip(): cid int(line.split()[0]) dist[cid] 1 total_boxes 1 print(f总标注框数: {total_boxes}) for cid in sorted(dist): print(f类别 {cid}: {dist[cid]} 框, 占比 {dist[cid] / total_boxes:.2%})统计结果出来后占比低于10%的类就要优先处理。常见做法是先把少数类单独复制一份加入训练集或者关闭mosaic增强避免小目标被切碎数量实在不够时再考虑合成缺陷样本。至少你要知道瓶颈在哪而不是等训练完看混淆矩阵才后知后觉。另外要注意钢材缺陷类别里有的类视觉上高度相似比如rolled-in_scale和patches如果标注人员自己都分不清统计分布会掩盖“误标”的问题所以下一步必须做可视化抽查。3.4 可视化标注框脚本查不出的误标人眼抽查一遍就能发现格式检查和类别统计只能过滤“机器能判断的错”而“框偏大、框漏了一个缺陷、类别贴错标签”这类语义错误必须靠人眼看。这个步骤看似最原始却是整个流程里性价比最高的一步。我会从每个类里随机抽20张图把标注框直接画上去生成到check_vis/目录过目一遍。# visualize_boxes.py # 随机抽取图片把 YOLO 标注框画出来供人工检查 import random from pathlib import Path from PIL import Image, ImageDraw images_dir Path(images) labels_dir Path(labels) out_dir Path(check_vis) out_dir.mkdir(exist_okTrue) class_names [crazing, inclusion, patches, pitted_surface, rolled-in_scale, scratches] image_files list(images_dir.glob(*.jpg)) random.seed(42) sampled random.sample(image_files, min(60, len(image_files))) for img_path in sampled: label_path labels_dir / (img_path.stem .txt) if not label_path.exists(): continue img Image.open(img_path).convert(RGB) draw ImageDraw.Draw(img) w, h img.size for line in label_path.read_text(encodingutf-8).strip().splitlines(): cid, cx, cy, bw, bh map(float, line.split()) x1 (cx - bw / 2) * w y1 (cy - bh / 2) * h x2 (cx bw / 2) * w y2 (cy bh / 2) * h draw.rectangle([x1, y1, x2, y2], outlinered, width2) draw.text((x1, y1 - 8), class_names[int(cid)], fillred) img.save(out_dir / img_path.name) print(f已生成 {len(sampled)} 张可视化图到 {out_dir})抽查时重点看三种情况框是否把整块钢面全包住这说明标注人员用“大框套小框”图省事同一处缺陷被画了两个重叠框这会干扰NMS以及某个类别明显标反。还要注意坐标原点约定有的标注工具原点在左上角有的是中心点如果整体偏移了半个框看可视化图会非常明显。钢材缺陷形态相似度高人工抽查能提前纠正一批错标比训练完再返工省时得多。这一遍看下来你对整个数据集的可信度基本就有数了。4. 用 YOLOv8 训练自己的钢材数据集环境、划分与首次调参4.1 环境准备一张N卡、一个conda环境和预训练权重到了训练这一步我默认你已经有一台带NVIDIA GPU的机器V100、3090、4090都可以显存8GB以上就够跑yolov8n。CPU训练1800张图也不是不行但迭代速度和GPU差一个数量级调试一次要等几个小时体验很差。环境安装不需要太多花活conda create -n yolo python3.10 -y conda activate yolo pip install ultralyticsultralytics这个包会把yolo命令行工具一起装好训练、验证、预测、导出都通过它完成。首次训练时它会尝试自动下载yolov8n.pt预训练权重如果机器无法联网下载权重就提前在别处下载好权重文件放到项目目录再在命令里指定modelyolov8n.pt它会自动识别本地文件。预训练权重对钢材缺陷这种小样本场景帮助很大因为COCO预训练已经把通用纹理、边缘特征学过了迁移后只需少量epoch就能拟合缺陷形态。4.2 数据划分与 data.yaml同一根带钢的相邻帧不许进两个集合1800张图如果只有一个images/目录训练前必须自己划分。这一步最容易犯的错误是随机划分时不考虑数据来源关系。钢材生产线上连续采集的图像相邻帧之间背景高度相似、甚至缺陷就是同一个如果相邻的几帧分别进了train和val验证集就失去了独立性mAP虚高到现场一换光源马上露馅。我的划分脚本固定用seed并支持按“图像前缀”分组。如果文件名是steel_001_01.jpg、steel_001_02.jpg这种连续帧就按前缀分桶而不是一张一张随机分。下面给一个最基础的无前缀随机划分版本1800张规模够用# split_dataset.py # 对 images 和 labels 做一致划分复制不移动保留原始备份 import random import shutil from pathlib import Path src_img Path(images) src_lbl Path(labels) train_img Path(images/train) val_img Path(images/val) train_lbl Path(labels/train) val_lbl Path(labels/val) for d in [train_img, val_img, train_lbl, val_lbl]: d.mkdir(parentsTrue, exist_okTrue) file_stems [p.stem for p in src_img.glob(*.jpg)] random.seed(42) random.shuffle(file_stems) val_count int(len(file_stems) * 0.2) val_stems set(file_stems[:val_count]) for stem in file_stems: target_img val_img if stem in val_stems else train_img shutil.copy2(src_img / f{stem}.jpg, target_img / f{stem}.jpg) lbl_file src_lbl / f{stem}.txt if lbl_file.exists(): target_lbl val_lbl if stem in val_stems else train_lbl shutil.copy2(lbl_file, target_lbl / f{stem}.txt) print(ftrain: {len(file_stems) - val_count}, val: {val_count})用copy2而不是move是故意留的后悔药原始目录保留一份划分错了也能重新来。val占比按20%来1800张图会分出约360张验证足够评估如果某类缺陷样本太少验证集里那一类可能只有几个框此时建议改为按类别数量分层抽样。如果文件名带着产线批次前缀先按前缀去重成组再整组划分这一步不能省。目录定好后把data.yaml写到项目根目录# data.yaml path: /home/your_name/steel_defect train: images/train val: images/val names: 0: crazing 1: inclusion 2: patches 3: pitted_surface 4: rolled-in_scale 5: scratches这里path必须是绝对路径train和val是相对path的目录names数量要和标注文件里的id一一对应顺序错了模型就会拿着“裂纹”的标签去学“划痕”的像素训练过程能跑完但结果全错。类别名本身不影响训练效果影响的是后续分析时你认不认得出来。4.3 训练命令与四个要调的参数环境、数据、配置三件事都落地后训练本身只需要一条命令yolo detect train \ datadata.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ device0 \ projectsteel_runs关键的几个参数我习惯做成一张表贴在项目里每次换数据集都先看一眼参数建议值说明epochs100迁移学习场景的起步值配合早停观察曲线imgsz640钢材小缺陷建议试960或1280显存加倍batch1612GB显存跑yolov8n的常见值24GB可上32lr00.01数据噪声大时降到0.001freeze0微调新产线数据时设10冻结backbone底层imgsz是钢材缺陷任务里最重要的参数。缺陷框平均高度不到原图十分之一用默认640输入时小缺陷只占十几个像素建议至少试一版960或1280batch直接由显存决定12GB显存下yolov8n用16比较安全24GB可以上32V100的32GB版可以尝试batch48但注意batch变大后学习率也要跟着调整epochs对迁移学习场景我一般从100起步数据量只有1800张跑完看曲线再决定要不要加。训练启动后日志里最值得盯的是train/box_loss和val/box_loss两条曲线。box_loss持续下降说明模型在学习框定位val_loss如果先降后升说明过拟合常见做法是提前停在一个较早的epoch上。第一次训练建议把所有结果先看一轮不要中途频繁改参数重开因为你还没建立“当前数据集的loss正常区间”这层认知。跑完后在steel_runs/detect/train*/下会得到weights/best.pt和weights/last.pt后续验证和推理都用best.pt。提示epoch数不是越大越好钢材缺陷场景跑过拟合后val曲线会在某轮后开始抬升此时best.pt依然停留在最优轮次直接拿来用即可。5. 钢材缺陷训练常见问题排查五个翻车点的现象、原因、解决先给这五个问题排个优先级前两个是数据层面的问题不解决就别谈训练中间两个是训练过程与评估策略问题最后一个是压缩包本身的问题。遇到任何异常按这个顺序逐个排查大部分情况下能在一个session里定位。5.1 中文文件名乱码导致图片和标注对不上现象数据集在Windows右键解压后一切正常传到Linux服务器上图片和标注文件明明都在训练日志却疯狂提示找不到对应的标注文件用ls看目录全是乱码字符。原因zip打包者在Windows下用GBK中文命名了文件和目录压缩包本身不记录编码Linux的unzip按UTF-8解压时就解析成了乱码。标注文件与图片文件名对不上自然匹配失败。解决解压时优先用7z或者用python -c import zipfile; zipfile.ZipFile(xxx.zip).extractall()后者会按zip内部记录的编码尽量还原解压完成后立刻统一替换成纯英文文件名避免后续所有环节踩同一个坑。改名脚本里用Path.rename()把中文stem映射成img_0001这类编号即可。5.2 训练日志里val set显示“0 labels”mAP永远为0现象训练流程正常、loss也在下降但每次验证阶段打印出来的目标数量是0最终mAP0.5始终为0。原因绝大多数情况是标签目录和图片目录不配套比如data.yaml里指向images/val但标签在labels/根目录下没有按train/val分层还有可能是图片使用.jpg、标注文件恰好叫.JPG大小写不一致导致匹配不上。解决直接把labels目录也按图片划分建立同样的train/val子目录或者更省事的是用软链接让labels/val真实存在。排查时执行find images/val -name *.jpg | wc -l和find labels/val -name *.txt | wc -l两个数字相等再继续不相等就回到第3章的配对脚本查原因。5.3 训练到一半 loss 不降反升模型越学越差现象train_loss前10个epoch一路下降到第20个epoch突然反弹到比第5轮还高val_loss同步恶化最终mAP惨不忍睹。原因先怀疑标签有错尤其是一张图里标注框把整幅钢面的大半都圈进去的“灵异框”这种样本每个epoch都会给一个巨大且错误的梯度其次怀疑类别id与names顺序不一致导致模型学到了错误的映射。解决回头跑第3章的标注可视化把loss反弹最剧烈那几张图的标注框调出来看。框明显异常的样本先删除或剪裁修正再重新训练。如果确认标签无误则检查学习率初始值是否过大lr0从默认0.01下调到0.001再试一轮。钢材缺陷数据里误标一个框比多十个正常框的破坏力都大。5.4 精度高召回低现场漏检严重现象验证集mAP0.5超过0.8看起来挺好实际把测试图像喂进去大批小缺陷漏报现场漏检率完全不可接受。原因钢材缺陷场景里小目标占比高而mAP是精确率与召回率的复合指标一个模型可能通过只预测最有把握的大缺陷框也能刷出不错的精度但召回率很低。验证时conf默认取0.25小缺陷框置信度普遍低于大缺陷直接被过滤掉了。解决推理时把conf阈值拉低到0.1到0.15观察召回变化训练时把imgsz从640提到960或1280小缺陷能获得更多像素信号如果显存有余量换yolov8m或yolov8l。单纯精度高不能证明模型能上线一定要单独看recall曲线。5.5 zip伪加密或解压报错数据差点作废现象解压时提示需要密码但这个数据集本不该加密或者解压到一半报CRC校验错误文件不完整。原因前者是zip文件头中某个加密标志位被错误置位也就是伪加密并不代表文件内容真的被加密后者多半是传输过程丢包或者压缩包被二次编辑过文件目录信息与实体内容不一致。解决伪加密用7z解压通常能直接绕过因为7z按数据流解析而非死读标志位报CRC错误时先把已经解压出来的部分做一次标注文件完整度检查图片缺失不多的可以直接拿现有子集训练缺得多再找原始发布渠道重新获取。用Python的zipfile打开如果抛RuntimeError: File is encrypted可以手动检查flag_bits 0x1判断是否伪加密确认是伪加密后强行读取数据区即可。这个坑一旦撞上最容易让人误以为整个数据集废了实际只是压缩包文件头的问题。6. 混淆矩阵、批量验证与冻结微调训练收尾后仍值得做的三件事训练结束不是终点模型能不能用要看验证集之外的表现。先打开steel_runs/detect/train*/confusion_matrix.png重点看对角线以外的格子。钢材的rolled-in_scale和patches在视觉上很像混淆矩阵里这两类互相渗透是常态如果某个非对角格特别亮说明该类别需要更多样本或更细致的标注区分度而不是靠调参能解决。接着做一次批量推理把验证集全部图跑一遍输出带框的预测图看模型给出的置信度分布# batch_predict.py # 用训练好的 best.pt 对验证集做批量推理并保存可视化结果 from pathlib import Path from ultralytics import YOLO model YOLO(steel_runs/detect/train/weights/best.pt) img_dir Path(images/val) out_dir Path(pred_vis) out_dir.mkdir(exist_okTrue) for img_path in sorted(img_dir.glob(*.jpg))[:100]: results model.predict(img_path, conf0.15, imgsz640) for r in results: r.save(out_dir / fpred_{img_path.name})conf0.15比默认阈值低不少目的就是看那些“模型其实检测到了但不敢报”的框。如果这批低置信度预测里有大量真实缺陷那么当前阈值设0.25太高了如果全是乱框说明模型在低置信区不可信反而要维持高阈值。最后说冻结微调。当你后来拿到几十张新产线样本时不必把整个模型重训用freeze10冻结前10层只更新检测头几百步就能适应新产线yolo detect train \ datadata.yaml \ modelsteel_runs/detect/train/weights/best.pt \ epochs30 \ freeze10 \ imgsz640 \ batch8数据越少冻结层越多这是小样本场景下兼顾拟合速度与防过拟合的常见做法。我在这类钢材缺陷数据集上翻过几次车后来养成的习惯是每次拿到新zip先写分布清单、再做可视化标签这关没过之前绝不提交训练任务。这个纪律救了我很多次希望帮到你。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联
返回资讯列表 →