1. 从 YOLO 的版本演进看目标检测的工程化路线
1.1 为什么一个检测框架值得反复“考古”
YOLO 这个词在圈子里出现的频率太高了,高到很多人第一次接触目标检测就是拿它跑通一个摄像头 demo。但真正在项目里落地过的人都知道,版本选型这件事远比“装个包跑起来”复杂。我见过太多团队在 v5 和 v8 之间反复横跳,也见过有人拿着 v3 的配置文件去训 v8 的权重,最后 loss 不降反升还找不到原因。
把历代版本捋一遍,本质上是在梳理一条工程化路线:从“能检测”到“检测得准”,再到“部署得动”,最后到“不用写 anchor、不用写 NMS、甚至不用写后处理”。每一代的变化都不是拍脑袋,而是被上一代在实际场景里暴露的问题逼出来的。你理解了这条线,选型的时候就不会只看 mAP 数字,而是会去看输入分辨率、后处理复杂度、导出格式、量化友好度这些真正影响交付的东西。
这篇文章面向的是准备把 YOLO 用进真实项目的人——不管你是做学生专注度检测、交通事故分析,还是拿 D435i 做测距、拿 AGX Orin 做边缘部署。我会把每个版本的核心改动、适用场景、踩坑点讲清楚,最后给一套可以直接抄的选型思路。
1.2 一条主线:从“回归框”到“端到端”
YOLO 最开始的卖点就一句话:把检测当成回归问题,一个网络一次前向出结果。v1 的时候这个想法很激进,把图片切成 7×7 的格子,每个格子预测两个框,直接回归坐标和类别。速度快得离谱,但小目标和密集目标一塌糊涂,因为一个格子只能出一个类。
v2 开始打补丁:加了 anchor、加了 BN、用了更高分辨率分类器做预训练。v3 是真正封神的一代,FPN 式的多尺度预测、更好的 backbone、独立的类别预测,让它在速度和精度之间找到了一个甜点。v4 是“集大成”,把当时能用的 trick 全塞进去,CSP、Mish、CIoU、SAT 自对抗训练,工程上很扎实但创新点偏少。
v5 是工程化分水岭,Ultralytics 把它做成了一个开箱即用的框架,数据配置、训练、导出、推理一条龙,这也是为什么现在还有大量项目跑在 v5 上。v6/v7 更像是社区维护的过渡版本,v7 的 E-ELAN 和辅助训练头在精度上有提升,但生态没跟上。
v8 是又一次范式转变:anchor-free、解耦头、TaskAlignedAssigner,分类和回归分开处理,对小目标和密集场景明显更友好。v9/v10 继续往端到端走,v10 直接砍掉了 NMS,靠一致性双分配做无 NMS 推理,部署链路一下子短了很多。v11 则是把前几代的模块做了系统化整合,在精度和速度上做了更细的平衡。
这条主线的终点很清晰:让检测这件事从“一堆超参和手工后处理”变成“一个可以端到端导出、量化、部署的模块”。你选版本的时候,其实是在选你愿意为这个终点付出多少迁移成本。
2. 历代版本核心改动与适用场景拆解
2.1 v1 到 v3:奠定“单阶段检测”的基本盘
v1 的结构现在看很朴素:24 个卷积层加两个全连接,输入 448×448,输出 7×7×30。30 是 2 个框各 5 个值(x, y, w, h, confidence)加 20 类条件概率。损失函数是坐标误差、置信度误差、分类误差的加权和,坐标用根号处理让大框和小框的误差尺度接近。
问题也很明显:每个格子只能预测一个类别,两个物体中心落在同一格就废了;小目标因为下采样太狠基本检测不到。v2 的改进很直接:加 anchor 让每个格子可以预测多个不同形状的框,加 BN 让训练更稳,用 448×448 的分类预训练再 fine-tune 检测,mAP 从 63.4 拉到 78.6。
v3 是我个人认为最值得反复读的一代。它做了三件事:第一,backbone 换成 Darknet-53,残差结构让网络可以更深;第二,多尺度预测,在 13×13、26×26、52×52 三个尺度上分别出框,小目标终于有救了;第三,类别预测从 softmax 改成 logistic,支持多标签。损失函数里分类用 BCE,坐标用 MSE,置信度也用 BCE,正负样本用 ignore 阈值处理。
注意:v3 的 anchor 是用 k-means 在 COCO 上聚出来的,如果你换数据集,一定要重新聚类。我见过有人直接拿 COCO 的 anchor 去训工业缺陷数据,小目标召回率直接掉一半。
v3 的适用场景到现在还没过时:算力受限的边缘设备、需要快速出原型的项目、教学演示。它的结构图清晰,改起来方便,很多“YOLO 算法讲解 PPT”都是拿 v3 当模板。
2.2 v4 到 v7:工程 trick 的堆叠与生态分化
v4 的作者是 AlexeyAB,他的风格就是“把能用的都加上”。CSPDarknet53 做 backbone,SPP 加 PANet 做 neck,Mish 激活,CIoU 损失,Mosaic 数据增强,SAT 自对抗训练,DropBlock 正则。这些东西单拎出来都不是他发明的,但组合在一起效果确实好,在 COCO 上 AP 到了 43.5%。
v4 的工程价值在于它把训练技巧系统化了。Mosaic 增强把四张图拼成一张,变相增大了 batch size 和场景多样性;CIoU 把框的长宽比和中心点距离都考虑进去,收敛更快。但 v4 的代码库比较重,依赖多,导出 ONNX 的时候经常遇到算子不支持的问题。
v5 是 Ultralytics 的作品,它的核心不是算法创新,而是工程体验。一个 YAML 文件定义模型结构,一个 data.yaml 定义数据集,命令行一行训完,导出支持 ONNX、TensorRT、CoreML、TFLite。它的自适应 anchor 计算、自动学习率调度、混合精度训练,让新手也能训出不错的结果。
v5 的争议也在这:它太“黑盒”了,很多人训完不知道发生了什么。但站在交付角度,v5 的生态是最成熟的,文档全、issue 多、社区脚本多,遇到问题基本能搜到答案。
v6 是美团出的,主打重参数化,训练时用多分支,推理时合并成单路,速度有优势。但社区活跃度一般,资料少。v7 是 v5 和 v6 的融合,E-ELAN 结构、辅助训练头、模型缩放策略,在精度上比 v5 高一点,但生态没起来,用的人不多。
实操心得:如果你现在要开一个新项目,v5 和 v8 是首选。v5 适合快速验证和已有生态依赖的场景,v8 适合对精度和小目标有要求的场景。v6/v7 除非你有特殊需求,否则不建议新项目入坑。
2.3 v8 到 v11:anchor-free 与端到端的两次跃迁
v8 的变化是结构性的。它把 anchor 去掉了,改成 anchor-free 的预测方式,每个位置直接预测框的中心偏移和宽高。检测头解耦成分类分支和回归分支,分类用 BCE,回归用 DFL 加 CIoU。正负样本分配用 TaskAlignedAssigner,根据分类和回归的一致性来选正样本。
这些改动带来的直接好处是小目标和密集场景的召回率提升。我实测过一个学生专注度检测的场景,同样数据集 v5 的 mAP@0.5 是 0.82,v8 能到 0.87,尤其是后排小目标的人脸和手部动作,v8 明显更稳。
v8 的另一个优势是任务覆盖全:检测、分割、姿态、分类、跟踪都有官方模型。你要做实例分割,直接拿 v8-seg 的权重 fine-tune 就行,不用自己搭 mask head。导出方面,v8 对 ONNX 和 TensorRT 的支持很完善,动态 batch、动态尺寸都能处理。
v9 是 v8 的过渡版,主要改了可编程梯度信息,训练更稳,但生态没跟上。v10 是真正的端到端版本,它砍掉了 NMS,靠一致性双分配让网络自己学会去重。这意味着导出后的模型不需要后处理,推理链路更短,在 TensorRT 上延迟更低。
v10 的代价是训练更复杂,对数据质量要求更高。如果你的数据集标注噪声大,v10 的表现可能不如 v8。v11 则是把 v8 到 v10 的模块做了系统整合,在精度和速度上做了更细的平衡,官方给的模型谱系很全,从 n 到 x 都有。
| 版本 | 核心改动 | 适用场景 | 部署友好度 |
|---|---|---|---|
| v3 | 多尺度预测、Darknet-53 | 边缘设备、教学、快速原型 | 高,结构简单 |
| v4 | CSP、Mosaic、CIoU | 精度要求高的通用检测 | 中,依赖多 |
| v5 | 工程化框架、自适应 anchor | 快速验证、生态依赖 | 高,导出完善 |
| v8 | anchor-free、解耦头 | 小目标、密集场景、多任务 | 高,ONNX/TensorRT 完善 |
| v10 | 无 NMS 端到端 | 低延迟部署、链路简化 | 极高,无后处理 |
| v11 | 模块整合、精度速度平衡 | 新项目首选 | 高,官方支持全 |
3. 从零跑通一个 YOLO 项目的完整实操
3.1 环境搭建:PyCharm 与 AGX Orin 两条路线
先说 PyCharm 这条线,适合本地开发和调试。我的习惯是先用 conda 建一个干净环境,Python 版本选 3.9 或 3.10,太新太旧都容易遇到包兼容问题。
conda create -n yolo python=3.10 conda activate yolo pip install ultralyticsUltralytics 这个包把 v5/v8/v11 都整合进去了,装一个就能用。如果你要跑 v5 的原版,得单独 clone 仓库装依赖,那个 requirements 比较老,经常需要手动降级 numpy 和 opencv。
PyCharm 里配置解释器的时候,记得把 conda 环境的 python 路径选对。跑训练脚本的时候,工作目录要设成项目根目录,不然数据集路径会找不到。我踩过的坑是 PyCharm 默认的工作目录是脚本所在目录,而 Ultralytics 的 data.yaml 里路径是相对项目根的,结果就是“dataset not found”。
再说 AGX Orin 这条线,这是边缘部署的典型场景。Orin 是 ARM 架构,CUDA 和 PyTorch 的版本必须和 JetPack 匹配。我的建议是直接用 NVIDIA 提供的 l4t-pytorch 镜像,省去编译 PyTorch 的麻烦。
# 在 Orin 上检查 JetPack 版本 cat /etc/nv_tegra_release # 根据版本选对应的 l4t-pytorch 镜像 docker pull nvcr.io/nvidia/l4t-pytorch:r35.2.1-pth2.0-py3Orin 上跑 YOLO 的关键是 TensorRT 加速。PyTorch 直接推理只能跑到十几 FPS,导出成 TensorRT engine 后能到 60 FPS 以上。导出的时候要注意精度选择,FP16 基本无损,INT8 需要校准集,精度掉多少取决于你的数据分布。
注意:Orin 上导出 TensorRT engine 时,如果用了动态尺寸,第一次推理会触发 engine 构建,耗时可能几分钟。建议在部署前先用固定尺寸构建好 engine,避免线上第一次请求超时。
3.2 数据集准备:标注、划分与配置文件
数据集这块,标注工具我用过 labelImg、CVAT、Roboflow。labelImg 最简单,但只支持矩形框;CVAT 支持分割、关键点,适合复杂任务;Roboflow 在线标注加增强一条龙,但免费版有额度限制。
标注格式上,YOLO 用的是 txt,每行class_id x_center y_center width height,坐标都是归一化到 0-1 的。这里有个容易错的地方:归一化是除以图片的宽和高,不是除以最大边。我见过有人统一除以最大边,结果框全偏了。
数据集划分一般是 8:1:1 或 7:2:1。小数据集建议用交叉验证,不然验证集波动很大。划分的时候要保证每个类别的样本在训练集和验证集里分布均匀,不然某些类别在验证集里一个都没有,mAP 算出来是 0。
data.yaml 的写法:
path: /home/user/datasets/mydata train: images/train val: images/val test: images/test nc: 3 names: ['person', 'phone', 'cup']nc是类别数,names的顺序必须和标注里的 class_id 对应。我踩过的坑是改了 names 顺序但没改标注,结果模型把人和杯子搞反了。
数据增强方面,YOLO 默认开了 Mosaic、HSV 抖动、随机翻转、缩放。如果你的场景对颜色敏感(比如交通灯检测),要把 HSV 的 h 分量关掉。如果目标有方向性(比如文字),随机翻转要慎用。
3.3 训练配置:超参、损失函数与训练技巧
训练命令很简单:
yolo detect train data=mydata.yaml model=yolov8n.pt epochs=100 imgsz=640 batch=16但背后的超参才是决定成败的东西。学习率默认是 0.01,用 SGD 优化器,cos 调度。小数据集建议降到 0.001,用 AdamW,收敛更稳。batch size 受显存限制,640 输入下 8G 显存大概能跑 batch 16,不够就开梯度累积。
损失函数这块,v8 之后是分类 BCE 加回归 DFL 加 CIoU。DFL 是把框的宽高离散成 16 个 bin,预测分布再求期望,比直接回归更稳。CIoU 考虑了重叠面积、中心距离和长宽比,收敛比 IoU 快。
训练过程中要盯几个指标:box_loss、cls_loss、dfl_loss、mAP50、mAP50-95。box_loss 不降说明回归有问题,可能是 anchor 不匹配或者学习率太大;cls_loss 不降说明分类难,可能是类别不平衡或者标注噪声;mAP 震荡说明验证集太小或者学习率调度有问题。
实操心得:训练前先用小学习率跑几个 epoch 看 loss 是否下降,这叫“学习率探测”。如果 loss 直接炸了,说明学习率太大;如果 loss 几乎不动,说明太小。我一般会跑一个 lr finder,让框架自动找最优学习率。
早停策略建议开,patience 设 20 到 30。如果验证集 mAP 连续 20 个 epoch 不提升就停,避免过拟合。模型保存选 best.pt 和 last.pt 都留着,best 用于推理,last 用于恢复训练。
3.4 导出与部署:ONNX、TensorRT 与边缘设备
导出 ONNX:
yolo export model=best.pt format=onnx imgsz=640 opset=12 simplify=Truesimplify会用 onnx-simplifier 把冗余算子合并,减小模型体积。opset版本要和推理引擎匹配,TensorRT 8 支持到 opset 17,但 12 最稳。
导出 TensorRT:
yolo export model=best.pt format=engine imgsz=640 half=True device=0half=True用 FP16,速度翻倍精度基本不掉。如果要 INT8,得提供校准数据,在 data.yaml 里指定。
在 D435i 这种深度相机上部署,流程是:RGB 图进 YOLO 出框,深度图取框内中值作为距离。这里要注意对齐,D435i 的 RGB 和深度是不同传感器,需要用 align 模块对齐到同一坐标系。不对齐的话,框的位置和深度值对不上,测距会偏。
在 Orin 上部署,我一般用 DeepStream 或者自己写 TensorRT 推理。DeepStream 适合多路视频流,自己写适合单路低延迟。自己写的话,预处理用 CUDA kernel 做 resize 和归一化,后处理用 GPU 做 NMS,整条链路都在 GPU 上,延迟能压到 10ms 以内。
4. 常见问题与排查技巧实录
4.1 训练不收敛、mAP 上不去怎么查
训练不收敛是最常见的问题,排查顺序我一般是这样:
第一,看数据。用脚本把标注框画到图上,肉眼检查有没有框偏了、类别错了、漏标了。我遇到过标注文件里坐标是像素值没归一化,训练 loss 直接 NaN。
第二,看学习率。太大 loss 震荡,太小 loss 不降。用 lr finder 跑一下,选 loss 下降最快那个点的一半。
第三,看 batch size。太小 BN 统计不准,训练不稳。如果显存不够,用梯度累积模拟大 batch。
第四,看预训练权重。从 COCO 预训练权重 fine-tune 比从零训快得多,mAP 也高。如果你从零训,需要更多数据和更长的 epoch。
第五,看类别平衡。如果某些类别样本极少,用 copy-paste 增强或者 focal loss。YOLO 默认的分类损失对不平衡数据有一定鲁棒性,但极端情况还是得处理。
mAP 上不去还有一个隐蔽原因:验证集和训练集分布不一致。比如训练集是白天,验证集是晚上,模型在验证集上表现差是正常的。这时候要做的是让训练集覆盖验证集的分布,而不是调模型。
4.2 导出 ONNX 报错、推理结果对不上
导出 ONNX 报错,最常见的是算子不支持。YOLO 里有些算子(比如 v8 的 DFL)在旧版 opset 里没有,需要升 opset 或者改结构。另一个原因是动态尺寸,如果导出时用了 dynamic,某些推理引擎不支持,改成固定尺寸就好。
推理结果对不上,一般是预处理不一致。PyTorch 推理时用的是 letterbox 填充,保持长宽比,填充灰色。如果你在 ONNX 推理时直接 resize,长宽比变了,框的位置就会偏。解决办法是把 letterbox 的参数也导出,推理时按同样方式处理。
还有一个坑是归一化。PyTorch 里是除以 255,如果你在推理时忘了这步,输入值域不对,输出全是乱的。建议把预处理写成一个函数,训练和推理共用,避免不一致。
4.3 边缘设备上的性能优化与踩坑
在 AGX Orin 上优化性能,几个关键点:
第一,用 TensorRT 而不是 PyTorch。PyTorch 的推理有框架开销,TensorRT 会把算子融合、选最优 kernel,速度差好几倍。
第二,用 FP16 或 INT8。FP16 基本无损,INT8 需要校准。校准集要从训练集里采样,覆盖各种场景,不然量化误差会集中在某些类别上。
第三,预处理和后处理也放到 GPU 上。CPU 做 resize 和 NMS 会成为瓶颈,尤其是多路视频流的时候。
第四,控制输入分辨率。640 和 1280 的速度差 4 倍,精度差多少取决于你的目标大小。如果目标在画面里占比大,640 够用;如果目标小,得上 1280。
注意:Orin 的功耗模式会影响性能。默认模式是 15W,性能受限。跑推理前用
nvpmodel切到 MAXN 模式,性能能提升 30% 以上。但功耗和发热也会上去,散热要做好。
4.4 常见问题速查表
| 问题现象 | 可能原因 | 排查方法 | 解决方案 |
|---|---|---|---|
| loss NaN | 学习率太大、数据有 NaN | 检查输入数据、降学习率 | 用 lr finder、检查标注 |
| mAP 为 0 | 类别不匹配、验证集为空 | 检查 data.yaml 和标注 | 对齐类别、重新划分 |
| 导出 ONNX 失败 | opset 不支持、动态尺寸 | 看报错算子、改 opset | 升 opset、固定尺寸 |
| 推理框偏移 | 预处理不一致 | 对比训练和推理的预处理 | 统一 letterbox 和归一化 |
| Orin 上速度慢 | 没用 TensorRT、功耗模式 | 看推理后端、查 nvpmodel | 导出 engine、切 MAXN |
| 小目标漏检 | 输入分辨率低、anchor 不匹配 | 看小目标召回率 | 升分辨率、换 v8/v11 |
5. 版本选型与项目落地的个人经验
5.1 什么场景选什么版本
如果你做的是教学演示或者快速原型,v3 或 v5 就够了。v3 结构清晰,改起来方便,适合讲原理;v5 生态好,一行命令跑通,适合出 demo。
如果你做的是工业检测、小目标密集场景,直接上 v8 或 v11。anchor-free 和解耦头对小目标更友好,多任务支持也全。v11 是官方主推,文档和模型谱系最全,新项目建议直接 v11。
如果你做的是低延迟部署,比如自动驾驶、机器人,v10 的无 NMS 端到端是首选。导出后没有后处理,链路短,延迟低。但训练难度高,数据质量要跟上。
如果你做的是多模态分析,比如“YOLO 目标检测 + 多模态 AI 分析”的交通事故检测,v8 的检测结果可以作为结构化输入,喂给后面的分析模块。v8 的导出格式标准,和下游模块对接方便。
5.2 迁移学习的几个关键决策
从 COCO 预训练权重 fine-tune 是标配,但有几个决策点:
第一,冻结哪些层。小数据集建议冻结 backbone 的前几层,只训 neck 和 head。大数据集可以全量 fine-tune。
第二,学习率怎么设。fine-tune 的学习率要比从零训小一个数量级,一般 0.001 起步。
第三,要不要改结构。如果类别数变了,改最后一层的输出维度;如果输入尺寸变了,改 imgsz 参数;如果场景特殊,可以加注意力模块,但要小心过拟合。
第四,数据增强怎么调。小数据集增强要强,大数据集可以弱一些。Mosaic 对小数据集提升明显,但对大目标可能有害,因为拼接后大目标被切碎了。
5.3 从检测到分割、姿态的扩展
YOLO 现在不只是检测。v8-seg 做实例分割,在检测头基础上加 mask 分支,输出每个实例的 mask。v8-pose 做姿态估计,输出关键点坐标。v8-cls 做分类,直接输出类别概率。
这些任务的训练流程和检测类似,只是数据集格式和损失函数不同。分割需要 mask 标注,姿态需要关键点标注,分类只需要类别标签。
扩展的时候要注意,多任务联合训练可以共享 backbone,但 head 要分开。如果任务之间差异大,联合训练可能互相拖累,这时候分开训再集成更好。
实操心得:做实例分割的时候,mask 的分辨率是原图的 1/4,小目标的 mask 会很粗糙。如果小目标分割要求高,要么升输入分辨率,要么用专门的分割模型。
5.4 一键部署脚本的写法与注意事项
一键部署脚本的核心是把环境检查、依赖安装、模型导出、服务启动串起来。我一般写成 shell 脚本,分步骤执行,每步都有日志和错误处理。
#!/bin/bash set -e # 检查 CUDA if ! command -v nvcc &> /dev/null; then echo "CUDA not found" exit 1 fi # 安装依赖 pip install ultralytics onnx onnxruntime-gpu # 导出模型 yolo export model=best.pt format=engine imgsz=640 half=True # 启动服务 python serve.py --engine best.engine --port 8080注意事项:set -e让脚本遇到错误就停,避免错误累积;导出 engine 的时候如果已经存在,要判断是否覆盖;服务启动前要检查端口是否被占用。
在 Orin 上,还要检查 JetPack 版本和 TensorRT 版本是否匹配,不匹配的话 engine 构建会失败。我一般会在脚本里加一个版本检查函数,不匹配就提示用户。
6. 几个真实场景的落地细节
6.1 学生专注度检测:小目标与遮挡的处理
学生专注度检测的难点是后排学生小、互相遮挡、光照变化大。我的做法是:输入分辨率上到 1280,用 v8m 或 v11m,backbone 容量够大能提取小目标特征。数据增强加随机遮挡,模拟互相遮挡的场景。后处理用 soft-NMS,避免遮挡时框被误删。
专注度判断不能只看检测框,还要结合头部姿态和眼睛开合。我的方案是 YOLO 出人脸框,裁出来送一个轻量分类网络判断专注/分心。这样检测和分类解耦,各自优化。
6.2 交通事故检测:多模态融合的思路
交通事故检测需要检测车辆、行人、交通灯,还要判断碰撞、逆行、违停。YOLO 负责出目标框和类别,后面的分析模块用规则引擎或时序模型判断事件。
多模态融合的关键是时间对齐。视频帧、雷达点云、GPS 数据的时间戳要对齐到同一时钟。YOLO 的检测结果按帧输出,和雷达点云做空间融合,能提升测距精度。
6.3 D435i 测距:对齐与滤波
D435i 的 RGB 和深度对齐用rs.align(rs.stream.color)。对齐后,检测框内的深度值取中位数,比取平均更抗噪。如果深度值缺失(比如反光表面),用周围有效值的均值填充。
测距精度受基线、距离、光照影响。1 米内精度能到几毫米,3 米外误差到几厘米。如果精度要求高,可以用多帧滤波,卡尔曼或者滑动平均。
6.4 食物卡路里检测:从检测到估算
食物卡路里检测的流程是:YOLO 检测食物类别和位置,根据框的大小估算体积,再乘以密度和热量密度。难点是框的大小和实际体积的关系,需要标定。
我的做法是放一个参照物(比如硬币)在画面里,用参照物的已知尺寸反推食物的实际尺寸。这样不同距离下都能估算。参照物检测也用 YOLO,单独训一个类别。
这个场景的精度有限,因为食物形状不规则、密度差异大。但作为粗略估算够用了,用户要的是量级正确,不是精确到卡路里。
7. 写在最后的一些零散经验
YOLO 的版本迭代很快,但核心思想变化不大:更好的特征提取、更合理的正负样本分配、更简洁的后处理。你抓住这条线,看新版本的时候就不会被各种名词绕晕。
实际项目里,版本选型只是第一步,数据质量、训练策略、部署优化才是决定成败的。我见过用 v3 做出很好效果的团队,也见过用 v11 但数据一塌糊涂结果没法用的。工具是死的,人是活的。
如果你刚开始入门,建议从 v8 或 v11 入手,生态好、文档全、遇到问题能搜到答案。跑通一个 demo 后,再回头看看 v3 的结构,理解一下检测的基本原理。这样既有了工程能力,也有了理论基础。
最后分享一个小技巧:训练的时候开 TensorBoard,把 loss、mAP、学习率、权重分布都画出来。很多问题在曲线上就能看出来,比看日志快得多。我一般会同时开两个终端,一个跑训练,一个盯 TensorBoard,有问题随时停。