拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

轻量型目标检测算法全解析:从骨干网络到端侧部署实践

轻量型目标检测算法全解析:从骨干网络到端侧部署实践

轻量型目标检测算法,这几年被行业里聊得非常多。我早期做端侧视觉项目时,最先跑的模型是YOLOv2和SSD,在手机上跑一帧要几百毫秒,模型文件动辄几十MB,后来逐步接触MobileNet系列、NanoDet、PP-PicoDet,再到YOLOv5n、YOLOv8n,能明显感觉到这条路在设计思路和工程落地上已经非常成熟。现在一个5MB左右的目标检测模型跑实时视频流,已经不是什么新鲜事。这篇文章想把这些年“摸过”的轻量型目标检测算法做个系统梳理,聊聊背后的设计逻辑、常见算法选型、训练部署流程,以及我实际踩过的坑,适合正在做模型选型,或者准备在手机、嵌入式设备上落地检测功能的朋友参考。

1. 为什么说轻量型目标检测算法是端侧项目的第一道坎

1.1 端侧算力不是堆出来的

“轻量型目标检测”之所以成为一门重要的研究方向,根本原因在于真实世界的算力环境非常不均匀。服务器上跑一个几百MB的大模型,用A100显卡当然没问题,但换到手机、摄像头、无人机、门禁设备上,内存和功耗都是硬约束。端侧项目面对的往往不是“准不准”这一个指标,还有“跑不跑得动”“会不会发烫”“功耗能不能撑住一整天”这些更接地气的问题。

我见过太多项目在前期选型时直接拿GPU服务器上的大模型做实验,精度确实不错,一到样机阶段就翻车。芯片厂商的SDK不支持某些算子,板子内存不够,模型文件塞不进固件,这些都是常见事故。轻量型目标检测算法解决的就是这类问题:在尽量少的参数和计算量下,把目标检测这事做对。它不是把大模型“缩小一点”,而是从结构设计、压缩方法到部署细节的一整套工程方法。

1.2 轻量化不等于“牺牲精度”

很多人一听到“轻量型算法”就下意识觉得精度一定差很多,这个印象需要修正。近几年轻量型算法的精度在公共数据集上的表现,已经相当能打。比如YOLOv8n这样量级的模型,参数只有几百万,在COCO数据集上的mAP能到37上下,很多垂直场景只要数据足够好,效果完全够用。更关键的是,轻量化带给业务的价值不只是“跑得动”,还包括更低的服务器成本、更快的响应速度以及更好的隐私保护。视频流不需要上传云端,在设备本地就能完成检测,这对很多行业来说是刚需。

我的经验是,选轻量型目标检测算法,不要只盯着精度排序,要先把“设备、分辨率、帧率、模型大小”这几个约束写清楚。只要约束明确,很多模型其实差别不大,真正决定项目成败的往往是后续的数据清洗、标注质量、训练调参和算子兼容,这些内容后面会详细展开。

2. 轻量型目标检测算法的四条设计主线

2.1 轻量骨干网络是地基

目标检测模型可以粗略拆成“骨干网络”和“检测头”两部分。骨干网络负责提取图像特征,特征提得好不好,直接决定检测上限。轻量型算法的第一条主线,就是把骨干网络做轻。目前用得最多的思路有深度可分离卷积、通道混洗、结构重参数化,以及靠神经架构搜索搜出来的高效结构。

以MobileNet系列为代表,核心操作是深度可分离卷积。它把标准3×3卷积拆成两步:先用一个3×3卷积对每个输入通道单独做卷积,再用一个1×1卷积在通道之间做线性组合。在输入通道和输出通道都是C的情况下,标准3×3卷积的参数量是9×C×C,而深度可分离卷积的参数量是9×C+C×C,当C比较大时,计算量和参数大概能降到原来的九分之一左右。这样换来的代价是某些任务上精度略微下降,但换到端侧设备上就是帧率几倍的提升。

ShuffleNet系列走的是另一条路:用分组卷积配合通道混洗,让各组特征之间能够“串门”,同样能有效减少计算量。EfficientNet-Lite则通过自动搜索找到兼顾精度和效率的缩放系数,在移动端也经常能看到。实际选骨干网络时,不必非得看懂每篇论文的细节,但需要清楚一件事:深度可分离卷积几乎成了轻量检测模型的默认配置,如果项目里遇到一个模型计算量奇高、参数量还大,大概率是因为骨干网络用到了太多普通卷积。

