首页 / 资讯中心 / 文章详情

DETR自定义数据集实战:COCO格式转换到训练部署全流程

DETR自定义数据集实战:COCO格式转换到训练部署全流程 ★ FEATURED ARTICLE
1. 项目概述与整体设计思路1.1 这个项目到底要解决什么问题DETRDetection Transformer检测Transformer这个名字在目标检测圈子里已经不算新鲜了但直到现在真正拿它跑过自己数据集的人依然不算多。原因很简单网上公开的教程大多是拿COCO这种现成数据集做演示换到自己的业务数据时光是把数据格式理顺就要折腾不少时间。我最初接触DETR的时候也踩了不少坑。那时候我对Transformer在视觉方向的理解还停留在“看完论文觉得很厉害但不知道代码长什么样”的层面。后来花了几个周末把官方仓库里的训练代码、数据加载逻辑、损失函数部分逐行过了一遍再用自己的数据集完整跑通了一次训练和推理才算是真正入了门。这篇内容想分享的核心就一件事如何从零开始把你的私有数据集做成DETR能认的格式然后完成训练、评估、推理的完整闭环。内容会涉及数据集转换脚本怎么写、训练参数怎么调、loss曲线怎么看、模型导出之后怎么部署以及我在实际操作中遇到的各种稀奇古怪的报错和解决办法。适合看这篇内容的人我觉得主要有三类一是已经在用Faster R-CNN或YOLO做检测想试试Transformer方案的二是论文需要做对比实验但没时间从零啃源码的研究生三是工程上需要部署检测模型但被DETR的数据格式卡住一直没跑通的开发者。1.2 为什么选DETR而不是继续用YOLO在做这个项目之前我也在YOLOv5和DETR之间纠结过。YOLO系列的生态太成熟了从数据标注到部署几乎每一步都有现成工具。但DETR有一个YOLO系方法很难替代的优势它把目标检测彻底变成了一个集合预测问题不需要Anchor、不需要NMS整个过程是端到端的。这意味着什么用生活类比来说YOLO的做法像在一个大房间里先摆很多不同大小的“相框”Anchor框然后逐个判断哪个相框里正好框住了一个物体而DETR的做法更像直接问“这个房间里有哪些物体分别在哪、多大”让模型一次性给出答案并且通过匈牙利匹配算法让预测结果和真实目标一一配对。DETR的另一个隐性优势是对小目标和遮挡场景的建模能力。它的注意力机制天然具备全局感受野不像传统CNN检测器那样受限于局部卷积核。不过这里也要泼一盆冷水DETR的收敛速度确实比YOLO慢训练需要更多轮次对显存的要求也更高。所以它并不是“取代”YOLO的方案而是提供了另一种解决问题路径。1.3 项目整体技术栈与依赖环境在我实际跑通的这套流程里技术栈很明确组件版本建议说明Python3.8 或 3.10太老或太新的版本容易跟CUDA版本冲突PyTorch1.10 以上DETR对自动混合精度支持较好建议使用新版CUDA11.x需要和PyTorch编译时使用的CUDA版本对应环境工具Anaconda用虚拟环境隔离项目依赖避免污染系统环境标注工具LabelImg 或 X-AnyLabeling输出Pascal VOC格式后续转成COCO JSONCocoDataset是DETR官方源码中默认使用的数据接口它需要每一张图片对应一个JSON文件精灵标注或LabelImg生成的XML格式无法直接使用所以数据格式转换是整个流程的第一步也是最重要的一步。2. 数据集准备与COCO格式转换详细指南2.1 COCO数据集格式到底长什么样聊转换之前必须先说清楚COCO格式的结构。很多人在这一步就迷糊了原因在于COCO的JSON文件不像VOC的XML那么直观它是一个嵌套的字典结构。一个标准的COCO标注JSON核心包含五个字段{ info: {...}, licenses: [...], images: [ { id: 1, file_name: 000001.jpg, height: 480, width: 640 } ], annotations: [ { id: 1, image_id: 1, category_id: 1, bbox: [x, y, width, height], area: 10000, segmentation: [], iscrowd: 0 } ], categories: [ {id: 1, name: person}, {id: 2, name: car} ] }这里有几个容易出错的地方。bbox的坐标是左上角x、y以及框的宽高注意不是中心点坐标也不是右下角坐标。很多人在转换时顺手就用了VOC格式里的xmin, ymin, xmax, ymax结果就是训练出来的模型预测框全是歪的。area字段的计算方式是width * height有的工具导出的JSON里area字段算错了会导致训练时损失震荡因为DETR的小目标判定依据之一就是area大小。image_id必须和images数组里的id对应上否则训练时模型会找不到图片对应的标注。这个问题排查起来相当隐蔽因为程序通常不会报错只是精度上不去。2.2 VOC转COCO完整脚本实现我用的数据标注工具默认导出Pascal VOC格式也就是每张图一个XML文件里面存着目标类别和bounding box坐标。写一个转换脚本把这些XML批量转成COCO的单个JSON文件步骤如下import os import json import xml.etree.ElementTree as ET from PIL import Image def voc_to_coco(annotation_dir, image_dir, output_json, categories): images, annotations [], [] annotation_id 1 image_id_counter 1 # 记录类别名称到id的映射 cat_name_to_id {name: idx for idx, name in enumerate(categories, start1)} xml_files [f for f in os.listdir(annotation_dir) if f.endswith(.xml)] for xml_file in xml_files: tree ET.parse(os.path.join(annotation_dir, xml_file)) root tree.getroot() # 获取图片信息 filename root.find(filename).text img_path os.path.join(image_dir, filename) with Image.open(img_path) as img: width, height img.size image_entry { id: image_id_counter, file_name: filename, width: width, height: height } images.append(image_entry) # 读取所有object标注 for obj in root.findall(object): name obj.find(name).text if name not in cat_name_to_id: continue category_id cat_name_to_id[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) # 保证坐标非负 xmin max(0, xmin) ymin max(0, ymin) width_box max(0, xmax - xmin) height_box max(0, ymax - ymin) annotation_entry { id: annotation_id, image_id: image_id_counter, category_id: category_id, bbox: [xmin, ymin, width_box, height_box], area: width_box * height_box, segmentation: [], iscrowd: 0 } annotations.append(annotation_entry) annotation_id 1 image_id_counter 1 coco_json { images: images, annotations: annotations, categories: [{id: v, name: k} for k, v in cat_name_to_id.items()] } with open(output_json, w) as f: json.dump(coco_json, f, indent2) print(fProcessed {len(images)} images, {len(annotations)} annotations) if __name__ __main__: categories [person, car, cat, dog] # 改成你自己的类别 voc_to_coco( annotation_dirdata/annotations_xml, image_dirdata/images, output_jsondata/annotations_train.json, categoriescategories )注意我只转换了bbox和area没有处理segmentation因为DETR训练时如果segmentation为空数组损失函数会自动跳过分割部分只计算检测相关损失。如果你的数据标注里有polygon多边形信息也可以一并转出来但那样的话需要额外处理复杂度会高不少。2.3 目录结构与数据集划分官方仓库的数据加载逻辑通过image_dir和annotation_file两个参数区分训练集和验证集。我个人的习惯是建一个如下的目录结构data/ ├── images/ │ ├── train/ │ │ ├── img_001.jpg │ │ └── ... │ └── val/ │ ├── img_001.jpg │ └── ... ├── annotations/ │ ├── instances_train.json │ └── instances_val.json这里有一个重要的坑训练集和验证集的图片要严格分开别让同一张图同时出现在两个集合里。我最初图省事随机划分时忘了设置随机种子导致训练集和验证集重叠严重结果验证精度虚高模型实际部署效果很差。划分比例我建议先按8:2来。如果数据量特别少比如不到1000张可以试试9:1但要注意验证集太少会导致评估结果抖动很大。提示整个转换完成后务必手动打开生成的JSON文件检查几个数据点看看bbox坐标是否在图片范围内category_id是否和categories列表对应。别偷懒这一步在以后排查问题时能省下大量时间。3. 训练环境搭建与参数配置深度解析3.1 从源码层面理解DETR的训练入口DETR官方仓库的训练入口是main.py它接收一组命令行参数核心内容包括数据集路径、模型结构选择、训练轮数、学习率、批量大小等。这里我贴一个我实际用过的启动命令同时解释每个参数的含义python main.py \ --dataset_file coco \ --coco_path data/ \ --output_dir output/ \ --resume output/checkpoint.pth \ --batch_size 4 \ --num_workers 4 \ --epochs 300 \ --lr 1e-4 \ --lr_drop 200 \ --clip_max_norm 0.1 \ --seed 42dataset_file coco表示使用COCO格式的数据集加载器coco_path指向包含images和annotations子目录的根路径。--resume用来从已有checkpoint继续训练这个参数训练中断恢复时特别有用。--lr_drop 200是什么意思它表示在第200个epoch时把学习率降低一个数量级。DETR训练后期需要小学习率来收敛得更精细这个设定是有理论依据的。在实际训练中我建议不要随意去掉这个参数否则最后几十轮的loss可能会出现平台期。3.2 Batch Size与显存占用一张卡能跑多大DETR对显存的消耗比大多数CNN检测器要高原因在于Transformer解码器里的自注意力机制需要对所有目标查询object query计算两两之间的注意力权重。我的显卡是24GB显存的情况下用ResNet-50作为骨干网络batch_size可以稳定撑到4到6。如果是12GB显存的小卡建议batch_size从2开始试。如果显存不够但又想加大batch_size我试验过最有效的方法是开启自动混合精度AMP。在启动命令里加上--amp参数显存占用能下降约30%到40%。PyTorch的AMP会自动识别哪些算子可以用半精度计算哪些必须保持全精度DETR的匹配损失部分对精度比较敏感但AMP会自动处理实测结果影响不大。注意如果你的显卡型号比较老不支持新的CUDA特性AMP可能导致训练速度变慢而不是变快。动手之前先确认一下显卡的算力版本。3.3 GIOU损失和分类损失的平衡权重DETR的损失由三部分组成分类损失使用交叉熵、L1回归损失预测框与真实框的坐标差异、GIOU损失预测框与真实框的交并比差异。官方默认的权重设置是weight_dict { loss_ce: 1, loss_bbox: 5, loss_giou: 2 }这个权重比不是我随便说的是官方训练时使用的默认值。L1损失权重设为5是为了把坐标误差的数值尺度拉到和分类损失接近的量级。在自定义数据集上如果目标框普遍很大L1损失的数值波动会比COCO更明显这时可以考虑把loss_bbox的权重稍微调小一点比如从5调到2或3。调权重的方法是在源码中修改loss.py里的weight_dict结构重新设置后需要重新编译吗不需要Python脚本改动后重启训练就生效了。但我的经验是除非你的数据分布和COCO差异相当大否则先按默认权重跑一个版本再说这比盲调靠谱得多。3.4 骨干网络选择ResNet-50还是ResNet-101DETR的骨干网络直接决定特征提取的能力和训练时间。官方提供了两种配置--backbone resnet50和--backbone resnet101。我做了两组对比实验在自己的数据集上约5000张精标数据ResNet-101相比ResNet-50在AP上大概能涨1到2个百分点但训练时间增加了将近50%。如果追求训练速度先用ResNet-50跑通整个流程确认代码和数据都没问题然后再用ResNet-101做一轮正式训练。不要一上来就用大模型否则如果数据格式有隐蔽错误会让你浪费大量时间在一个错误的基线之上。4. 训练过程中的核心观察与调参实战4.1 Loss曲线怎么看识别收敛的信号这是整篇文章里我觉得最值得详细写的一部分。很多新手拿到训练日志后只会盯着一个总loss值看其实DETR训练日志里有多个分量每个分量的意义不同。第一个epoch结束时你看到的loss_ce分类损失通常比较大大概在2到3之间。这是因为匈牙利匹配算法在初始化阶段还没有找到好的匹配策略预测结果和真实目标之间的对应关系是混乱的。随着训练推进到第5到第10个epoch你会看到loss_ce快速下降到1左右这个下降速度比YOLO快因为Transformer的分类头相对简单。而loss_giou的下降就慢得多通常要到第50个epoch之后才趋于稳定。我在实际项目中观察到loss_giou在前20个epoch几乎是一条斜率为负的很缓的直线但只要过了某个临界点下降速度会突然加快这跟匈牙利匹配的对应关系逐渐稳定是同步的。我的建议是把训练日志重定向保存下来每隔10个epoch用TensorBoard或者直接画一张loss曲线图。如果发现loss_ce一直在1.5以上降不下去大概率是数据标注里有问题比如类别标注错误、bbox框得不准或者某个类别的样本数量太少。4.2 各类别AP不平衡问题与数据增强策略如果你的数据集里类别分布严重不平衡比如“缺陷”类有3000个样本“商标位置异常”类只有200个样本DETR训练出来的模型在少样本类别上的AP会非常难看。最朴素但有效的方法是对少样本类别做离线复制增强。具体做法是把包含该类别的小图片随机裁剪、翻转、调整亮度后重新存为新的训练样本。我试过一次把某类别样本量从200扩到800AP从0.31提升到了0.47提升幅度相当可观。第二种方法是调整类别权重。在criterion.py里你可以给CrossEntropyLoss传入weight参数让少样本类别的loss权重更高。实际操作中一个简单的做法是用1 / sqrt(class_frequency)作为权重向量这个技巧在长尾分布数据上效果明显。三种增强的组合是我当前比较推荐的方案随机水平翻转概率0.5、随机尺度缩放0.8到1.2倍、颜色抖动亮度、对比度、饱和度各做轻微扰动。DETR对平移和尺度变化比较敏感多尺度训练能让它学到更鲁棒的特征。4.3 训练中断恢复与Checkpoint管理大型训练任务往往要跑十几个小时甚至几十个小时中途断电、显存溢出导致的训练中断几乎一定会遇到。DETR的官方仓库支持用--resume参数加载checkpoint继续训练。这里我需要分享一个可能很多人没用过的小细节官方实现里只会保存model_state_dict和optimizer_state_dict但不保存训练步数计数器。所以断点续训后学习率调度器的起点会错乱。如果你在第150个epoch中断然后从最近的checkpoint恢复学习率调度器是从第150个epoch的步数继续这没问题但如果你的checkpoint保存了步数而加载时又忘了改参数就可能出现重复训练同一个epoch的情况。我个人的做法是写一个自定义的回调函数每几个epoch保存一次状态并且在文件名里带上epoch编号例如checkpoint_epoch_100.pth。恢复训练时手动把--start_epoch设为对应的数字保证学习率调度器和验证集评估的epoch口径对得上。提示如果训练日志显示loss已经收敛但AP上不去先别急着加数据。检查验证集标注是不是有漏标。DETR对漏标的惩罚是隐形的AP被低估却不明显而human标注的漏标率在5%到10%都是很常见的。5. 模型评估与推理测试完整流程5.1 验证集评估AP、AR指标解读在模型训练完成后官方仓库执行评估的命令是加--eval参数。评估完成后会在日志里输出一段类似下面这样的指标汇总Average Precision (AP) [ IoU0.50:0.95 | area all | maxDets100 ] 0.412 Average Precision (AP) [ IoU0.50 | area all | maxDets100 ] 0.638 Average Precision (AP) [ IoU0.75 | area all | maxDets100 ] 0.431 Average Recall (AR) [ IoU0.50:0.95 | area all | maxDets100 ] 0.535这里面最有参考价值的数字是APIoU0.75它反映的是定位精度。如果你的目标应用场景对框的精确位置要求高比如工业定位、自动驾驶这个指标比AP0.5重要得多。另外一个你可能会忽略的指标是ARAverage Recall平均召回率它衡量的不是定位精度而是“模型最多能找出多少目标”。如果AR高但AP低说明模型能找到目标但定位不准优先调回归损失权重如果AP高但AR低说明模型漏检多优先做数据增强和调整分类损失。5.2 用测试图片跑推理的完整示例训练完成后你肯定希望直接拿一张新图片看效果。DETR官方仓库提供了一个推理脚本但输出的是一个封装好的DetectionResults对象需要自己解析。这里我给出一个精简版推理脚本import argparse import torch import torchvision.transforms as T from PIL import Image from models import build_model from util.misc import nested_tensor_from_tensor_list def main(args): # 加载模型结构 model, criterion, postprocessors build_model(args) # 加载权重 state_dict torch.load(args.resume)[model_state_dict] model.load_state_dict(state_dict) model.eval() # 图像预处理 transform T.Compose([ T.Resize(800), T.ToTensor(), T.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) ]) img Image.open(args.image_path).convert(RGB) img_tensor transform(img).unsqueeze(0) # 推理 with torch.no_grad(): outputs model(img_tensor) # 后处理 probas outputs[pred_logits].softmax(-1)[0, :, :-1] keep probas.max(-1).values 0.5 boxes outputs[pred_boxes][0, keep] scores probas[keep].max(-1).values labels probas[keep].max(-1).indices print(fDetected {boxes.shape[0]} objects) # 保存结果或可视化 for score, label, box in zip(scores, labels, boxes): print(fClass: {label}, Score: {score:.3f}, Box: {box.tolist()}) if __name__ __main__: parser argparse.ArgumentParser() parser.add_argument(--resume, typestr, requiredTrue) parser.add_argument(--image_path, typestr, requiredTrue) parser.add_argument(--backbone, typestr, defaultresnet50) parser.add_argument(--num_classes, typeint, default91, help更新为你自己的类别数) args parser.parse_args() main(args)注意这里的--num_classes必须和你训练时的类别数一致并且要包含背景类。也就是说你实际检测5类物体这里要填5加1等于6。5.3 导出模型到ONNX进行部署项目最终落地时很少直接使用PyTorch模型文件进行推理部署通常需要导出为ONNX格式。DETR导出ONNX时有一个老生常谈的坑Transformer的函数中有一个nested_tensor的操作在ONNX导出时会报错解决办法是把输入统一成普通张量禁用mask机制。我提供的导出脚本核心如下model.eval() dummy_input torch.randn(1, 3, 800, 800) # 关键DETR的mask是隐藏在输入里的导出前需要解除mask逻辑 # 可以临时把backbone输出的mask置为None torch.onnx.export( model, dummy_input, detr.onnx, input_names[input], output_names[pred_logits, pred_boxes], dynamic_axes{input: {0: batch_size}, pred_logits: {0: batch_size}} )导出之后再用ONNX Runtime加载模型做一次推理验证。如果在ONNX下结果和PyTorch不一致优先检查Batch Normalization层在导出时是不是被错误地设为训练模式。DETR的骨干网络里BN层在推理时必须处于eval模式导出的模型在ONNX Runtime里默认是推断模式但如果你导出的checkpoint是在训练模式下导出的数值会有偏差。6. 常见问题与排查技巧实录6.1 训练速度极慢GPU利用率上不去这个问题出现频率非常高而且往往查不出明确报错。我遇到过最典型的场景是nvidia-smi显示GPU利用率为60%左右但训练一个epoch需要6个小时。排查思路分成三路第一检查--num_workers是否设置得当。默认值为2可能不够但设置过高比如12可能导致数据加载进程之间互相争抢系统资源反而变慢。我的经验是8核CPU配置4到6个worker是比较甜点的区间。第二确认输入图像的分辨率是否过大。DETR训练时默认会把图像等比例缩放到短边800像素但如果你的原始图片是4000x3000读取和解码本身会占用大量I/O时间。可以在数据加载阶段就对图片做一次预处理存成短边1600左右的缩略图能明显提速。第三检查是不是CPU瓶颈。在数据加载日志里开启--profile或者简单粗暴地在每个epoch结束后打印一次平均耗时对比不同阶段是数据队列等待还是模型前向耗时占大头。后者如果是瓶颈就要考虑是不是batch size太小导致GPU流水线有空闲。6.2 训练时显存溢出一个Batch都跑不起来显存溢出是最让人头疼的错误之一。如果连batch_size1都无法运行问题大概率在模型配置上而不是显存本身。我遇到过一种特殊情况把--hidden_dim设得过大比如512甚至1024导致Transformer解码器的参数量暴增。DETR默认的hidden_dim是256在大多数自定义数据集上完全够用完全没必要学COCO实验里那种大模型配置。此外检查是否开启了--amp。如果显卡支持混合精度这个选项能显著降低显存占用。如果用了--amp依旧溢出就要考虑换一个骨干网络更小的配置比如把ResNet-101换成ResNet-50。6.3 模型预测结果全是背景类空白输出预测框全部为空是异常情况中最常见、也最容易被误认为“模型训练失败了”的现象。但实际上绝大多数情况是后处理逻辑出了问题。pred_logits的shape是(batch, num_queries, num_classes 1)最后一维里额外的那一类是背景类类别ID为num_classes。在从probas里取最大值时如果忘了去掉背景类那一维模型确实只会输出背景类因为背景类的logit数值通常是最高的。我贴的推理代码里有一行probas outputs[pred_logits].softmax(-1)[0, :, :-1]这行代码就是用来去掉背景类维度的。很多人漏掉这行导致后面阈值筛选 0.5时永远找不到满足条件的物体。这个问题只要检查一下输出维度就能发现但因为它不抛异常找起来特别费时间。另外后处理里的阈值0.5不是标准答案。如果你的数据集类别比较少类别预测置信度一般偏低可以适当降低到0.3如果场景需要降低误报率可以调高到0.7。这阈值本质上是业务需求决定的没有统一的最优值。6.4 训练loss不降反升的问题定位思路loss上升的情况比较罕见但一旦出现通常意味着数据链路出了问题。我遇到过一次loss震荡特别剧烈的情况排查到最后发现是验证集里混了一张全黑图片标注框坐标明显越界。定位思路是查看loss曲线里波动幅度最大的epoch把该epoch的训练日志和该batch的图片一一对应找出来。有个简单可行的办法在engine.py中临时打印每个batch的image_id配合checkpoint保存的步数信息反推是哪张图导致异常。梯度裁剪相关参数--clip_max_norm 0.1建议保持开启状态。它能把每次更新的梯度范数限制在0.1以内可以避免偶然的异常batch把模型权重推向一个不可恢复的区域。我自己做过实验移除这个参数后训练稳定性明显下降。7. 经验总结与效率提升技巧7.1 数据标注质量对DETR训练的影响权重做了多个DETR项目后我形成一个很强烈的感受数据质量对DETR的影响比对传统CNN检测器更明显。原因在于DETR端到端训练的匹配机制如果真实框标得不准匈牙利匹配算法在初期很难为这个目标找到合适的预测框最终导致这一部分的梯度信号非常弱。主观感受上DETR相比YOLO在边框标注精度上更“挑剔”。YOLO的Anchor机制天然能容忍一定程度的标注偏移而DETR的回归头直接预测绝对坐标对偏差敏感得多。因此在数据标注这个环节哪怕多花一倍时间把框边界标准也比后面加数据来弥补更划算。7.2 迁移学习用COCO预训练权重还是从头训练在数据量还不大的阶段强烈建议下载官方提供的COCO预训练模型作为初始化权重。官方仓库在Hub上提供了ResNet-50和ResNet-101作为骨干的不同检查点加载方式是在启动命令里加--pretrained https://dl.fbaipublicfiles.com/detr/detr-resnet50.pth预训练权重为头部初始化提供了一个合理的特征提取空间。即使你的目标域和COCO差异较大前几层提取的边缘、纹理特征仍然有迁移价值。在这个实践项目里加载预训练权重后只用了120个epoch就达到了从头训练350个epoch的AP水平。但注意官方预训练权重是在COCO上训练的类别数量是91。加载时源码会自动忽略分类头和框回归头的权重如果没有自动忽略你会看到这几层加载时出现“size mismatch”的警告那属于正常现象。7.3 后续扩展方向从DETR到Deformable DETR和DINO跑通这套基础流程后下一步可以尝试的几个方向依次是Deformable DETR、Conditional DETR和DINO。先说说Deformable DETR。它在DETR基础上引入了可变形注意力机制只对每个查询附近的少量采样点做注意力计算能显著降低训练难度和收敛时间。我大概只花了半天时间就把数据加载部分从DETR迁移到了Deformable DETR因为两者共用同一套COCO数据接口改的基本只有模型构建部分。收敛速度大概快了一倍多最终AP也更高。然后是DINODenoising with Anchor Boxes for End-to-End Object Detection。它把去噪训练和锚点框结合了起来在COCO上取得了比Deformable DETR更具竞争力的结果而且部署推理的流程几乎一致。但DINO的训练脚本复杂不少建议等熟练掌握了DETR的数据链路之后再去接触。7.4 我做这个项目时的整体心得体会最后分享一点个人感受。DETR这套方案在自定义数据集上落地真正的门槛不在模型结构理解而在于数据准备和调试耐心。COCO格式虽然琐碎但只要跨过这个坎后面从训练到部署的通路反而是最顺畅的。它不像YOLO那样需要为每个数据集重新设计Anchor尺寸也不需要调NMS阈值省掉的这些工程时间足以弥补训练阶段的等待。如果你准备动手做我的建议是先拿一个20张图片的小数据集跑通全流程确认每个环节都没问题再扩大到全量数据。这个“探路策略”看起来绕路实则能帮你节省至少半天排查时间。训练过程中至少每隔20个epoch做一次验证集评估不要等到训练结束才看结果那样一旦发现方向错误整个训练周期就白费了。
阅读完成 · 觉得有帮助?
咨询建站