ARTICLE DETAIL

资讯详情

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

YOLO手机检测实战:2800张数据集训练、调优与部署全流程

YOLO手机检测实战:2800张数据集训练、调优与部署全流程 1. 手机检测数据集项目整体设计与思路拆解1.1 为什么手机检测值得单独做一个数据集手机检测这个方向乍一听好像挺小众但真正在工业质检、考场监控、产线管理、二手回收这些场景里摸爬滚打过的人都知道手机目标检测的需求一点都不少。比如手机组装厂的产线末端需要自动识别流水线上是否还有遗留的手机整机或半成品再比如一些涉密场所的入口管理需要检测是否有人违规携带手机进入特定区域还有二手手机回收平台需要批量识别手机的品牌、型号、屏幕状态甚至判断有没有拆修痕迹。这些场景的共同点是目标物体尺寸相对固定、背景复杂度中等、但对检测精度和推理速度都有比较明确的要求。我这次整理的这套数据集一共2800张图像全部标注为YOLO格式覆盖了手机在多种场景下的外观形态。说实话2800张这个量级在目标检测任务里不算大但对于手机这一类形态相对统一的目标来说已经足够训练出一个可用的基线模型了。关键在于标注质量和场景覆盖度而不是单纯堆数量。我见过太多人拿着几万张标注稀烂的数据集训练最后mAP还不如人家两千张精标的模型这种事情在目标检测圈子里太常见了。这套数据集的核心价值在于它提供了一个开箱即用的手机检测基线你可以直接拿去做迁移学习的起点也可以作为自己采集数据时的标注参考。适合的人群包括刚入门YOLO目标检测的开发者、需要快速搭建手机检测原型的工程师、以及做相关课题研究的学生。不管你用的是YOLOv5、YOLOv8还是更新的版本这套数据集的目录结构和标注格式都是通用的。1.2 数据集的核心构成与标注规范先说一下这套数据集的基本构成。2800张图像按照常见的划分比例我建议按照7:2:1或者8:1:1来切分训练集、验证集和测试集。如果按照8:1:1来算训练集2240张验证集280张测试集280张。这个比例在手机检测这种单类别任务上是比较稳妥的验证集和测试集各280张足够评估模型的泛化能力了。标注格式是标准的YOLO txt格式每张图像对应一个同名的txt文件每行表示一个目标格式为class_id x_center y_center width height其中坐标都是归一化到0到1之间的相对值。手机检测通常只有一个类别所以class_id就是0。这里要特别注意一个坑很多人在转换VOC格式到YOLO格式的时候忘记做归一化或者把绝对坐标直接写进去了导致训练时loss直接爆炸。我建议在正式训练之前先写个脚本抽查一下标注文件确认所有坐标值都在0到1之间且width和height不为零。数据集的目录结构我推荐这样组织phone_dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yamldata.yaml的内容大致如下train: ./images/train val: ./images/val test: ./images/test nc: 1 names: [phone]这个结构是YOLOv5和YOLOv8都兼容的直接改一下路径就能用。我试过用同样的结构在YOLOv8上跑不需要任何额外改动非常省心。1.3 场景覆盖与难度分层设计2800张图像如果只是从同一个场景里截取那训练出来的模型泛化能力会很差。所以我在整理这套数据集的时候刻意做了场景分层。大致可以分为以下几类室内桌面场景手机平放在桌面上背景是键盘、鼠标、水杯等常见办公物品这类场景大约占40%。这类图像的特点是光照均匀、目标清晰属于简单样本。手持场景手机被人拿在手里角度多变有时只有部分机身可见这类大约占25%。这类样本的难点在于手部遮挡和角度变化。多机堆叠场景多部手机叠放在一起存在相互遮挡这类大约占20%。这是检验模型遮挡处理能力的关键样本。复杂背景场景手机放在沙发、床单、草地等纹理复杂的背景上这类大约占15%。这类样本主要考验模型对背景干扰的鲁棒性。这种分层设计的好处是你在训练过程中可以通过验证集的分项指标清楚地知道模型在哪类场景下表现好、哪类场景下还有欠缺。比如如果手持场景的mAP明显低于桌面场景那就说明模型对角度变化和遮挡的适应能力还不够可以考虑增加RandAugment或者Mosaic增强的强度。注意场景分层的比例不是固定的你可以根据自己的实际应用场景调整。如果你的目标场景主要是产线传送带那就应该把产线场景的样本比例提高到60%以上其他场景作为补充。2. 核心细节解析与实操要点2.1 YOLO标注格式的细节陷阱YOLO格式看起来简单但实际操作中有几个细节特别容易翻车。第一个是坐标归一化的基准。YOLO的x_center和y_center是相对于图像宽高的归一化值不是相对于标注框的。我见过有人把x_center算成了框中心相对于框宽的比例这种错误在训练初期可能不会报错但模型学出来的东西完全是错的。第二个是类别编号的起始值。YOLO的类别编号从0开始不是从1开始。如果你是从VOC格式转换过来的VOC的类别编号通常从1开始转换的时候一定要减1。这个坑我踩过不止一次训练的时候loss正常下降但推理的时候所有框的类别都是错的排查了半天才发现是编号没对齐。第三个是空标注文件的问题。有些图像里确实没有手机目标对应的txt文件应该是空的而不是不创建。YOLOv5和YOLOv8对空标注文件的处理方式是该图像会被视为背景样本不参与正样本的loss计算但仍然会参与背景的loss计算。如果你直接删掉了空标注文件那这些背景图像就完全不会被加载模型对背景的抑制能力会变弱。第四个是标注框的边界问题。如果标注框超出了图像边界YOLO在训练时会自动裁剪但裁剪后的框可能变得非常小甚至为零。我建议在标注阶段就确保所有框都在图像范围内留出至少几个像素的边距。2.2 图像尺寸与增强策略的选择YOLO系列默认的输入尺寸是640x640但这套数据集里的图像原始分辨率各不相同。我建议在训练前统一resize到640x640同时保持长宽比多余的部分用灰色填充。这种做法比直接拉伸变形要好因为手机的长宽比相对固定直接拉伸会导致目标变形影响检测精度。数据增强方面我实测下来以下几组增强策略对手机检测比较有效增强方法参数建议作用Mosaic概率0.5-1.0提升小目标和遮挡场景的检测能力MixUp概率0.1-0.2增强模型对重叠目标的区分能力HSV增强h0.015, s0.7, v0.4提升对不同光照条件的鲁棒性随机翻转水平翻转概率0.5增加样本多样性随机缩放缩放范围0.5-1.5提升对不同尺寸目标的适应能力Mosaic增强是YOLOv5和YOLOv8的默认增强方式它把四张图像拼成一张能显著提升模型对遮挡和小目标的检测能力。但要注意Mosaic增强在训练后期可能会让模型对拼接边界产生依赖所以通常会在最后几个epoch关闭Mosaic。YOLOv8默认是在最后10个epoch关闭Mosaic这个策略我实测下来是合理的。HSV增强的参数需要根据你的实际场景调整。如果数据集中光照变化不大HSV增强的幅度可以小一些如果光照变化剧烈比如有强光直射和暗光环境那HSV增强的幅度可以适当加大。我一般会把h设为0.015s设为0.7v设为0.4这个组合在大多数场景下都比较稳。2.3 预训练模型的选择与迁移学习策略手机检测属于单类别目标检测数据量只有2800张从零开始训练很难收敛到理想效果。所以迁移学习是必须的。YOLOv8提供了n、s、m、l、x五个尺度的预训练模型我建议从YOLOv8s或YOLOv8m开始。n版本太小特征提取能力有限l和x版本参数量太大2800张数据容易过拟合。迁移学习的策略我一般分两步走第一步冻结骨干网络只训练检测头学习率设大一点比如0.01训练20到30个epoch。这一步的目的是让检测头快速适应手机这个新类别。第二步解冻全部网络用较小的学习率比如0.001再训练50到100个epoch让整个网络微调。这种分步策略比直接端到端训练收敛更快最终精度也更高。提示如果你用的是YOLOv8可以直接通过model.train()的freeze参数来控制冻结的层数。比如freeze10表示冻结前10层通常就是骨干网络的前几个stage。预训练模型的下载渠道我一般用官方发布的权重文件直接从YOLO的官方仓库下载。注意要下载对应版本的权重YOLOv8的权重不能直接用在YOLOv5上虽然结构相似但层名和参数对应关系不一样。2.4 损失函数与评价指标的关注重点YOLOv8的损失函数由三部分组成分类损失、定位损失和DFL损失。对于手机检测这种单类别任务分类损失其实很快就降下去了真正影响最终精度的是定位损失。所以我在训练过程中会重点关注box_loss的变化趋势如果box_loss下降缓慢或者震荡严重通常说明学习率设置有问题或者标注框的质量不高。评价指标方面mAP0.5和mAP0.5:0.95是两个核心指标。mAP0.5反映的是模型在宽松IoU阈值下的检测能力mAP0.5:0.95则更严格反映的是定位精度。对于手机检测我一般要求mAP0.5达到0.95以上mAP0.5:0.95达到0.75以上才算是一个可用的模型。如果mAP0.5很高但mAP0.5:0.95很低说明模型能检测到手机但框的位置不够准这时候需要检查标注框的贴合度。混淆矩阵也是我必看的一个指标。虽然手机检测是单类别混淆矩阵看起来很简单但通过混淆矩阵可以判断模型是否把背景误检为手机。如果背景被大量误检说明模型的背景抑制能力不足可以考虑增加背景样本或者提高背景损失的权重。3. 实操过程与核心环节实现3.1 环境搭建与依赖安装环境搭建这一步我踩过的坑比训练本身还多。最常见的问题是CUDA版本和PyTorch版本不匹配导致训练时GPU用不了或者报一些莫名其妙的错误。我建议直接用conda创建一个独立环境然后按照PyTorch官网的安装命令来装不要自己瞎折腾版本组合。conda create -n yolo_phone python3.9 conda activate yolo_phone pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install ultralytics装完ultralytics之后可以用yolo checks命令检查环境是否正常。这个命令会输出PyTorch版本、CUDA是否可用、GPU型号等信息。如果CUDA显示不可用那就要检查显卡驱动和CUDA版本是否匹配。注意如果你用的是V100这类计算卡CUDA版本建议选11.8或12.1这两个版本对V100的支持都比较稳定。太新的CUDA版本可能没有对应的PyTorch预编译包太旧的版本又可能不支持新的YOLO特性。3.2 数据集准备与配置文件编写数据集准备好之后按照前面说的目录结构放好。然后写data.yaml文件这个文件是YOLO训练时读取数据路径和类别信息的入口。我一般会把data.yaml放在数据集根目录下内容如下path: /home/user/phone_dataset train: images/train val: images/val test: images/test nc: 1 names: [phone]这里有个细节path字段是数据集根目录的绝对路径train、val、test是相对于path的相对路径。这种写法比直接写绝对路径更灵活换机器的时候只需要改path一个地方。写完之后我建议先跑一个数据检查脚本确认所有图像都能正常读取标注文件都能正确解析。YOLOv8自带了一个数据检查功能可以在训练前用model.train()的rect参数开启矩形训练这样会在第一个epoch打印出数据集的统计信息包括图像数量、标注框数量、类别分布等。如果发现标注框数量为零那就要检查标注文件路径是否正确。3.3 训练参数配置与启动训练参数的配置直接决定了最终模型的质量。我一般会用一个python脚本或者yaml配置文件来管理参数而不是在命令行里敲一长串。以下是我常用的YOLOv8训练配置from ultralytics import YOLO model YOLO(yolov8s.pt) results model.train( dataphone_dataset/data.yaml, epochs100, imgsz640, batch16, workers4, device0, optimizerAdamW, lr00.001, lrf0.01, momentum0.937, weight_decay0.0005, warmup_epochs3, warmup_momentum0.8, box7.5, cls0.5, dfl1.5, hsv_h0.015, hsv_s0.7, hsv_v0.4, degrees0.0, translate0.1, scale0.5, shear0.0, perspective0.0, flipud0.0, fliplr0.5, mosaic1.0, mixup0.1, copy_paste0.0, patience50, saveTrue, save_period10, projectphone_detection, nameyolov8s_phone )这里有几个参数需要重点解释一下。batch16是在V100上比较稳妥的值显存占用大约8GB左右。如果你的显存更小可以降到8或者4。lr00.001是初始学习率配合AdamW优化器使用。lrf0.01是最终学习率相对于初始学习率的比例也就是学习率会从0.001线性降到0.00001。warmup_epochs3是预热轮数前3个epoch学习率从很小的值逐渐升到初始学习率避免训练初期梯度爆炸。box、cls、dfl这三个参数是损失函数的权重。box7.5表示定位损失的权重是7.5cls0.5表示分类损失的权重是0.5dfl1.5表示DFL损失的权重是1.5。对于手机检测这种单类别任务分类损失可以适当降低定位损失可以适当提高因为定位精度才是关键。3.4 训练过程监控与日志解读训练启动之后控制台会输出每个epoch的损失值和评价指标。我一般会重点关注以下几个指标的变化趋势box_loss定位损失应该稳步下降如果震荡严重说明学习率偏大。cls_loss分类损失单类别任务下应该很快降到接近零。dfl_lossDFL损失反映框的分布学习情况应该稳步下降。mAP0.5宽松IoU下的平均精度应该稳步上升。mAP0.5:0.95严格IoU下的平均精度上升速度会比mAP0.5慢。如果训练过程中发现mAP0.5在某个epoch之后不再上升甚至开始下降那大概率是过拟合了。这时候可以看看验证集的loss是否在上升如果是那就应该早停或者降低模型复杂度。YOLOv8的patience参数就是用来控制早停的我一般设为50意思是如果连续50个epoch验证集指标没有提升就自动停止训练。训练完成后YOLOv8会在runs/detect/phone_detection/yolov8s_phone/目录下保存权重文件、训练日志和评估结果。其中weights/best.pt是验证集上表现最好的权重weights/last.pt是最后一个epoch的权重。我一般用best.pt做后续的推理和部署。3.5 模型评估与推理测试训练完成后第一件事是在测试集上跑一遍评估看看模型的真实泛化能力。YOLOv8提供了model.val()方法可以直接在测试集上计算mAP、precision、recall等指标。model YOLO(runs/detect/phone_detection/yolov8s_phone/weights/best.pt) metrics model.val(dataphone_dataset/data.yaml, splittest) print(metrics.box.map) # mAP0.5:0.95 print(metrics.box.map50) # mAP0.5如果测试集上的mAP和验证集上的mAP差距不大说明模型没有过拟合泛化能力可以。如果差距很大比如验证集mAP0.5是0.96测试集只有0.85那说明模型对验证集过拟合了需要增加数据增强或者减少模型参数量。推理测试我一般会拿几张训练时没见过的图像用model.predict()跑一下看看实际检测效果。重点关注几个方面小目标手机是否漏检、遮挡手机是否漏检、背景是否误检。如果发现某类问题比较突出可以针对性地补充训练数据或者调整后处理参数。results model.predict(sourcetest_images/, conf0.25, iou0.45, saveTrue)conf0.25是置信度阈值低于这个值的检测框会被过滤掉。iou0.45是NMS的IoU阈值用于去除重叠的检测框。这两个参数需要根据实际场景调整。如果漏检比较多可以降低conf如果误检比较多可以提高conf。4. 常见问题与排查技巧实录4.1 训练不收敛或loss震荡的排查思路训练不收敛是新手最常遇到的问题。我总结下来原因无非这么几个学习率太大、标注质量差、数据增强太猛、预训练权重不匹配。排查的时候可以按照以下顺序逐一检查。先看学习率。如果box_loss在前几个epoch就飙到几百甚至上千那基本可以确定是学习率太大了。这时候可以把lr0降到0.0001试试。如果loss下降非常慢那可能是学习率太小了可以适当调大。再看标注质量。如果loss能下降但降不到很低比如box_loss一直在0.5左右徘徊那就要检查标注框是否贴合目标。我一般会随机抽几十张图像把标注框画出来看看如果框明显偏大或偏小那就需要重新标注。数据增强太猛也会导致不收敛。比如Mosaic概率设为1.0MixUp概率设为0.5那训练初期的图像会非常混乱模型很难学到有效特征。我建议训练初期把Mosaic概率设为0.5MixUp设为0.0等loss稳定下降后再逐步加大增强强度。预训练权重不匹配这个问题比较隐蔽。如果你用的是YOLOv8的权重但代码里加载的是YOLOv5的模型结构那权重加载会失败模型实际上是从随机初始化开始训练的。这种情况下的loss曲线会非常难看而且很难收敛。排查方法是看训练日志里有没有loading pretrained weights的提示如果没有那就是权重没加载上。4.2 验证集mAP高但测试集mAP低的过拟合问题过拟合在2800张这种小数据集上非常常见。典型表现是验证集mAP0.5能到0.97但测试集只有0.85。解决过拟合的思路无非是增加数据多样性、降低模型复杂度、加强正则化。增加数据多样性最直接的办法是加强数据增强。我一般会把Mosaic概率提到1.0MixUp提到0.2HSV增强的幅度也加大。另外可以试试RandAugmentYOLOv8内置了RandAugment的支持通过augmentTrue开启。RandAugment会自动从一组增强操作中随机选择比手动调参省事很多。降低模型复杂度就是换更小的模型。如果YOLOv8s过拟合那就换YOLOv8n。n版本的参数量只有s版本的三分之一左右在小数据集上反而可能表现更好。我实测下来2800张数据用YOLOv8n训练测试集mAP0.5能到0.93左右比YOLOv8s的0.91还高一点因为过拟合程度更轻。加强正则化可以通过增大weight_decay来实现。我一般会把weight_decay从默认的0.0005提到0.001甚至0.002。另外dropout也可以加但YOLOv8默认没有dropout层需要自己改模型结构比较麻烦不太推荐。4.3 推理时漏检和误检的调优方法漏检和误检是推理阶段的两大痛点。漏检通常是因为置信度阈值设得太高或者模型对小目标、遮挡目标的检测能力不足。误检通常是因为置信度阈值设得太低或者模型对背景的抑制能力不够。调优的第一步是调整conf阈值。我一般会从0.25开始如果漏检多就降到0.15如果误检多就升到0.35。但要注意conf阈值不能无限降低降到0.1以下的话几乎每个位置都会出框后处理压力会非常大。第二步是调整NMS的iou阈值。iou阈值越大保留的重叠框越多适合密集场景iou阈值越小去除的重叠框越多适合稀疏场景。手机检测一般用0.45到0.5之间比较合适。如果调整后处理参数还是解决不了那就需要从模型本身入手。漏检多的话可以在训练时增加小目标和遮挡样本的权重或者用更大的输入尺寸比如从640提到1280。误检多的话可以增加背景样本或者在损失函数里提高背景损失的权重。4.4 常见问题速查表问题现象可能原因排查方法解决方案训练loss不下降学习率太小或标注错误检查学习率和标注文件调大学习率重新标注loss震荡严重学习率太大或batch太小观察loss曲线调小学习率增大batch验证集mAP高测试集低过拟合对比验证集和测试集指标加强增强换小模型推理漏检多conf阈值太高或模型能力不足降低conf阈值测试降低conf增大输入尺寸推理误检多conf阈值太低或背景抑制不足提高conf阈值测试提高conf增加背景样本GPU显存不足batch太大或模型太大查看显存占用减小batch换小模型训练速度慢workers太少或数据加载瓶颈查看GPU利用率增大workers用SSD存储提示这张表是我在实际项目中反复踩坑总结出来的建议保存下来遇到问题的时候按表排查能省不少时间。4.5 几个容易被忽略的实操心得第一个心得是关于图像预处理的。YOLOv8默认会把图像resize到640x640但如果原始图像的长宽比和1:1差距很大resize后目标会变形。我建议在数据准备阶段就把图像裁剪成接近正方形的比例或者在训练时用rect参数开启矩形训练这样YOLO会按长边缩放短边填充保持长宽比。第二个心得是关于学习率调度的。YOLOv8默认用的是线性调度从lr0线性降到lr0*lrf。但我实测下来余弦退火调度在手机检测任务上效果更好最终mAP能高0.5到1个点。可以通过cos_lrTrue开启余弦退火。第三个心得是关于模型导出的。训练完的pt模型如果要部署到边缘设备通常需要导出成ONNX或TensorRT格式。导出的时候要注意输入尺寸和动态batch的设置。我一般会导出成ONNX然后用TensorRT做进一步优化。导出命令很简单yolo export modelbest.pt formatonnx imgsz640 dynamicTruedynamicTrue表示支持动态batch这样部署的时候可以灵活调整batch大小。但要注意动态batch的推理速度通常比固定batch慢一些如果对延迟要求很高建议用固定batch。第四个心得是关于数据集版本管理的。2800张图像虽然不多但标注文件有2800个手动管理很容易乱。我建议用DVC或者Git LFS来做版本管理每次修改标注都提交一次这样出问题的时候可以快速回滚。我吃过这个亏有一次不小心覆盖了标注文件又没有备份只能重新标注了200多张血的教训。5. 模型改进与进阶方向5.1 针对手机检测的模型结构微调YOLOv8的默认结构是针对通用目标检测设计的如果要在手机检测上进一步提升精度可以考虑做一些针对性的结构微调。手机这个目标的特点是长宽比相对固定通常在1.5:1到2:1之间而且边缘特征比较明显。基于这些特点我试过以下几种改进方向。第一种是调整anchor的尺寸。虽然YOLOv8是anchor-free的但它的DFL损失实际上还是在学习框的分布。如果数据集中手机的尺寸分布比较集中可以通过调整DFL的reg_max参数来优化。默认reg_max16表示框的分布被离散成16个bin。如果手机尺寸变化不大可以降到8这样DFL的学习会更集中定位精度可能更高。第二种是在骨干网络后面加一个轻量级的注意力模块。我试过加SE模块和CBAM模块在手机检测任务上CBAM的效果更好一些mAP0.5:0.95能提升1到2个点。但要注意加注意力模块会增加参数量和推理时间如果对速度有要求需要权衡一下。第三种是改进检测头。YOLOv8的检测头是解耦的分类和回归分开。我试过把检测头换成Efficient Head参数量减少了约15%推理速度提升了约10%精度基本持平。Efficient Head的核心思想是用深度可分离卷积替代普通卷积减少计算量。这个改进对于部署到边缘设备比较有价值。5.2 与Transformer结合的尝试YOLO和Transformer结合是最近比较热的方向。我试过在YOLOv8的骨干网络后面加一个轻量级的Transformer Encoder用自注意力来增强全局特征。实测下来在手机检测任务上加了Transformer之后mAP0.5:0.95能提升1.5个点左右但推理速度会下降约20%。如果要做这个改进我建议用MobileViT或者EfficientFormer这类轻量级Transformer结构不要直接用标准的Transformer Encoder参数量太大了。另外Transformer的层数不要太多1到2层就够了多了容易过拟合。还有一个思路是用Transformer来做后处理比如用DETR式的集合预测替代NMS。但这个改动比较大需要重新设计损失函数和训练策略不太适合在2800张这种小数据集上做。5.3 知识蒸馏在手机检测上的应用知识蒸馏是提升小模型精度的有效手段。思路是用一个大模型比如YOLOv8l作为教师模型一个小模型比如YOLOv8n作为学生模型让学生模型学习教师模型的输出分布。我试过在手机检测任务上做蒸馏学生模型的mAP0.5:0.95能从0.72提升到0.78左右效果还是比较明显的。蒸馏的关键是设计好蒸馏损失。我一般会用教师模型的soft label分类头的输出和回归头的输出作为监督信号让学生模型去拟合。蒸馏温度T一般设为2到4温度越高soft label越平滑学生模型学到的信息越多。但温度太高也会导致学生模型学不到细节需要根据实际情况调整。注意知识蒸馏需要同时加载教师模型和学生模型显存占用会翻倍。如果显存不够可以先把教师模型的输出保存下来再单独训练学生模型。5.4 部署与推理优化训练完的模型最终是要部署的。手机检测的部署场景通常有两类一类是服务端部署用GPU做批量推理另一类是边缘端部署用CPU或者NPU做实时推理。服务端部署我一般用TensorRT做优化。TensorRT可以把ONNX模型进一步优化推理速度能提升2到3倍。导出TensorRT引擎的命令如下yolo export modelbest.pt formatengine imgsz640 halfTruehalfTrue表示用FP16精度推理速度更快精度损失很小。如果对精度要求极高可以用FP32但速度会慢一些。边缘端部署我一般用ONNX Runtime或者NCNN。ONNX Runtime的兼容性最好支持多种硬件后端。NCNN在ARM CPU上的性能更好适合部署到树莓派这类设备上。如果设备有NPU比如瑞芯微的RK3588可以用RKNN做推理速度比CPU快很多。推理优化的另一个重点是输入尺寸。640x640是精度和速度的平衡点如果对速度要求更高可以降到416x416或者320x320但精度会有所下降。我实测下来320x320的推理速度是640x640的3倍左右但mAP0.5会下降5到8个点。具体用哪个尺寸需要根据实际场景的精度和延迟要求来权衡。6. 数据集扩展与长期维护建议6.1 如何持续扩充数据集2800张只是一个起点实际项目中数据集是需要持续扩充的。扩充的思路有两种一种是主动采集一种是被动挖掘。主动采集就是根据模型的bad case有针对性地去采集新数据。比如模型在暗光场景下漏检多那就专门去采集暗光场景的手机图像。这种方式的效率最高但需要人工判断哪些场景是薄弱环节。被动挖掘就是让模型在实际运行中不断收集数据然后人工筛选出置信度低的样本标注后加入训练集。这种方式适合已经部署上线的模型可以持续迭代优化。我一般会设置一个置信度阈值比如0.6低于这个阈值的检测结果会被保存下来定期人工审核。扩充数据集的时候要注意保持类别平衡和场景平衡。不要只采集某一类场景的数据否则模型会偏向这类场景其他场景的精度会下降。我一般会维护一个场景分布表每次扩充后更新一下确保各类场景的比例不要偏差太大。6.2 标注质量的控制与审核标注质量是数据集的生命线。2800张图像如果标注质量参差不齐训练出来的模型精度会大打折扣。我建议建立一套标注审核流程至少包括三个环节标注、初审、终审。标注环节由标注员完成要求标注框紧贴目标边缘不多标不漏标。初审环节由另一个标注员交叉检查重点检查是否有漏标和明显错误的框。终审环节由项目负责人抽查抽查比例不低于10%。审核的标准我一般会量化为几个指标框的IoU与真实框的IoU不低于0.85漏标率不高于1%误标率不高于0.5%。如果达不到这些指标就需要重新标注或者修正。提示标注工具我推荐用LabelImg或者CVAT。LabelImg轻量简单适合小规模标注CVAT功能强大支持团队协作和自动标注适合大规模项目。6.3 数据集版本管理与复现性保障数据集版本管理经常被忽略但它的重要性不亚于模型训练本身。没有版本管理你很难复现之前的实验结果也很难追踪每次修改带来的影响。我一般用DVC来做数据集版本管理。DVC的原理是用Git管理代码和元数据用远程存储管理大文件。每次修改数据集后用dvc add命令生成一个新的版本然后提交到Git。这样任何时候都可以通过dvc checkout回滚到指定版本。除了版本管理复现性保障还包括随机种子的固定。YOLOv8的训练过程中有很多随机操作比如数据增强、权重初始化、batch采样等。如果不固定随机种子每次训练的结果都会有差异。我一般会在训练脚本开头加上import torch import numpy as np import random seed 42 torch.manual_seed(seed) torch.cuda.manual_seed_all(seed) np.random.seed(seed) random.seed(seed) torch.backends.cudnn.deterministic True torch.backends.cudnn.benchmark False这样每次训练的结果基本一致方便对比不同改进方案的效果。但要注意cudnn.deterministicTrue会降低训练速度如果对速度要求高可以设为False但结果会有轻微波动。6.4 从单类别到多类别的扩展思路手机检测目前是单类别但如果你的应用场景需要区分手机的品牌、型号或者状态那就需要扩展到多类别。扩展的思路有两种一种是直接增加类别把品牌或型号作为类别标签另一种是保持单类别检测再加一个分类网络做二次判断。直接增加类别的方式比较简单但需要重新标注所有数据工作量很大。而且如果某些品牌的样本很少模型很难学好。我一般建议样本量少于500张的类别不要单独设类可以归到其他类别里。两阶段的方式是先检测手机再对检测到的手机区域做分类。这种方式的好处是检测和分类可以独立优化分类网络可以用更大的数据集训练。缺点是推理速度会慢一些因为要跑两个模型。如果对速度要求不高这种方式更灵活。我个人更倾向于两阶段方式因为手机检测的数据集可以复用分类网络可以单独采集数据训练互不影响。而且分类网络可以随时更新不需要重新训练检测模型。7. 实际项目中的经验体会7.1 数据质量比数据数量更重要这个体会是我做了多个目标检测项目之后最深的感受。2800张精标的数据训练出来的模型比10000张粗标的数据要好得多。我见过太多人为了追求数据量用自动标注工具批量生成标注结果标注框歪歪扭扭模型学出来的框也是歪的。精标的核心是框要贴合目标边缘。手机这个目标边缘比较清晰标注的时候要沿着手机的外轮廓画框不要留太多空白也不要切掉边缘。如果手机有保护壳框应该包含保护壳如果手机屏幕和机身颜色差异很大框应该包含整个机身。另外标注的一致性也很重要。同一批数据里不能有的框包含保护壳有的不包含。这种不一致会让模型困惑降低精度。我一般会在标注前写一份标注规范文档明确各种边界情况的处理方式标注员按照规范执行。7.2 小数据集训练的关键是迁移学习2800张数据在目标检测领域算是小数据集从零训练很难收敛到理想效果。迁移学习是小数据集训练的关键。我试过从零训练和迁移学习的对比迁移学习的mAP0.5比从零训练高15到20个点差距非常明显。迁移学习的核心是选择合适的预训练模型。YOLOv8在COCO数据集上预训练的权重已经学到了丰富的通用特征这些特征对手机检测也是有效的。所以直接用COCO预训练权重做初始化然后在自己的数据集上微调是最省事也最有效的方式。微调的时候要注意学习率的设置。预训练权重已经学得很好微调的时候学习率不能太大否则会破坏预训练学到的特征。我一般会把初始学习率设为0.001比从零训练时的0.01小一个数量级。7.3 模型部署才是真正的考验训练出一个高精度的模型只是第一步部署才是真正的考验。我见过太多模型在测试集上mAP很高但部署到实际场景中效果大打折扣。原因通常是训练数据和实际场景的数据分布不一致。解决这个问题的办法是在训练数据中尽可能覆盖实际场景的各种情况。比如实际场景有逆光、暗光、雨雾等条件训练数据中就要有对应的样本。如果实际场景的数据很难采集可以用数据增强来模拟比如用亮度调整模拟暗光用对比度调整模拟逆光。部署后的监控也很重要。我一般会在部署后持续收集推理结果定期分析bad case然后把bad case加入训练集重新训练。这种迭代优化的方式能让模型越来越适应实际场景。7.4 最后分享一个小技巧如果你在训练过程中发现模型对某个特定场景的检测效果特别差比如对暗光场景漏检严重但又没有足够的暗光样本可以试试用GAN生成一些暗光图像。我试过用CycleGAN做光照转换把正常光照的图像转换成暗光图像然后加入训练集。实测下来暗光场景的mAP能提升5到8个点效果还是比较明显的。当然GAN生成的图像质量参差不齐需要人工筛选。我一般会生成一批然后挑出质量好的加入训练集。这个方法的成本比实际采集暗光数据低很多适合快速补充特定场景的样本。这个数据集后续还可以这样扩展加入手机屏幕状态的标注比如屏幕亮/灭、是否有裂纹等这样就能用于二手手机质检场景。或者加入手机品牌和型号的标注用于手机回收分类。扩展的方向取决于你的实际应用需求数据集本身只是一个起点。
返回列表