2.2 检测头也要“减重”

很多研究者在做轻量化时,会把大量精力花在骨干网络上,但检测头同样不能忽略。早期SSD、Faster R-CNN这类模型,检测头通常是一组普通卷积堆叠,通道数动辄256、512,算下来占整个模型的比重不小。轻量型目标检测算法在检测头上一般做三件事:缩小通道数、用深度可分离卷积替换普通卷积、从anchor-based改成anchor-free来简化回归目标。

举个例子,YOLOv8n的检测头就是anchor-free风格,不再需要设计一堆先验框,也省去了和anchor匹配相关的计算与调参。NanoDet在检测头上做了更激进的设计,砍掉很多冗余分支,并引入轻量化的特征金字塔结构,所以模型可以做到不到1M参数,还能保持不错的精度。这里我的经验是,检测头越小,训练时需要花更多时间让特征对齐,但换来的是部署时非常舒服的模型体积和推理速度。

2.3 训练后的压缩手段

结构上的轻量化是“天生瘦”,训练后的压缩则是“后天减脂”。常见手段有三板斧:剪枝、量化、知识蒸馏。

剪枝是去掉权重里贡献比较小的一部分。非结构化剪枝会得到稀疏的网络,需要特殊库和硬件支持,在移动端并不常见;结构化剪枝直接剪掉某些输出通道或卷积核,对部署框架比较友好。实操中我一般用torch_pruning这类库,给模型做一个按通道的稀疏化训练,再设一个保留比例,剪完后微调几个epoch。需要注意,剪枝不是越狠越好,剪到20%可能损失很小,超过50%往往要花很长时间才能把精度拉回来。

量化指的是把模型权重从FP32变成INT8,最关键的是减少计算和内存占用。INT8量化后模型体积能变成原来的四分之一,推理速度在某些端侧芯片上能提升两到三倍。知识蒸馏则是让轻量模型去学习大模型的“软标签”,用大模型作为teacher,小模型作为student,通常能补回不少精度。我的建议是,先训练好一个大模型作为基准,再用蒸馏的方式去带小模型,比直接硬训一个小模型要稳定得多。

2.4 自动搜索与结构重参数化

近两年,越来越多轻量模型开始借助神经架构搜索来自动决定网络的深度、宽度、卷积类型。EfficientNet-Lite和MobileNetV3都依赖这种思路。这类模型的内部结构看起来并不“手工”,但工程效果往往比手工调出来的更好。结构重参数化则是另一种思路:训练时用多分支结构,部署前把多分支合并成一个普通卷积,典型代表是RepVGG。目标检测模型里也能看到类似思想,训练和部署用两套结构,换来的是推理阶段几乎没有额外开销。

不过自动搜索出来的模型虽然精度不错,偶尔会碰到部署框架不支持的算子。在实际项目里,我一般会优先看这个模型有没有现成的端侧部署案例,算子兼容性比一点精度更影响上线进度。

3. 主流轻量型目标检测算法一次盘点

3.1 先分清参数量、FLOPs、MACs这三个指标

盘点算法之前,必须把几个容易混淆的指标说清楚。参数量指的是模型里有多少个可学习的权重,单位通常是M(百万)或K;模型文件大小主要由参数量和存储精度决定。比如一个FP32的权重,每个参数要占4字节,模型文件换算下来大约是“参数量×4”;如果是INT8,则大约是“参数量×1”。

FLOPs是浮点运算次数,MACs是乘加运算次数,二者经常一起出现,且1次MAC约等于2次FLOP。热搜里如果看到“MACs仅5MB的目标检测模型”,其实这里把“计算量”和“模型文件大小”混在一起说了。MACs的单位是G、M,指的是推理时要做的运算次数,MB是存储体积,两者没有直接换算关系。一个模型可能文件很小,但计算量很大;也可能文件不小,但计算量并不高。看模型是否轻量,两个指标都要看。

3.2 经典组合:SSD + MobileNet

