ARTICLE DETAIL

资讯详情

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

YOLOv4配置文件(.cfg)详解:从网络结构到超参数调优

YOLOv4配置文件(.cfg)详解:从网络结构到超参数调优 1. 从配置文件开始为什么YOLOv4的.cfg文件如此重要如果你刚接触YOLOv4或者从其他深度学习框架比如PyTorch、TensorFlow转过来可能会觉得Darknet框架有点“原始”。没有花哨的图形界面没有一键式的训练脚本一切似乎都从几个命令行和一个文本配置文件开始。而yolov4.cfg就是这个文本配置文件它定义了整个YOLOv4网络的骨架、血肉和灵魂。很多人拿到这个文件看到里面密密麻麻的[net]、[convolutional]、[route]、[shortcut]等段落以及各种数字参数第一反应可能是直接跳过或者在网上找个“调好的”配置直接用。但如果你想真正理解YOLOv4甚至想根据自己的数据集和任务去优化它那么读懂这个.cfg文件是绕不开的第一步。它不像PyTorch那样把网络结构写在Python代码里直观但分散Darknet把一切都浓缩在这个配置文件中结构清晰修改起来也直接。可以说掌握了.cfg文件你就掌握了在Darknet框架下驾驭YOLOv4的钥匙。这篇笔记就是带你一行行拆解官方的yolov4.cfg文件把每个参数的含义、背后的设计逻辑以及在实际项目中如何调整它们都讲清楚。这不是简单的翻译文档而是结合我实际训练和部署中的经验告诉你哪些参数动了会“伤筋动骨”哪些微调一下就能带来意想不到的效果提升。我们从最开头的[net]部分开始。2. 网络全局配置[net] 段落详解[net]段落位于.cfg文件的最开头它定义了整个网络训练的全局超参数。这部分不涉及具体的网络层结构而是控制着训练过程的“节奏”和“方式”。理解这些参数对于成功训练一个模型至关重要。2.1 基础尺寸与批次设置[net] # Testing # batch1 # subdivisions1 # Training batch64 subdivisions16 width608 height608 channels3batch与subdivisions这是Darknet训练中非常核心且容易混淆的一对参数。batch指的是批次大小batch size。它表示在一次权重更新即一次反向传播之前网络会处理多少张图片。batch64意味着累积64张图片的梯度后才更新一次网络权重。更大的batch size通常能使梯度估计更稳定可能有助于收敛但需要更多的显存。subdivisions子批次subdivision。由于我们显卡的显存VRAM可能无法一次性装入一个完整batch的图片进行计算Darknet引入了subdivisions来将batch拆分。实际每次前向-反向传播处理的图片数量是batch / subdivisions。在上面配置中batch64,subdivisions16那么每次迭代显卡实际只处理64/16 4张图片。网络会累积16次这样的“小批次”梯度总共64张图然后才进行一次权重更新。如何调整如果你的显卡报错“Out of memory”首先应该调大subdivisions比如从16调到32、64这相当于减小了每次送入显卡的图片数量。如果调大subdivisions到很大值比如等于batch还不行再考虑减小batch。注意调整subdivisions不会影响最终的学习效果因为它只是改变了计算的“批次”但累积梯度对应的batch没变。而调整batch则会直接影响优化过程。测试/推理模式注释掉的batch1, subdivisions1是用于测试或推理的配置。此时不需要累积梯度所以batch和subdivisions都设为1表示每次处理一张图。width,height,channels定义了输入网络的图片尺寸和通道数。width608, height608YOLOv4的默认输入分辨率。YOLO系列要求输入图片必须是正方形且尺寸是32的倍数因为网络中有5次步长为2的下采样2^532。608是常用的尺寸在速度和精度间取得了较好平衡。你也可以尝试416或832。调整影响增大width/height会让模型看到更多细节通常能提升小目标检测精度但会显著增加计算量和显存消耗减慢训练和推理速度。减小尺寸则相反。注意如果你改变了这里的输入尺寸后续所有卷积层、路由层中的尺寸计算都会基于此改变但YOLO检测头[yolo]层中的anchors尺寸是相对于网络输入尺寸这里是608预设的。如果你改变了输入尺寸强烈建议根据新尺寸重新聚类生成anchors否则性能会下降。channels3彩色RGB图像。2.2 学习率与优化策略momentum0.949 decay0.0005 learning_rate0.0013 burn_in1000 max_batches 500500 policysteps steps400000,450000 scales.1,.1learning_rate初始学习率。这是最重要的超参数之一。0.0013是YOLOv4作者针对batch64设置的一个经验值。学习率与batch size通常有关。如果你调整了batch学习率可能也需要按线性或平方根规则缩放。例如如果你把batch从64减小到16学习率可能也需要相应减小。burn_in学习率热身warm-up步数。在前burn_in次迭代中学习率会从一个很小的值计算公式为lr * (current_iter / burn_in)^4逐渐上升到设定的learning_rate。这有助于在训练初期稳定训练过程防止梯度爆炸。1000次迭代对于大数据集是合理的。policy,steps,scales学习率衰减策略。policysteps表示采用“阶梯式”衰减。steps400000,450000在训练到第40万次和45万次迭代时触发学习率衰减。scales.1,.1衰减系数。到达第一个step时学习率乘以0.1到达第二个step时再在已经衰减的基础上再乘以0.1。例如初始学习率0.0013在40万次迭代后变为0.00013在45万次迭代后变为0.000013。调整建议max_batches最大迭代次数需要根据你的数据集大小设定。官方COCO数据集很大所以设了50万次。对于较小的数据集你可能需要减少max_batches并相应调整steps。一个经验法则是steps可以设为max_batches的80%和90%左右。momentum动量参数。用于随机梯度下降SGD优化器帮助加速收敛并逃离局部极小值。0.949是一个较高的值在YOLOv4中很常见。decay权重衰减L2正则化系数。用于防止过拟合通过对大的权重进行惩罚。0.0005是标准值。2.3 数据增强与训练技巧angle0 saturation 1.5 exposure 1.5 hue.1这是Darknet内置的数据增强参数在训练时在线随机应用可以极大地提升模型的泛化能力。angle随机旋转角度。这里设为0表示不进行旋转增强。有些配置可能会设置一个较小的值如angle10来增加多样性。saturation,exposure,hue分别控制饱和度、曝光度和色调的随机调整范围。saturation1.5饱和度变化范围是 [1/1.5, 1.5]。exposure1.5曝光度变化范围是 [1/1.5, 1.5]。hue.1色调变化范围是 [-0.1, 0.1]因为色调范围是0~1。调整建议对于自然场景目标检测这些默认值通常工作良好。如果你的数据集图像质量、光照条件非常统一可以适当增强这些值以增加多样性。如果数据集本身已经非常多样且包含各种光照条件可以降低这些值甚至关闭设为1或0防止引入过多噪声。mosaic1Mosaic数据增强YOLOv4引入的强大增强技术默认开启mosaic1。它会随机选取4张训练图片将它们拼接成一张大图进行训练。这样做的好处是丰富上下文让模型在一张图中看到更多样化的背景和目标组合。模拟小目标原本正常的物体在拼接后可能变成相对较小的目标提升了模型检测小目标的能力。提升批归一化BN效果由于一张图就包含了4张图的信息相当于在一个“批次”内统计了更丰富的均值和方差使得BN层的统计更稳定。注意Mosaic增强会显著增加显存消耗因为一张拼接图的尺寸可能很大。如果训练时出现显存不足可以考虑关闭它mosaic0但会损失一部分性能。3. 网络骨架与核心层类型解析在[net]段之后就是网络层的具体定义了。YOLOv4采用了CSPDarknet53作为主干特征提取网络BackboneSPPSpatial Pyramid Pooling和PANetPath Aggregation Network作为颈部Neck最后是YOLO检测头Head。我们首先理解几种核心的层类型。3.1 卷积层[convolutional]这是最基础的构建块。一个典型的卷积层配置如下[convolutional] batch_normalize1 filters32 size3 stride1 pad1 activationmishbatch_normalize是否使用批归一化Batch Normalization。1为使用0为不使用。在YOLOv4中几乎每个卷积层后都跟了BN层这是稳定训练、加速收敛的关键。如果关闭BN通常需要非常小心地调整学习率。filters该卷积层输出特征图的通道数。它决定了这一层能学习到多少种不同的特征。size卷积核的大小。3表示3x3的卷积核这是最常用的尺寸。stride卷积步长。1表示滑动步长为1输出特征图尺寸不变。2表示步长为2输出特征图宽高会减半用于下采样。pad填充padding。1表示在输入特征图周围填充1圈0。当size3, stride1, pad1时输出特征图尺寸保持不变。这是一个常用组合。activation激活函数。YOLOv4主干网络中大量使用了mish激活函数x * tanh(softplus(x))相比传统的LeakyReLU它在某些情况下能提供更好的梯度流和精度。在网络的更深处你可能会看到activationleaky。3.2 CSP 结构[convolutional] 与 [route] 的组合CSPCross Stage Partial connections是CSPDarknet53的核心旨在解决大型Backbone中梯度信息重复的问题。它在.cfg中不是以一个单独的[csp]层出现而是通过[convolutional]、[route]和[shortcut]的组合来实现。理解其配置是关键。我们看一个简化示例取自CSP块的一部分# 第一部分主路径分支 [convolutional] ... filters64 ... [convolutional] ... filters64 ... # 第二部分捷径分支 [route] layers-2 # 取当前层往前数第2层的输出 [convolutional] ... filters64 ... [route] layers-1, -3 # 将捷径分支的处理结果(-1)和主路径分支的输入(-3)拼接起来输入特征图被分成两部分在代码中实现配置里不直接体现。一部分走主路径经过多个卷积层如两个[convolutional]。另一部分走捷径分支通过[route] layers-2获取输入然后经过一个卷积层。最后通过[route] layers-1, -3将主路径的输出-1和捷径分支处理后的结果-3这里-3需要根据实际层数计算在通道维度上进行拼接concat。拼接后的特征图通道数会翻倍后面通常会接一个[convolutional]层来调整通道数。核心思想让梯度流通过两条路径传播缓解梯度消失同时减少计算量。3.3 路由与拼接层[route][route]层是Darknet中实现特征融合和分支操作的关键。它本身不进行计算只负责“路由”数据。[route] layers-1, -3, -5, -6layers指定要获取哪些前面层的输出。参数可以是正数从网络开头算起的绝对索引从0开始或负数从当前层往前数的相对索引-1表示上一层。功能单个值如layers-4直接获取指定层的输出。多个值如layers-1, -3将指定层的输出在通道维度channel dimension上进行拼接。这就要求这些层输出的特征图在高度height和宽度width上必须完全相同否则会报错。拼接后的通道数是各层通道数之和。在YOLOv4中的应用构建FPN/PANet通过[route]层将深层的高语义特征图与浅层的高分辨率特征图进行拼接实现多尺度特征融合。实现残差连接与[shortcut]层配合见下文。实现CSP结构如上节所述。3.4 残差连接层[shortcut][shortcut]层实现了残差连接Residual Connection是构建深度网络、解决梯度消失问题的核心。[shortcut] from-3 activationlinearfrom指定要与当前层输入进行相加的“捷径”来源层。例如from-3表示取当前层往前数第3层的输出。activation通常为linear表示相加操作后不接激活函数因为残差块通常的设计是F(x) x激活函数在F(x)内部。工作原理[shortcut]层会将它自身的输入即上一层的输出与from指定的层的输出进行逐元素相加element-wise addition。这就要求两个张量必须形状完全相同包括batch, channels, height, width。与[route]的区别[route]是拼接concat增加通道数[shortcut]是相加add不改变形状是特征的重用和增强。3.5 空间金字塔池化层[maxpool] 与 [route]SPP层在YOLOv4中用于增加主干网络提取特征的感受野它对同一特征图进行多种尺度的最大池化然后将结果拼接。[maxpool] stride1 size5 [maxpool] stride1 size9 [maxpool] stride1 size13 [route] layers-3, -2, -1, -4首先一个输入特征图假设来自-4层。经过三个并行的[maxpool]层它们的size池化核大小分别是5, 9, 13但stride1并且通过pad的设置在代码中自动计算cfg里不显示使得输出特征图的空间尺寸H, W与输入保持一致。不同大小的池化核捕获了不同范围的上下文信息。最后通过一个[route] layers-3, -2, -1, -4层将三个池化后的结果-3, -2, -1和原始的输入-4在通道维度上拼接起来。这样输出的特征图就融合了多尺度的信息。3.6 上采样层[upsample]用于将特征图的尺寸放大通常用在特征金字塔网络中将深层的、低分辨率的特征图上采样以便与浅层的高分辨率特征图进行融合。[upsample] stride2stride上采样倍数。stride2表示将特征图的高和宽都放大2倍。Darknet默认使用最近邻插值nearest neighbor interpolation方法。4. YOLO检测头与输出解析经过Backbone和Neck特征图被送到YOLO检测头进行最终的分类和定位预测。在yolov4.cfg中有三个[yolo]层分别对应三个不同尺度的检测输出用于检测不同大小的目标。4.1 [yolo] 层配置详解我们以第一个[yolo]层为例对应最大的特征图用于检测小目标[yolo] mask 6,7,8 anchors 12, 16, 19, 36, 40, 28, 36, 75, 76, 55, 72, 146, 142, 110, 192, 243, 459, 401 classes80 num9 jitter.3 ignore_thresh .7 truth_thresh 1 random1 scale_x_y 1.05 iou_thresh0.213 cls_normalizer1.0 iou_normalizer0.07 iou_lossciou nms_kindgreedynms beta_nms0.6mask指定使用哪一组anchors。anchors列表定义了9组先验框的宽高每两个数字一组共9组顺序是[w1, h1, w2, h2, ...]。mask 6,7,8表示使用第6、7、8组anchors索引从0开始。这三个anchors对应于当前检测层尺度最匹配的预设框尺寸。anchors先验框anchor boxes的尺寸。这些尺寸是相对于网络输入图片如608x608的绝对像素值是通过在训练集上使用k-means聚类得到的。三个[yolo]层共享这个完整的anchors列表但通过mask选取不同的子集。大尺度的检测层检测小目标使用较小的anchors小尺度的检测层检测大目标使用较大的anchors。classes数据集的目标类别数。COCO是80如果你训练自己的数据集需要修改为你的类别数。numanchors的总数这里是9。jitter随机抖动系数。在训练时会对输入图片进行随机的长宽比扰动resize时增加数据多样性。0.3是常用值。ignore_thresh忽略阈值。在计算损失时如果某个预测框与所有真实框的最大IoU交并比小于这个阈值0.7且它又不是负责预测该目标的anchor即不是与真实框IoU最大的那个anchor那么这个预测框的“对象性obj”损失会被忽略。这有助于减少简单负样本对训练的干扰让模型更关注难例。truth_thresh在计算损失时如果一个anchor与真实框的IoU超过此阈值这里是1实际上意味着只要匹配上就算它就会参与边界框回归损失的计算。通常设为1。random是否在训练时随机多尺度训练。1为开启。Darknet会在每个批次batch后随机从一组预定义的尺度中如{320, 352, ..., 608}选择一个作为新的输入尺寸进行训练。这能极大地提升模型对不同尺度的鲁棒性。这是YOLOv3/v4的一个强大训练技巧。scale_x_yYOLOv4引入的“消除网格敏感度Eliminate grid sensitivity”技巧。在v3中预测的边界框中心坐标被限制在其所属的网格单元内这可能导致对于靠近网格边界的物体预测不佳。scale_x_y通常1如1.05, 1.2放大了坐标预测的范围允许中心点偏移到相邻网格提升了定位精度。每个[yolo]层可以有不同的值。iou_thresh,cls_normalizer,iou_normalizer,iou_loss,nms_kind,beta_nms这些是YOLOv4在损失函数和非极大值抑制NMS上的改进。iou_lossciou使用CIoU Loss作为边界框回归损失。相比传统的IoU Loss和GIoU LossCIoU考虑了重叠面积、中心点距离和长宽比收敛更快定位更准。iou_thresh0.213在计算CIoU Loss时的一个阈值参数。iou_normalizer0.07和cls_normalizer1.0分别是边界框回归损失和分类损失的权重系数。用于平衡不同损失项的重要性。nms_kindgreedynms和beta_nms0.6指定NMS的类型和参数。greedynms是标准的贪婪NMS。beta_nms可能与DIOU-NMS有关是YOLOv4的另一个可选优化。4.2 三个检测层的分工与特征图流向YOLOv4的三个检测层分别位于网络的不同深度对应不同尺度的特征图第1个[yolo]层在配置文件靠后部分连接到尺度最大的特征图如76x76如果输入608则下采样8倍。mask通常对应较小的anchors如索引6,7,8主要负责检测小目标。第2个[yolo]层中间连接到中等尺度的特征图如38x38下采样16倍。mask对应中等大小的anchors如索引3,4,5负责检测中等目标。第3个[yolo]层最后连接到尺度最小的特征图如19x19下采样32倍。mask对应最大的anchors如索引0,1,2主要负责检测大目标。这三个层的输出会通过复杂的[route]和[convolutional]操作进行特征融合即PANet结构使得每个检测层都融合了深层语义信息和浅层位置信息从而提升多尺度检测能力。5. 关键参数调整实战与避坑指南理解了每个参数的含义我们来看看在实际项目中如何调整它们以及有哪些常见的“坑”。5.1 根据硬件调整 batch 和 subdivisions这是训练开始前必须做的。假设你有一张8GB显存的显卡如RTX 2070想用batch64训练608尺寸的YOLOv4很可能会爆显存。正确步骤先将subdivisions调大比如设为32或64。这意味着每次处理64/641张图。如果还OOM说明一张608的图就超过8G显存了这不太可能通常是因为模型本身太大。如果subdivisions调到等于batch即每次1张还OOM就必须减小batch。可以尝试batch32,subdivisions8每次4张或者batch16,subdivisions4每次4张。调整学习率记住batch减小了学习率通常也要相应减小。一个经验规则是线性缩放new_lr old_lr * (new_batch / old_batch)。例如从batch64, lr0.0013降到batch16新学习率可以设为0.0013 * (16/64) 0.000325。你也可以使用平方根缩放new_lr old_lr * sqrt(new_batch / old_batch)。同步调整burn_in和steps如果你的总迭代次数max_batches因数据集变小而减少了那么steps学习率衰减点和burn_in也需要按比例调整。例如原配置针对50万次迭代你的数据集可能只需要10万次那么steps可以设为80000,90000burn_in设为1000或按比例减小。5.2 修改输入尺寸 width/height 的连锁反应如果你想用416x416而不是608x608来训练以加快速度。必须做的修改[net]下的width和height为416。重新聚类anchors这是最关键的一步。官方的anchors是针对608x608聚类得到的。输入尺寸变小目标的绝对像素尺寸也变小了原来的anchors可能不再合适。你需要用自己的训练集图片在416x416的尺度下重新运行k-means聚类Darknet源码里有darknet detector calc_anchors ...命令然后用得到的新anchors替换[yolo]层里的anchors列表。检查random多尺度训练如果开启确保预定义的尺度范围包含了你的新尺寸416以及其附近尺寸。可选调整网络结构本身是尺度不变的所以理论上只改输入尺寸和anchors即可。但有些数据增强如mosaic在较小尺寸下可能效果会打折扣可以保持默认。5.3 训练自己的数据集修改 classes 与 anchors假设你要训练一个检测“猫”、“狗”两个类别的模型。修改classes将三个[yolo]层中的classes80全部改为classes2。修改对应卷积层filters每个[yolo]层前面紧邻的[convolutional]层其filters数需要根据公式计算filters (classes 5) * 3。这里的5代表4个框坐标x,y,w,h加1个对象置信度3代表每个网格预测3个anchor框。对于COCO的80类(805)*3255所以你会看到[yolo]层前的卷积层filters255。对于你的2类(25)*321所以你需要把这三个[convolutional]层的filters从255改为21。务必找到正确的层它们通常就在[yolo]层上面一两行。重新聚类anchors强烈建议使用你自己的数据集图片重新聚类anchors这能显著提升模型在你数据上的性能。使用Darknet提供的命令即可。5.4 数据增强参数调优数据增强是防止过拟合、提升泛化能力的利器但过犹不及。何时增强如果你的数据集背景单一、目标姿态变化少、光照条件固定比如工业质检可以增强saturation,exposure,hue甚至可以开启angle小角度旋转并确保mosaic1。何时减弱如果你的数据集已经非常多样化来自各种真实场景比如自动驾驶街景过强的颜色抖动和Mosaic可能会让模型学习到不真实的关联。可以考虑降低sat,exp,hue的值如设为1.2或者将mosaic设为0。一个技巧在训练后期例如最后10%的迭代次数可以关闭Mosaic增强让模型专注于学习更精确的定位。jitter这个参数对性能影响较大。0.3是一个稳健的值。如果目标尺度变化不大可以适当减小如0.2如果目标尺度变化剧烈可以保持或略微增大。5.5 学习率策略与损失权重微调学习率stepsmax_batches和steps需要根据你的数据集大小设定。一个粗略的估计是遍历整个数据集一次为一个epoch。总迭代次数max_batches可以设为epoch数 * (训练集图片数 / batch)。steps通常设为max_batches的0.8和0.9倍。例如你有10000张图batch64想训练100个epoch那么max_batches 100 * (10000/64) ≈ 15625。steps可以设为12500, 14062。损失权重iou_normalizer和cls_normalizer一般不需要动除非你发现模型在某个任务上严重偏向比如定位极准但分类全错或者反过来。在自定义数据集上如果类别极度不均衡可以尝试调整cls_normalizer给样本少的类别更大的权重但这需要在代码层面修改cfg参数只控制整体分类损失权重。CIoU Loss参数iou_thresh0.213和scale_x_y1.05是作者调优后的结果在大多数情况下表现良好除非有特殊需求否则不建议新手改动。读懂yolov4.cfg只是第一步但却是至关重要的一步。它让你从“黑盒使用者”变成了“白盒调试者”。下次当你的模型训练出现loss震荡、不收敛、或者检测效果不佳时你不会再茫然无措而是可以有针对性地检查是不是输入尺寸和anchors不匹配是不是batch size太大导致学习率需要调整是不是数据增强太强引入了噪声这份配置文件就是你的地图而其中的参数就是你可以调节的旋钮。掌握了它们你才能真正让YOLOv4为你所用。在后续的笔记中我们会继续深入Darknet的源码看看这些配置是如何在代码中实现的以及训练、测试、推理的完整流程。
返回列表