做目标检测Object Detection这活儿前前后后折腾了不少项目从学术竞赛到工业落地都碰过。它是深度学习里我做过最多的一类视觉任务也是落地最广的方向之一输入一张图像输出每个目标的类别和位置框Bounding Box。说白了就是让模型回答两个问题图片里有什么分别在哪。这篇内容不打算复述课程PPT而是把我在算法选型、数据准备、训练调参到问题排查这条完整链路里积累的经验写出来尤其是那些网上不太会说但实际特别重要的细节。不管你是刚接触深度学习的学生、准备拿目标检测做本科毕业设计还是要在实际项目里落地检测模型这篇都适用。我见过不少人一上来就怼着某个YOLO版本调参调了一周也没搞明白为什么效果不行。其实多数问题都出在更底层的地方数据质量、标注一致性、评价指标的理解、模型和场景是否匹配。这篇文章我把这些环节逐一拆开讲尽量说人话把我踩过的坑和验证过有效的做法都写在里面。1. 目标检测到底在解决什么问题1.1 从分类到检测任务本质先回到任务本身。图像分类Image Classification只需要回答“这张图里是什么”模型输出一个全局类别标签就行。目标检测难在“定位分类”的组合图像里通常有多个目标每个目标的位置不一样尺寸不一样甚至相互遮挡。模型要同时预测出每个目标在哪坐标框、它是什么类别置信度这就比单纯分类复杂了一个量级。举个例子把分类理解成“你远远看见一群人能说出其中有没有你的朋友”那检测就是“你必须指出你朋友在第几排第几个还要画出他大概的轮廓”。这一步对模型的要求是既要懂全局语义又要做局部精确定位。从数学表示上看检测模型的输出一般是一个变长的列表每个元素包含五部分[x_center, y_center, width, height, class_score]或者是左上角右下角坐标加类别得分。变长是因为图像里目标数量不确定。这个“可变长度输出”也决定了检测网络的head部分不能像分类任务那样简单接一个全连接层而是要通过anchor、proposal或者query机制来设计输出结构。理解了这一点后面看各种检测算法的设计就顺了。1.2 两大思路的博弈两阶段和单阶段目标检测算法的发展脉络基本就是一条“精度和速度互相拉扯”的历史。早期以R-CNN为代表的两阶段Two-stage算法干了一件事先用区域提议Region Proposal找出大概可能含目标的候选框再用CNN对候选框逐个做分类和回归。思路直觉、精度高但慢到让人崩溃因为在当时要对一张图的2000多个候选区域都过一遍网络。Faster R-CNN的诞生是个转折点。它引入Region Proposal NetworkRPN把“找候选框”这个步骤也塞进神经网络里让候选框生成和特征提取共享卷积特征。这样一来两阶段算法在精度和速度之间找到了比较好的平衡。哪怕放到今天Faster R-CNN的检测精度在不少数据集上依然是强基线尤其适合小目标密度高、类别区分度低的场景。另一条路线是单阶段One-stage代表就是YOLO和SSD。核心思路是抛弃“先提议后分类”的两步走直接在特征图上铺满预定义的锚框一步输出类别和偏移。它的优点非常直观速度快结构简单容易工程部署。早期单阶段算法的短板是精度不如两阶段尤其是小目标。后来YOLO系列通过多尺度预测、更好的数据增强、更强的backbone一路追赶到了YOLOv8这个时代单阶段在大部分常规场景下已经能和两阶段打得有来有回甚至在速度和部署友好度上全面胜出。选型建议比较现实如果是学术实验、追求极致精度、目标密集且小两阶段依然是可靠的选择如果是工程落地、实时视频流、边缘设备单阶段几乎是不二之选。说白了单阶段是现代工业界的宠儿但理解两阶段的设计思想对做检测的人来说依然是基本功。1.3 后起之秀Transformer把检测做成了端到端2020年DETRDetection Transformer的出现给目标检测带来了完全不同的视角。它不去设计锚框也不做候选区域而是把检测当成一个“集合预测问题”模型直接输出一个固定大小的预测集合用匈牙利算法在预测框和真实框之间做最优匹配然后计算损失。这种思路把检测流程简化成了“一个backbone 一个Transformer 一个FFN”去掉了NMS、Anchor等一堆后处理和预设。DETR很优雅但也有明显痛点训练收敛极慢小目标检测效果一般。这里就要提到热词里的Deformable DETR。它用可变形注意力Deformable Attention代替标准自注意力每层只关注少量关键采样点而不是在所有空间位置上做全局注意力同时把多尺度特征融合进来。这个改进让收敛速度大幅提升小目标检测能力也明显增强算是Transformer检测派里目前在工程和学术上最有生命力的方向之一。我的看法是DETR/Meta架构代表了一种“简化检测流程”的趋势尤其是它告别了大量手工设计的组件的做法让整个系统更干净。但从部署角度看Transformer结构在移动端和工业设备上依然不算友好计算量偏大、显存占用高所以目前工业落地里还是CNN派的YOLO系列占据绝对主导。对初学者理解Transformer检测的价值更多在于打开思路而不一定是你第一个上手的项目选择。2. 模型选型怎么做2.1 主流模型实测对比选型是很多人第一步就会卡住的地方。我自己的选择依据有这么几个任务精度基线、算力预算、部署目标、数据规模。下面这个表是我在多个项目里实测下来的大致感受注意数值只是量级参考因为不同数据集、不同训练配置结果差异会很大但它能反映模型之间的相对关系。模型范式精度表现推理速度显存占用部署友好度适用场景Faster R-CNN两阶段强慢高中高精度需求、小目标密集场景SSD单阶段中快中高实时性要求高、类别少YOLOv5/v8单阶段强很快中低高通用检测、工业落地第一选择DETRTransformer中上较慢很高低科研、流程简化探索Deformable DETRTransformer强中高低强精度、大模型离线推理场景从我的经验看如果你没有特殊理由新项目优先试YOLOv8是最稳的起手式。它的生态好、文档全、社区活跃训练推理一条龙扩展性也不错。如果你发现YOLOv8在特定场景下精度不够再往Faster R-CNN或者Deformable DETR方向做对比实验这样效率最高。2.2 轻量模型和边缘部署热词里有一条“macs仅5mb的目标检测模型”这是很多人在关注的方向。要提醒一下5MB通常说的是模型权重文件大小或者参数量而MACs乘加运算次数衡量的是计算量两者不是一回事。一个模型可以很小但跑得很慢也可以参数多但计算量不算离谱。选轻量模型时要同时关注参数量影响内存占用、FLOPs/MACs影响推理时延、实际FPS在目标设备上实测。轻量化检测方案里NanoDet、YOLOv5n/v8n、EfficientDet-Lite、MobileNet-SSD 是比较常见的选项。NanoDet的思路很值得学习用轻量backbone、去掉NMS、减少head层计算量专为移动端CPU/嵌入式设备设计。我自己在树莓派和RK3588这类设备上实测过v8n配合TensorRT或者RKNN工具链能做到可用的实时帧率。轻量模型能保持多少精度关键在两点一是输入分辨率太低什么都看不清二是训练策略小模型更容易欠拟合需要更多数据增强和更长的训练周期。如果数据量充足还可以用大模型蒸馏知识蒸馏的方式把YOLOv8m的检测能力蒸馏到v8n里这是低成本换取精度提升的有效手段。2.3 多尺度与多模态特殊场景下的选型思路目标检测现在早就不是只用在普通RGB图片上了。热词里能明显看到三类趋势三维目标检测、多模态微调目标检测、开放词汇目标检测。三维目标检测主要用在自动驾驶和机器人领域输入通常是激光雷达点云或者“图像点云”的融合数据输出的是目标的3D包围框长宽高、中心点、朝向角。代表性工作有PointPillars、SECOND、CenterPoint等。这类任务和2D检测最大的区别在于要同时预测深度信息和朝向对传感器的标定和数据的时空对齐要求很高。多模态微调检测是近年的热门方向比如“视觉语言模型检测器”通过文本指引模型检测开放类别目标这就是开放词汇目标检测Open-Vocabulary Detection的思路代表工作有GLIP、Grounding DINO等。这类模型的优势是你不再需要为每类目标都准备大量标注数据只需要一个文本提示词模型就能尝试找到对应目标。在实际项目里它特别适合做“预标注工具”先自动标一遍再人工修正能省下大量标注时间。选型思路要对应场景走不要拿着一套模型套所有业务无人机航拍、遥感影像这种小目标居多的场景优先考虑多尺度能力强的模型并配合切图推理实时视频流监控考虑YOLO系列轻量版本加硬件加速自动驾驶等强空间理解需求就该看三维目标检测方案。3. 数据集与训练细节3.1 数据的三个坑标注、格式、分布和很多人想的不一样目标检测项目里占用时间最长的往往不是调模型而是整理数据。我做过一个鸟类目标检测的项目公开数据集覆盖的场景和我的摄像头视角差别很大最后只能自己采集标注前后花了快两周才把数据规整好。所以别指望拿个公开数据集直接训练就能解决你的所有问题数据分布不一致会让模型上线后效果大打折扣。数据标注工具有很多LabelImg、Labelme、X-AnyLabeling、Roboflow都常用。X-AnyLabeling现在比较流行它支持AI预标注能先用一个现成模型把框打出来人工再做修正。这个流程在大批量数据上能节省80%的时间强烈推荐。标注格式是新手最容易踩的坑。常见的有三种Pascal VOC用的是XML文件每张图对应一个XMLCOCO用的是JSON文件所有标注集中在一个大JSON里YOLO用的是TXT文件每张图对应一个TXT每行是“类别ID 中心点x 中心点y 宽 高”并且坐标是归一化到0到1的。很多模型代码库只认其中一种格式转换格式时坐标计算错误是高频bug尤其是从XML转到YOLO TXT时归一化坐标偶尔有人忘了除以图片宽高导致训练直接崩掉或者loss爆炸。数据分布的问题是隐性的类别不均衡比想象中常见得多。比如“正常零件”占了90%“瑕疵零件”只占10%如果不做处理模型很容易把瑕疵漏检。常用处理方法有难例挖掘、类别加权损失、以及针对少数类做数据增强。更实际的做法是训练完先看每个类别的AP把AP明显偏低的类别作为重点补充数据的目标而不是盲目追求总量。3.2 训练配置从损失函数到超参数目标检测的损失函数通常由三部分组成分类损失判断类别对不对、定位损失判断框准不准、置信度损失判断前景背景视模型架构而定。分类损失常用交叉熵或其变体Focal Loss就是用来解决正负样本极度不均衡的。定位损失常用Smooth L1或者CIoU Loss。CIoU这类基于IoU的损失直接优化“框的重合程度”比单纯回归坐标更符合检测的目标是目前主流选择。超参数方面我对新手的核心建议是先别乱动用模型默认配置跑通一条流程再逐步调整。imgsz输入分辨率640是目前性价比最高的默认值。如果你主要检测小目标可以试试960甚至1280但训练和推理时间会显著上升。batch_size取决于显存尽量设到显存能承受的最大值。epoch常规数据集100到300之间够用重点看验证集mAP是否还在上升。learning_rate一般从0.01或0.001开始配合cosine schedule或线性warmup。YOLO系列自带自适应学习率策略不太需要手动干预。anchor参数如果使用Anchor-Based模型可以先在自己的数据集上用K-Means重新聚类出合适的锚框尺寸能加快收敛。Anchor-Free模型则不需要关注这一点。数据增强在目标检测里权重极高。YOLO系列自带的Mosaic增强把四张图拼成一张对提升小目标检测特别有效因为拼接后目标尺度分布被拉宽了。随机仿射变换、HSV色域扰动、随机翻转都是标配。但要注意增强太猛也会带来副作用比如遥感图像和文字检测这类对方向敏感的任务就不能随便做90度旋转。训练之前一定要先选好预训练权重。用COCO训练好的权重做迁移学习能大幅加快收敛尤其是在数据量不大时。如果从零开始训练同样的数据量下效果通常差不少。这背后的原因很直观模型已经在海量图像上学到了通用的纹理、边缘和形状特征你要做的只是让它“适应”你自己的数据分布。3.3 评价指标怎么看检测任务里最常用的指标是mAPmean Average Precision。这里容易懵的是它有两种常见版本mAP0.5预测框和真实框的IoU大于0.5就算检测正确。这个标准比较宽松直观反映“找没找到”。mAP0.5:0.95把IoU阈值从0.5到0.95每隔0.05取一次计算多个阈值下的平均。这个标准更严格要求框得又准又稳。论文里说的COCO mAP默认指的就是0.5:0.95。我见过不少项目mAP0.5刷到0.9以上但一上到0.5:0.95就掉到0.5。这说明模型能找到目标但边框定位精度不够。如果你的业务对框的贴合度要求高比如机械臂抓取、医学图像切分那么更该关注0.5:0.95这个指标。落到实际我建议同时打印每类的Precision和Recall。Precision低说明误检多模型把一堆背景当成了目标Recall低说明漏检多模型漏掉了很多真目标。两种症状对应的优化思路完全不同前者要加负样本、调低置信度阈值、检查标注是否有背景混淆后者要补数据、加强增强、调低IoU阈值或者提高输入分辨率。4. 一次完整的最小训练流程4.1 环境准备目标检测的工程实践我建议首选PyTorch Ultralytics YOLOv8这套组合它把训练、验证、导出都封装得比较顺手。环境配置看似麻烦但只要注意版本匹配就能少走很多弯路。先安装Anaconda然后创建虚拟环境conda create -n yolo python3.10 -y conda activate yolo接着装PyTorch。这里最容易出问题的是CUDA版本和PyTorch版本不匹配。先运行nvidia-smi查看你的驱动支持的CUDA版本再到PyTorch官网选择对应命令。以CUDA 11.8为例pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118然后用python -c import torch; print(torch.cuda.is_available())验证是否能用GPU。输出了True就说明环境OK。如果这一步输出False大概率是CUDA版本或驱动问题和模型代码关系不大。最后安装ultralytics包pip install ultralytics4.2 准备自定义数据集用一个最小示例来演示假设你只需要检测“鸟”和“无人机”两类目标。数据集目录结构按YOLO规范来图像放在images/train和images/val标注TXT放在labels/train和labels/val。每个TXT文件名和对应图片名保持一致。然后写一个数据配置文件bird_uav.yamlpath: /your/project/dataset train: images/train val: images/val nc: 2 names: [bird, uav]第一次跑不建议一上来就上全量数据。每类先标50到100张图共100到200张图左右把整个训练流程跑通确认没问题再逐步加数据。这个习惯能帮你快速暴露代码、格式、路径方面的问题而不是等半天训练完才发现数据集有问题。4.3 训练验证推断训练命令非常简洁yolo detect train databird_uav.yaml modelyolov8s.pt epochs100 imgsz640 batch16这里yolov8s.pt是COCO预训练权重。从v8s开始跑是相对平衡的选择显存占用不大精度也不错。训练过程中每个epoch结束都会在验证集上算mAP正常情况下loss会逐步下降mAP会逐步上升。训练完成后权重保存在runs/detect/train/weights/best.pt。验证看看效果yolo detect val databird_uav.yaml modelruns/detect/train/weights/best.pt做一次单张图片推理yolo detect predict modelruns/detect/train/weights/best.pt sourcetest.jpg saveTrue跑完打开保存的预测图很多时候一眼就能看出问题有的框偏大、有的目标漏检、有的把树干当成了鸟。这一步比任何指标都直观。我现在的习惯是训练完不只看mAP一定会抽样看几百张验证集图片的预测结果根据坏样例判断下一步怎么优化。5. 实战问题与排查经验5.1 小目标检测差小目标检测差是反馈率最高的问题。无人机航拍里的行人、工厂监控里的微小缺陷、遥感图里的小船都属于这一类。小目标之所以难根本原因是信息量少一个只有10像素大小的目标经过backbone多次下采样之后在深层特征图上可能只剩一两个像素甚至直接被“抹掉”了。模型缺少足够的信息去分类和定位。解决思路有几种我按见效程度排列提高输入分辨率从640提到1280对小目标AP的提升一般立竿见影代价是训练和推理变慢。多尺度训练和测试训练时随机用不同分辨率推理时把图像分成几块分别检测再合并就是常见的SAHI切图方案对超大图和极小目标效果很好。利用P2层特征许多YOLO版本默认从P3层开始检测下采样8倍的输出对极小目标不够。可以修改模型结构把P2层下采样4倍加进来精度会有所提升但显存占用也会增加。数据侧增强在训练时对原图做Copy-Paste把小目标复制多份、在不同位置多次出现相当于变相增加小目标样本数。另外要注意的是NMS抑制。小目标靠得近时NMS容易把正确的框抑制掉可以适当降低NMS的IoU阈值或者改用Soft-NMS。5.2 训练不收敛或过拟合训练不收敛通常有几个表现loss一直不下降或者直接变成NaN。我遇到最多的是学习率太大导致loss震荡或爆炸。解决方法很简单把学习率调小一个量级或者把warmup轮数加长。另一个常见原因是数据标注本身有问题比如标注框坐标越界、类别ID超出范围、某些图没有任何标注但代码默认当作背景。训练前先写个脚本把所有标注过一遍把坐标小于0、宽高为0的标注都筛出来能省掉无谓的返工。过拟合的表现是训练集loss和mAP都很高验证集却上不去。这在数据量少的时候太常见了。应对办法加数据增强Mosaic、MixUp、随机擦除、加正则化weight decay调大一点、用早停patience设为30左右、或者在ImageNet/COCO预训练权重基础上做fine-tune。如果过拟合严重优先考虑的不是模型变小而是加数据哪怕是弱标注数据也能带来改善。5.3 显存不足与推理太慢显存不足CUDA OOM在训练和推理阶段的解决办法不同。训练阶段优先降低batch_size如果降得太多影响收敛就开梯度累积相当于每几步累积梯度后再更新参数。另一个有效手段是开启混合精度训练AMPultralytics默认已经开了能减少约一半显存占用。推理阶段显存不足一般是因为同时处理太多图片或者分辨率太高缩小batch或分辨率就能解决。推理太慢则是部署问题。模型剪枝、量化、知识蒸馏、TensorRT加速是常用的手段。YOLOv8可以直接导出TensorRT引擎yolo export modelbest.pt formatengine imgsz640 halfTrueTensorRT的优化非常明显实测在NVIDIA边缘设备上通常能比PyTorch直接推理快2到5倍。如果部署在ARM CPU或NPU上需要把模型转成ONNX再转对应的格式。轻量模型加硬件加速才是边缘设备上实时检测的最终解。排查问题这块我整理了一个速查表平时遇到问题先翻一遍比盲调省时间得多现象常见原因排查方向训练loss变成NaN学习率过大或数据异常调小学习率、检查标注是否有空/越界框验证集mAP高但实际很烂数据分布不匹配采样实际场景图片回灌测试集小目标全漏检输入分辨率低、深层特征丢失提高分辨率、加P2层、SAHI切图框偏移严重定位损失权重低或标注不准增大CIoU权重、重新检查标注推理速度慢后处理多、硬件加速没开导出TensorRT/ONNX、换轻量模型反复检测到背景负样本欠缺采集纯背景图加入训练集最后再分享一个我个人很受用的经验做目标检测不要迷信单一指标。mAP高不等于方案能上线模型在验证集上表现好不代表到了现场就不会翻车。每轮训练完我都会做一次“坏案例巡检”把误检和漏检的图片导出按场景归类看是天气问题、视角问题还是类别混淆问题然后有针对性地补数据。这个方法听起来土但比反复调参有效得多。目标检测是个系统工程把数据、模型、训练、部署这条链路都理顺了效果自然就出来了。