SSD-MobileNet是很多端侧项目的启蒙模型。它用MobileNet作骨干,在多个尺度的特征图上直接预测边界框和类别。相比Faster R-CNN,SSD没有RPN阶段,结构简单、计算量低,在2017年前后几乎是移动端检测的默认选项。

这套组合现在依然有意义,一是历史代码存量很大,很多老设备上的工程都是基于它改的;二是因为训练和部署资料非常全。缺点也很明显:backbone和检测头都是浅层设计,对遮挡严重、目标密集的场景表现一般。如果你今天从零开始一个新项目,我不会首推它,但理解SSD的多尺度特征图预测逻辑,对理解后来的YOLO系列很有帮助。

3.3 YOLO轻量版:从YOLOv5n到YOLOv8n

YOLO系列是目标检测领域绕不开的名字。YOLOv5n和YOLOv5s是较早一批把轻量化和生态做好的模型,尤其是YOLOv5n,参数量约1.9M、模型文件3.8MB左右,一度是中低端设备上最稳妥的选择。YOLOv6n、YOLOv7-tiny也都是同一思路,只是不同公司或作者维护。

YOLOv8n是我最近用得更多的模型,参数量约3.2M,输入640分辨率时FLOPs约8.7G,精度相比YOLOv5n有明显提升。它自带很完整的训练框架和导出工具链,从数据标注到ONNX导出再到TensorRT、NCNN部署,整个流程很顺。YOLOX-Nano则是在anchor-free这条路上的一家代表,参数约0.9M,设计上更强调工业部署的简洁性,适合对模型大小极其敏感的项目。这类轻量YOLO模型的标准用法是:用公开权重做迁移学习,在自己的数据集上微调,一般不推荐从头训练。

3.4 专门为移动端设计的NanoDet和PP-PicoDet

除了YOLO系,还有一批从设计之初就面向移动端的检测框架。NanoDet系列由开源社区推动,主打“小到极致”。NanoDet-Plus在不到1M参数的情况下,精度能接近早期的YOLOv5s,部署代码也很干净,很适合MCU级别的设备研究。

PP-PicoDet是百度飞桨推出的轻量型目标检测模型,它在移动端优化上做得非常细,除了使用深度可分离卷积,还引入了更强的数据增强策略、更好的标签分配和蒸馏方案。PP-PicoDet的模型体积和FLOPs控制得都很低,在ARM CPU上的帧率表现通常不错,这也是我近几年在端侧项目中最常推荐给团队测试的模型之一。需要注意的是,PicoDet的官方仓库基于PaddleDetection,如果你想用PyTorch复现,社区版本很多,需要自己甄别实现是否严格对齐原始配置文件。

3.5 轻量型目标检测算法对比表

下面这张表格是我根据公开项目里常看到的数据整理的,不同实现、不同输入分辨率会有差异,选型时建议以项目官方README为准。

模型参数量FLOPs(640输入附近)模型大小参考适合场景
SSD-MobileNetV2约6M(视检测头配置)约1G左右约14MB老项目迁移,入门教学
YOLOv5n约1.9M约4.5G约4MB通用轻量端侧检测
YOLOX-Nano约0.91M约1.1G约2MB对体积极度敏感的设备
YOLOv8n约3.2M约8.7G约6MB精度和生态兼顾
NanoDet-Plus约0.9M约1G级别约2MB移动端、低功耗设备
PP-PicoDet-S约1.2M约1G级别约5MBARM CPU、端侧摄像头

从这张表能看出,模型大小和FLOPs没有必然正比关系。有些模型文件很小,但推理运算量并不一定最低,因为文件大小还受存储格式影响。选型时不要只看单一指标,最好拿同一个部署环境跑一遍,用帧率和实际精度说话。

4. 从零训练一个轻量检测模型:完整实操流程

4.1 环境准备与数据集组织

实操部分我用YOLOv8n做例子,因为它的工具链最完整,适合大多数人快速上手。先准备Python环境,建议Python 3.8到3.11之间,安装ultralytics:

pip install ultralytics

然后在本地准备好数据集。这里以一个简单的安全帽检测项目为例,数据集按如下目录组织:

datasets/myhelmet/ ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── train/ └── val/

