拓冰建站拓冰建站
首页 / 资讯中心 / 正文

YOLOv8网络结构图全解:从C2f到PAN-FPN的绘制与改进实践

简介面向目标检测学习者和研究人员的YOLOv8网络结构解析型教程适合初次接触YOLO系列、希望深入理解模型组成并绘制结构图的读者。压缩包仅含1个doc文档大小53KB内容精炼、便于随时查阅已有2300人学习。文档以整体架构概述切入系统拆解Backbone、Neck、Head三个核心部分并对卷积层、C2f、SPPF、上采样层、Concat连接层和检测头等关键模块逐一说明结构作用。网络结构绘制部分从Visio、Graphviz等绘图工具选择讲起按Backbone、Neck、Head顺序给出标注和美化建议代码对应部分结合yolov8.yaml配置文件、PyTorch实现代码以及Netron等模型可视化工具帮助读者把结构图与工程实现一一对应。文档还分析了与YOLOv5的差异、注意力机制和轻量化改造等改进方向读完后既能独立绘制和验证YOLOv8结构图也能为后续调优和二次开发打下基础。 说实话每次在交流群里看到有人甩出一张 YOLOv8 网络结构图然后追问“C2f 里面到底是啥”“PAN-FPN 怎么画的”我都挺有感触。YOLOv8 的目标检测效果确实能打但如果不懂网络结构图后续训练、改模型、调小目标检测头全都得靠猜。这篇教程我不会只丢一张大图给你而是从“怎么画”“怎么看”到“怎么用结构图指导训练和改进”完整讲一遍面向刚开始接触检测模型、又被各种结构图劝退的朋友也适合想给 YOLOv8 做改进、但不知道从哪里下手的开发者。我最早研究 YOLOv8 网络结构图的时候走了不少弯路——拿着一张来源不明的结构图对着 yaml 文件核对发现两边的模块对不上最后用工具一点点点开才算真正看懂。其实网络结构图说白了就是一套“交通路线图”Backbone 是主干道Neck 是连接匝道Head 是出口收费站。把这张图彻底看明白你的训练日志、loss 曲线、改进方向全部都能串起来。1. 网络结构图先明白它到底解决什么事1.1 为什么一张图比十段文字更重要目标检测模型不像普通分类网络输入一张图直接输出一个类别就完事。它要同时回答“图像里有什么”“在哪个位置”“框得准不准”三个问题所以网络内部存在多条分支特征图也有多个尺度的流转。这种信息用文字描述非常绕一张结构图却能让人一眼看全。而且 YOLOv8 的代码是高度模块化的不管是 C2f、SPPF 还是 Detect都被封装成了一个个类。你如果不去看结构图直接啃源码很容易陷入细节里出不来。先看整体结构再看某个模块的具体实现这才是效率最高的学习路径。1.2 画图和看图的工具选型看过不少结构“图”实际来源五花八门我把它们分成三类官方 yaml 文件这是最权威的“定义”相当于源代码。YOLOv8 的网络结构本质是由 yaml 描述出来的配合 ultralytics 库可以自动构建模型。看结构图之前建议先把 yaml 过一遍。Netron 可视化Netron 是专门看神经网络模型结构的工具把训练好的.pt或导出的.onnx文件拖进去就能一层层点开查看每个模块的输入输出 shape、参数个数。这是最推荐的一步能让你看清“实际网络长什么样”。手工绘制的结构图很多论文博客里的图是作者自己画的优点是好理解但缺点是可能省略细节或者有版本误差。我见过把 C3 画成 C2f、把上采样画成反卷积的所以手工图只能当参考最终要以 Netron 为准。画图工具方面我用的最多的是 draw.io免费而且支持导出矢量图。Visio 也不错但安装比较麻烦。如果你只是自己理解直接在白纸上画就行重要的是理清数据流向。2. YOLOv8 整体结构拆解Backbone、Neck、Head 三段式2.1 三段式总览YOLOv8 的完整网络结构可以拆成三段Backbone主干网络负责从原始图像中提取特征。图像输入后经过一系列卷积和 C2f 模块分辨率不断降低通道数不断增加。这个过程类似于把一张大图逐步“压缩”成不同尺度的特征图。Neck颈部结构负责融合不同尺度的特征。YOLOv8 使用的是 PAN-FPN 结构既有自顶向下的路径把高层语义信息传递到底层又有自底向上的路径把底层的细节信息传回高层。这一步是为了让网络同时检测大目标和小目标。Head检测头负责最终输出。YOLOv8 使用解耦检测头把分类和回归任务分开处理分别输出目标类别概率和边界框坐标。很多同学问“为什么 YOLOv8 网络结构图里那么多分支”其实核心就是 Backbone 提取多尺度特征Neck 做多尺度融合Head 在多尺度上进行预测。2.2 C2f 模块内部推演C2f 是 YOLOv8 中最核心的基础模块也是从 YOLOv5 的 C3 模块演变来的。看到结构图里很多“C2f”方块如果你不理解它的内部构造后面就看不明白。C2f 的完整名字是 CSPDarknet Cross Stage Partial with 2 convolutions设计思路大致如下输入先经过一个 1x1 卷积把通道数调整并生成两个分支。一个分支直接连接到输出相当于“捷径”保留原始信息。另一个分支经过若干个 Bottleneck 子模块每个 Bottleneck 内部是“卷积 卷积 残差连接”。分支里的每个 Bottleneck 输出都会被“截留”一部分最后和捷径分支拼接到一起。拼接后再次经过一个 1x1 卷积得到最终输出。用生活化的比喻C2f 像一条流水线一个工人Bottleneck加工完半成品后不仅把成品传给下一个工人还匀出一份给质检组。最后质检组把所有人的成果汇总。这样做的好处是梯度可以直接从捷径分支传回去缓解深层网络梯度消失的问题同时每个 Bottleneck 的特征都得到了利用。这里有个容易看懵的地方yaml 文件里- [-1, 3, C2f, [128, True]]中的数字 3指的不是卷积核数量而是 Bottleneck 的重复次数。我在对照网络结构图的时候吃过这个亏一直以为 3 是输出通道后来反复核对 filter 数量才发现是重复次数。2.3 SPPF 与浅层特征怎么走的SPPFSpatial Pyramid Pooling - Fast是 YOLOv8 在 Backbone 最后使用的模块用来扩大感受野。它由 YOLOv5 的 SPP 改进而来核心操作是输入先经过一个 1x1 卷积降维。然后连续做三次 5x5 的最大池化。每次池化后的结果都保留最后把所有结果拼接起来。拼接后的特征经过一个 1x1 卷积输出给 Neck。设计思路可以理解为“用不同尺寸的筛子筛同一个东西”小感受野看细节大感受野看全局最后把不同粒度的信息都保留下来。相比 SPP 的并行设计SPPF 的串行设计在计算量上更小这也是很多结构图里 SPPF 是一个“串起来”的形状的原因。实际计算时有一个细节值得注意连续 3 次 5x5 最大池化的效果等同于 1 次 13x13、1 次 9x9 和 1 次 5x5 的池化组合但参数量和计算量却少了很多。这也是 YOLOv8 能在保持精度的同时比 v5 更高效的原因之一。3. 手把手画一张能用的 YOLOv8 结构图3.1 从 yaml 文件出发想画出可靠的结构图不能凭空想象我建议直接以官方yolov8.yaml为骨架。核心内容大致如下backbone: - [-1, 1, Conv, [64, 3, 2]] - [-1, 1, Conv, [128, 3, 2]] - [-1, 3, C2f, [128, True]] - [-1, 1, Conv, [256, 3, 2]] - [-1, 6, C2f, [256, True]] - [-1, 1, Conv, [512, 3, 2]] - [-1, 6, C2f, [512, True]] - [-1, 1, Conv, [1024, 3, 2]] - [-1, 3, C2f, [1024, True]] - [-1, 1, SPPF, [1024, 5]] head: - [-1, 1, nn.Upsample, [None, 2, nearest]] - [[-1, 6], 1, Concat, [1]] - [-1, 3, C2f, [512]] - [-1, 1, nn.Upsample, [None, 2, nearest]] - [[-1, 4], 1, Concat, [1]] - [-1, 3, C2f, [256]] - [-1, 1, Conv, [256, 3, 2]] - [[-1, 14], 1, Concat, [1]] - [-1, 3, C2f, [512]] - [-1, 1, Conv, [512, 3, 2]] - [[-1, 10], 1, Concat, [1]] - [-1, 3, C2f, [1024]] - [[15, 18, 21], 1, Detect, [nc]]这里每行代表一个网络层[-1, 3, C2f, [128, True]]的意思是输入来自上一层包含 3 个 Bottleneck模块类型是 C2f输出通道数 128。[-1, 6]这种写法表示输入来自第 6 层用来做特征拼接。画图前先解释一个通用规则输入图默认是640x640x3经过第一个 stride2 的卷积后变成320x320x64后面每经过一个 stride2 的卷积分辨率减半通道数翻倍。最终 Backbone 输出三个尺度的特征分别是下采样 8 倍、16 倍、32 倍的结果对应80x80、40x40、20x20。3.2 从 Backbone 画到 Neck 再到 Head画网络结构图我习惯按“主干 - 分支 - 融合”的步骤来先把骨架画出来再补细节。第一步画 Backbone 主干把主干想象成一条竖线从底部输入向上走。输入图经过第一个 Conv然后进入第一个 C2f再经过第二个 Conv 和第二个 C2f……直到 SPPF 结束。画的时候每个模块画成矩形框旁边标注输出特征图的尺寸和通道数。第二步画 Neck 融合路径从 Backbone 的80x80、40x40、20x20三个尺度引出三条分支。结构图上半部分是 PAN-FPN20x20的特征先上采样到40x40再与 Backbone 中40x40的特征拼接经过 C2f 融合然后继续上采样到80x80与80x80特征拼接融合。到这里很多结构图会戛然而止但 YOLOv8 的 Neck 还没完它还要再走一遍自底向上的路径80x80的特征下采样到40x40再次拼接融合再下采样到20x20再次拼接融合。最终 Head 接收的就是这三条经过双向融合的特征。第三步画 Head 输出YOLOv8 的 Detect 头是解耦的也就是每个尺度上都有两个平行分支。一个分支做分类输出80x80x类别数另一分支做回归输出80x80x644 个坐标各对应 16 个离散值由 DFL 解码出最终坐标。我在画图的时候踩过一个坑刚开始只看别人博客上的结构图看到 Head 那里两个分支连出来却不知道“分类分支和回归分支最后是怎么合成一个输出的”。实际上推理阶段会把分支结果合并然后经过 NMS 输出最终检测框结构图上往往不画 NMS 这一块但心里要有数。3.3 用 Netron 验证结构图手画的图对不对最快验证方法是用 Netron 打开模型文件。操作流程如下安装 ultralytics运行yolo export modelyolov8n.pt formatonnx导出 ONNX 文件。打开 Netron拖入导出的 ONNX 文件。在搜索框输入C2f或SPPF点开模块看内部细节。用 Netron 看结构的时候我强烈建议大家观察每个模块的输入输出形状shape这比画图本身更有价值。比如输入图片是640x640x3第一个卷积输出的 shape 是1x64x320x320说明 batch size1、通道数 64、宽高 320。你拿这个和手画图对照立刻能发现自己是不是把特征图尺寸标错了。另外有个小技巧Netron 里可以对整个图进行“选中某个节点查看前后关联”这样能快速理清数据流。我画结构图的习惯是先看 yaml 做草稿再用 Netron 逐步验证最后在 draw.io 里出成品图。三步走下来基本上不会出错。4. 结构图能直接用在训练和改进里4.1 训练时看损失曲线怎么对应结构很多朋友训练 YOLOv8 时只盯着 mAP不关心 loss。其实网络结构图和你的 loss 曲线是强相关的。我在这里把 YOLOv8 的三种 loss 和结构对应关系捋一遍Loss 名称对应 Head 分支作用cls_lossBCE分类分支衡量目标类别预测是否正确box_lossCIoU回归分支衡量预测框和真实框的重叠程度dfl_loss回归分支衡量边界框坐标的分布质量训练时如果box_loss下降慢说明回归分支的特征提取能力不够要重点检查 Neck 特征融合是否充分比如有没有在浅层特征上丢掉小目标信息。如果cls_loss抖动剧烈可能是正负样本分配策略或者数据标注本身有问题。Ultralytics 训练完成之后会在runs/detect/train目录下生成一个results.png里面画了所有 loss 和指标曲线。我每次训练完都会认真看这张图特别是前面 50 个 epoch 的收敛趋势能快速判断结构设计是否合理。4.2 想加小目标检测头先从结构图找下手点“YOLOv8 小目标检测头”是我在后台看到的高频搜索词。YOLOv8 默认只从P380x80、P440x40、P520x20三个尺度做预测其中 80 的特征图已经能检测相对小的目标但遇到高空遥感图、无人机视角、工业质检中的微小瑕疵还是不够。在结构图上做改进的思路很清晰再增加一个更大分辨率的输出也就是P2160x160检测头。在 Backbone 部分需要把C2f第一个模块的输出160x160引出来。在 Neck 部分新增一次上采样把深层特征和160x160特征拼接融合。在 Head 部分新增一组检测头负责小目标的分类和回归。但要注意加 P2 检测头不是免费的。160x160的特征图计算量比80x80大 4 倍显存占用和训练时间都会明显增加。我在 GTX 1660 Ti 上跑实验时加了 P2 后显存立刻不够只能把 batch size 调到 8 勉强跑动。如果你只有 6GB 左右显存建议先从YOLOv8n这种轻量版本开始加不要直接用YOLOv8x。另外结构图上的yaml文件也会改动需要新增几个模块并把Detect的输入索引从[15, 18, 21]改成对应新层。新手容易犯的错是只改了结构图没同步修改 yaml 和后续的 anchor 匹配逻辑结果训练直接报 shape 不匹配。4.3 改进 Head 时怎么结合结构图热词里还有不少“yolov8 head 改进”的需求。Head 部分改进通常有三种方向注意力机制在分类分支或者回归分支前面插入 SE、CBAM、CA 模块增强特征表达。因为 Head 本身结构简单插入注意力模块后效果往往立竿见影。轻量化把原来的 3x3 卷积替换成深度可分离卷积减参数量。这种方法适合端侧部署但精度可能会有轻微下降。多分支设计把原来的两个分支扩展成多分支同时预测不同语义信息。改进 Head 之前我建议先画出“微观结构图”也就是把某个检测头的内部结构单独放大看清楚每个卷积的输入输出通道再决定在哪一层插入新模块。否则你只会在宏观结构图上瞎改根本无法定位到具体代码位置。5. 常见问题与排查技巧实录5.1 结构图看不懂怎么办我遇到最多的问题是“结构图里 40x40 和 80x80 的特征到底怎么流动的”。这里分享一个非常土但有效的方法把各层输出 shape 全部打印出来然后和结构图对照。import torch from ultralytics.nn.tasks import DetectionModel model DetectionModel(cfgyolov8n.yaml, ch3, nc80) x torch.randn(1, 3, 640, 640) y model(x) for i, out in enumerate(y): print(i, out.shape)运行后你会看到三个输出分别对应(1, 84, 80, 80)、(1, 84, 40, 40)、(1, 84, 20, 20)。前面的 84 等于 80 个类别加 4 个坐标。如果你在结构图上看到某个分支 shape 对不上排查起来就很快。还有一个经典误解很多人以为 YOLOv8 的 Neck 只有一个自上而下的 FPN实际上它是双向的 PAN。只看网络结构图的上半部分不看下半部分会漏掉一半信息。我自己的经验是在结构图上把自上而下路径用一种颜色画自下而上路径用另一种颜色画立刻清晰很多。5.2 常见踩坑速查表症状可能原因解决办法结构图和 yaml 对不上博主画图时省略了细节或者版本不同以 yaml 和设备 Netron 结果为准训练报 shape 不匹配改结构时没有同步修改 Detct 输入索引核对 yaml 中Detect前面的层编号C2f 理解成 C3名称相近导致混淆点开 Netron 对照 Bottleneck 堆叠数加了 P2 后显存爆炸160x160特征图计算量太大换轻量版本或减小 batch size不知道在哪里加注意力没有画出 Head 微观结构先画单检测头内部图再决定插入位置5.3 卡在结构理解上的自查清单如果看到这里你还是觉得心里没底可以从这几个角度自查能不能说出 C2f 模块里“几个 Bottleneck”是怎么配置的能不能把 Backbone 输出的三个特征图尺寸准确写出来能不能解释 PAN 结构里的“自顶向下”和“自底向上”分别做了什么能不能指出网络结构中哪些地方适合插入注意力机制如果这些问题都能回答说明 YOLOv8 网络结构图你已经入门了。我个人在实际研究中的体会是网络结构图不是画完就完事了它应该随着你的模型演进而持续更新。我每改一次模型都会同步更新一张结构图哪怕只是在某个模块加了一个注意力层。这不仅是为了给别人讲解更是为了下次自己调试时不用重新对着代码翻半天。画图看起来花了额外的时间但排错和改模型的时候回报是立竿见影的。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门