标签文件是YOLO格式的txt,每行代表一个目标:类别id 归一化中心x 归一化中心y 归一化宽 归一化高。如果你手头只有VOC或者COCO格式的数据,可以用ultralytics内置的转换脚本,也可以自己写脚本转一下。数据做好后,创建一个YAML文件:

path: datasets/myhelmet train: images/train val: images/val names: 0: helmet 1: person

4.2 第一次训练:参数怎么调才不踩坑

轻量型模型训练在小数据集上很容易过拟合,所以我的习惯是先用公开权重做微调,而不是从头训练。执行下面这条命令:

yolo detect train data=myhelmet.yaml model=yolov8n.pt epochs=100 imgsz=640 batch=16 device=0

几个关键参数需要解释。imgsz控制输入分辨率,默认640,但如果目标普遍偏小,可以适当提升到960或1280,代价是训练和推理变慢。batch受显存限制,如果显存不够,可以先降batch,同时可以考虑开启混合精度训练。epochs不要一上来就设个500,先用100个epoch看收敛趋势,再决定是否加长。

训练时我会额外关心两类日志:一是loss曲线,二是验证集上的PR曲线。如果loss持续下降但mAP不动,大概率是数据标注问题或类别不均衡;如果loss下降很慢,可以试试把学习率调到0.001或者0.01。轻量模型尤其容易出现“瓶颈在网络结构容量,而不是训练程度”的情况,这时再堆epoch也意义不大。训练结束后,别急着用last.pt,最好使用best.pt,它是根据验证集mAP自动挑选出来的最优权重。

4.3 模型导出与剪枝量化

训练完成后,把PyTorch模型导出成ONNX,方便后续部署:

yolo export model=runs/detect/train/weights/best.pt format=onnx opset=12 simplify=True

如果是要部署到移动端,常用NCNN或MNN。以NCNN为例,拿到ONNX后执行:

onnx2ncnn helmet.onnx helmet.param helmet.bin ncnnoptimize helmet.param helmet.bin helmet.opt.param helmet.opt.bin 1

这里能看出,模型在PyTorch里表现很好只是第一步,很多算子转换后才暴露出兼容性问题。如果某个算子不支持,需要回到模型结构里替换成更基本的卷积、激活函数组合。

量化可以在这条链路里做,一般用PTQ(训练后量化)就够了。用一部分验证图片作为校准集,工具会统计每个激活值的分布,再决定INT8的量化参数。量化后一定要在目标硬件上重新跑一遍精度测试,不能只看文件变小了就宣布胜利。剪枝我一般放在量化之前,先剪枝微调,再量化,否则精确度损失容易叠加。

4.4 部署到边缘设备并验证帧率

部署到边缘设备时,有两个指标必须实测:单帧推理时间和峰值内存。只凭开发者电脑上的测速没有任何参考价值,因为不同芯片的算子库差异巨大。比如同一个模型,在带GPU的Jetson上表现不错,到纯ARM CPU上可能慢得离谱,原因可能是模型里某些算子对内存访问不友好,或者卷积实现没有针对芯片优化。

我习惯在真机上写一个简单的循环测试,连续跑100帧,取平均时间,再统计模型加载后的内存占用。如果某一块算子明显耗时,可以用NCNN的profiling工具定位,也可以考虑把输入分辨率降一档看看。这里切忌为一个模型反复调优而不回到业务目标:如果产品本身只需要5帧每秒,那就画一条“帧率与精度”的取舍线,超过需求的部分没必要硬扛。

5. 真实项目里最容易踩的坑及排查思路

5.1 小目标检测效果差

轻量型模型为了速度,往往会把输入图像缩小到320或416,这样一来小目标在特征图上只剩下几个像素,漏检很正常。解决思路有几个。第一,适当提高输入分辨率,从416提升到640,通常能立刻看到小目标召回率上升。第二,训练时使用多尺度训练,让模型适应不同尺寸的目标。第三,如果设备性能允许,使用“切图”策略,把大图切成几块分别检测,再合并结果。

我做一个鸟群监测项目时,用YOLOv8n在640分辨率下小目标漏检很严重,后来改成1280分辨率训练,模型FLOPs直接翻倍,但精度明显提升。注意轻量模型在大分辨率输入下,帧率下降幅度往往比大模型更明显,因为高分辨率下的特征图计算量也上来了。所以最好先量一下自己场景里的目标尺寸分布,再决定要不要为小目标牺牲速度。

5.2 训练精度不高但模型又小

轻量模型参数少,理论上更容易过拟合,但实际中经常出现的是另一个问题:模型容量不够,训练集精度已经很高,验证集上不去。遇到这种情况,我建议先检查训练数据是不是有“信息泄露”或者类别不均衡。比如安全帽数据集里,绝大多数图片只有一种角度,模型没有见过别的角度,哪怕换大模型也未必能解决。

数据增强对轻量模型尤其重要。ultralytics默认会有马赛克增强,对小数据集很有帮助。如果试了增强还很差,可以尝试用知识蒸馏。用一个大一些的模型作为teacher,把中间特征或输出分布一起约束轻量模型,往往能把mAP提升3到5个点。这里的“大模型”不一定要很大,YOLOv8m就够用了。

5.3 模型转换后算子不支持或精度掉点

模型在PyTorch里跑得好,导出ONNX后推理结果完全不对,或者出现NaN,是部署常见的头疼问题。最常见的原因有:ONNX版本和部署框架版本不匹配、某些动态尺寸没有固定、归一化方式不一样。我的习惯是,导出ONNX后在本地先用onnxruntime跑一遍,对比PyTorch输出,确认无误后再做下一步。

量化后精度掉点也很常见,尤其是小目标。如果校准集选得不好,或者模型里有些层对量化特别敏感,损失会更明显。我的排查思路是“二分定位”:逐个尝试跳过某些层的量化,找到掉点最严重的层,手动保持FP32或改用16位浮点。有些框架也支持混合量化,允许一部分层INT8、一部分层FP16,这样能换来精度和速度的平衡。

5.4 模型体积与推理速度的误区

前面提到过,“模型大小5MB”和“推理快”并不是同一件事。一个模型可能权重文件很小,但里面每层计算量都很大,原因是参数量少但输入尺寸大;反之,一个模型参数很多,但经过深度可分离卷积设计,速度可能比参数少的还快。所以我在团队里定了规矩:评估轻量模型时,至少列出参数量、FLOPs、内存占用、实测帧率四个指标,缺一不可。

部署端还有一个很容易忽略的点:模型加载时间和预热。有些模型在真机上第一次推理特别慢,因为算子库在初始化时做了很多内存分配。测试时必须跑足够多次,拿到稳定后的平均值,不能直接把第一次推理的时间当作性能结论。

6. 关于轻量型目标检测,我最后想说的几句

6.1 新手怎么选型

如果你刚接触轻量型目标检测,我的建议是先别急着研究所有算法,找一个生态完整的库把流程跑通一遍。YOLOv8n是一个非常好的起点,文档全、坑少,训练导出部署一整套路径都通。跑通之后再换到PP-PicoDet或者NanoDet,体会不同设计带来的差异,这时你对“轻量化”的感受会具体很多。

选型时把四个问题写清楚:设备CPU还是GPU、内存上限多少、目标帧率多少、检测的最小目标大概多大。答案一旦确定,很多泛泛而谈的模型对比其实可以直接跳过。

6.2 我踩过几次坑之后的体会

我曾经花了一周时间试图把一个模型剪枝到极致,最后文件是小了,但推理速度几乎没有提升,原因在于剪枝后产生了很多不规则稀疏算子,在目标芯片上支持并不好。后来我改成了整通道剪枝,配合微调和量化,效果才明显改善。做轻量化,不要只盯着“剪多少”,要看“在目标部署环境里能省多少”。

另外,轻量模型最终是给业务用的,不是用来刷指标的。我见过团队为了追求mAP涨零点几,把模型输入分辨率从416提到1280,结果设备端帧率掉了四倍,客户上线首发当天就崩了。根据我个人经验,最稳的路径是先锁定部署设备和使用场景,再反推模型选型和训练策略。轻量型目标检测算法更新很快,但想让它真正服务业务,还是离不开从数据、训练、压缩到部署的完整闭环。这套功夫没有捷径,但只要认真走一遍,后面的项目会越做越顺。

返回列表