资讯动态

YOLOv4训练避坑指南:cfg参数详解与实战调优

发布时间:2026/10/15 4:06:31 来源:尧图企业网站定制
1. 从cfg文件说起YOLOv4训练绕不开的那道坎如果你第一次拿到YOLOv4的工程目录打开cfg文件夹看到那一堆.cfg文件大概率会有点懵。yolov4.cfg、yolov4-custom.cfg、yolov4-tiny.cfg、yolov4-tiny-custom.cfg……每个文件打开都是几百行密密麻麻的配置项[net]、[convolutional]、[route]、[shortcut]、[yolo]这些块一个接一个参数名还都是缩写。很多人第一次改cfg的时候改完一跑就报错要么是维度对不上要么是训练loss直接nan要么是训练完了检测不出东西。这篇内容就是围绕YOLOv4的cfg参数和训练流程来展开的。我会把cfg文件里每个关键参数的作用、修改时容易踩的坑、训练前必须检查的几件事、以及训练过程中常见的异常和排查思路尽量讲透。适合已经跑通过YOLOv4推理、准备用自己的数据集做训练的人也适合训练过程中遇到问题想搞清楚原因的人。读完之后你应该能独立完成一份针对自己数据集的cfg配置并且知道训练时该盯哪些指标、出了问题往哪个方向查。先说一个基本认知YOLOv4的cfg文件本质上是一个网络结构定义文件它描述的是每一层的类型、通道数、卷积核大小、步长、输入输出维度以及检测头的锚框和类别数。训练的时候框架会按照这个文件逐层搭建网络加载预训练权重然后在你提供的数据集上做微调。所以cfg改错一个参数轻则精度下降重则直接跑不起来。这不是危言耸听我见过太多人因为filters没跟着classes改训练了半天结果检测头输出维度对不上白跑。2. cfg文件里真正需要你动手改的只有这几处2.1 先搞清楚哪些参数是“结构参数”哪些是“训练参数”YOLOv4的cfg文件里参数很多但并不是所有参数都需要你改。大部分参数是网络结构本身的一部分改了会破坏预训练权重的对应关系。真正需要你根据自己数据集调整的其实就那么几类。第一类是[net]块里的训练相关参数比如batch、subdivisions、width、height、channels、learning_rate、max_batches、steps、policy这些。第二类是每个[yolo]块前面的那个[convolutional]层里的filters它必须等于(classes 5) * 3。第三类是每个[yolo]块里的classes和anchors。第四类是[yolo]块里的mask它决定了每个检测头用哪几个锚框。其他的参数比如每个卷积层的size、stride、pad、activation以及[route]、[shortcut]、[upsample]这些都是网络结构的一部分除非你要做结构上的魔改否则不要动。动了之后预训练权重就对不上了等于从头训练效果会差很多。2.2[net]块训练超参的集中营打开yolov4-custom.cfg最上面就是[net]块。这里我挑几个最关键的参数说。batch和subdivisions决定了每次送入网络的样本数和梯度累积的次数。实际参与一次权重更新的样本数是batch / subdivisions。比如batch64、subdivisions16就是每次送4张图累积16次梯度再更新一次。这个设置直接影响显存占用和训练稳定性。显存小就把subdivisions调大但别调太大否则等效batch太小BN层的统计会不准。width和height是网络输入尺寸。YOLOv4默认是608x608但你可以改成416x416或者512x512。改小能提速但小目标的检测能力会下降。注意这两个值必须是32的倍数因为网络有5次下采样每次下采样2倍总共32倍。如果你设成500框架会自动调整到最近的32倍数但最好自己设对。learning_rate是初始学习率。YOLOv4默认0.0013配合policysteps和steps400000,450000、max_batches500200来用。如果你用自己的数据集max_batches一般设成classes * 2000但不少于4000。steps设成max_batches的80%和90%。比如你有3个类max_batches6000steps4800,5400。channels3不用改除非你处理的是灰度图或者多光谱图。mosaic、cutmix这些数据增强参数在YOLOv4里默认是开的如果你数据集很小可以保留如果数据集很大且多样性足够可以关掉一部分来加速训练。2.3filters的计算一个数字错全盘皆输这是最容易出错的地方。每个[yolo]块前面都有一个[convolutional]层它的filters必须等于(classes 5) * 3。为什么是5因为每个锚框要预测4个坐标偏移量加1个置信度共5个值。为什么乘3因为每个检测头有3个锚框。假设你有3个类那么filters (3 5) * 3 24。如果你有80个类filters (80 5) * 3 255。YOLOv4有三个检测头分别在 stride 8、16、32 的特征图上所以cfg里有三个[yolo]块每个前面的[convolutional]层的filters都要改成同一个值。我见过有人只改了第一个后面两个忘了改训练的时候直接报维度不匹配。也见过有人把filters算成了(classes 5) * 3以外的值比如忘了乘3结果检测头输出通道数不对训练loss一直不降。所以改完cfg之后一定要用搜索功能把所有的filters找出来确认三个检测头前面的那个都改了。2.4classes和anchors类别数和锚框的适配每个[yolo]块里都有classes和anchors。classes改成你的类别数三个[yolo]块都要改。anchors是9个锚框的宽高按从小到大排列每3个一组分配给三个检测头通过mask来指定。YOLOv4默认的anchors是在COCO数据集上聚类得到的针对的是80类通用目标。如果你的数据集目标尺寸分布和COCO差异很大比如你检测的是工业零件上的微小缺陷或者航拍图像中的大型车辆那么默认锚框可能不合适。这时候可以用k-means在自己的数据集标注框上重新聚类得到9个新的锚框替换掉默认值。mask参数决定了每个检测头用哪三个锚框。默认是mask 6,7,8、mask 3,4,5、mask 0,1,2分别对应stride 32、16、8的检测头。大锚框给大特征图小锚框给小特征图这个顺序不要乱。如果你重新聚类了锚框也要按大小重新分配mask。3. 训练之前这几项检查不做等于白跑3.1 数据集格式和路径配置YOLOv4训练需要两个文件obj.data和obj.names。obj.names里每行一个类别名顺序要和标注文件里的class id对应。obj.data里指定classes、train、valid、names、backup这几个路径。train和valid指向的是图片路径列表文件每行一个图片的绝对路径或相对路径。这里有个坑路径里不要有中文和空格。我试过路径里有空格训练直接报错找不到文件。另外backup目录要提前建好否则训练到第一次保存权重的时候会报错。valid可以指向和train一样的列表但最好留出一部分做验证方便观察过拟合。标注文件是YOLO格式的txt每行class_id x_center y_center width height坐标都是归一化到0到1之间的。如果你用的是VOC格式的XML或者COCO格式的JSON需要先转换。转换脚本网上很多但要注意坐标归一化的分母是图片的宽和高不是最大边。这个细节错了框的位置会整体偏移。3.2 预训练权重的加载与层匹配YOLOv4训练一般会加载yolov4.conv.137这个预训练权重它包含了骨干网络的前137层。加载的时候框架会按层名匹配如果cfg改了结构比如改了某个卷积层的filters那么这一层及之后的权重就加载不上会随机初始化。所以改cfg的时候尽量只改检测头相关的部分不要动骨干网络。如果你确实需要改骨干网络那就做好从头训练的准备或者用其他方式做迁移。加载预训练权重的时候终端会打印哪些层加载成功、哪些层跳过。如果跳过的层很多说明你的cfg改动太大需要重新考虑。3.3 显存与batch size的平衡显存不够是训练时最常见的问题。报错一般是CUDA out of memory。解决办法有几个调大subdivisions、调小width和height、调小batch。但要注意batch和subdivisions的比值才是实际batch size调大subdivisions只是减少了每次送入网络的图片数等效batch size不变但显存占用会降低。如果显存实在紧张可以把width和height降到416甚至320但精度会受影响。另一个办法是用yolov4-tiny它的参数量小很多显存占用低速度快但精度也低一些。选哪个取决于你的任务对精度的要求和对速度的要求。4. 训练启动之后终端里那些数字到底在说什么4.1 loss曲线的解读与异常判断训练启动后终端会不断打印类似这样的行v3 (608x608) 1: 0.523, 0.412 avg loss, 0.001300 rate, 0.000000 seconds这里的1是当前batch的序号0.523是当前batch的总loss0.412 avg loss是滑动平均loss0.001300 rate是当前学习率。总loss是各项loss的加权和包括框回归loss、置信度loss、分类loss。正常情况下avg loss会随着训练逐渐下降最后稳定在一个较低的值。如果loss一直不降或者震荡很厉害可能的原因有学习率太大、标注有问题、cfg里filters或classes没改对、预训练权重没加载上。如果loss突然变成nan一般是学习率太大或者数据里有异常值比如坐标超出0到1范围。我一般会关注avg loss的下降趋势而不是单个batch的loss。单个batch的loss波动很正常尤其是用了mosaic增强之后。如果avg loss在几百个batch之后还在0.5以上那基本可以判断有问题。4.2 学习率调整策略的实际效果YOLOv4默认用的是steps策略在指定的step处把学习率乘以scale默认0.1。比如steps400000,450000max_batches500200那么在400000步时学习率降到原来的0.1450000步时再降0.1。这个策略的目的是在训练后期减小学习率让模型收敛到更精细的解。如果你用自己的数据集max_batches设得比较小比如6000那么steps设成4800和5400。学习率在4800步之前保持初始值4800到5400之间降为0.1倍5400之后降为0.01倍。这样可以在有限步数内完成收敛。有时候你会发现训练到后期loss还在缓慢下降但max_batches已经到了训练自动停止。这时候可以适当增大max_batches或者用policycosine让学习率按余弦曲线衰减可能效果更好。但cosine策略需要调cosine_power参数默认是4调大衰减更快。4.3 权重保存与断点续训训练过程中框架会每隔一定步数保存一次权重到backup目录文件名类似yolov4-custom_1000.weights、yolov4-custom_2000.weights。保存间隔由[net]块里的save参数控制默认是每1000步保存一次。如果训练中断了可以用最后保存的权重继续训练命令里加-clear或者不加取决于框架版本。断点续训的时候要注意学习率会从初始值重新开始而不是从上次中断的地方继续。如果你不想这样可以手动改cfg里的learning_rate或者用-start参数指定从哪个step开始。但大多数情况下直接续训也能work只是学习率曲线会有点不一样。另外保存的权重文件会占用磁盘空间每个文件大概200多MB。如果训练步数很多backup目录会很大。可以定期清理旧的权重只保留最近的几个和最好的几个。判断哪个权重最好一般看验证集上的mAP或者看avg loss最低的那个。5. 那些年我踩过的cfg坑和训练翻车现场5.1 改了classes忘了改filters训练直接崩这是我第一次训练YOLOv4时犯的错。当时数据集有5个类我把三个[yolo]块里的classes都改成了5但忘了改前面[convolutional]层的filters。结果训练启动后loss一直是nan终端疯狂打印nan。我一开始以为是学习率太大调小之后还是nan。后来仔细检查cfg才发现filters还是默认的255而classes5对应的应该是(55)*330。改过来之后训练立刻正常了。这个坑的本质是检测头的输出通道数必须和(classes5)*3一致否则网络输出的维度和损失函数期望的维度对不上计算loss的时候就会出现nan或者直接报错。所以改cfg的时候一定要把classes和filters成对修改三个检测头都不能漏。5.2 锚框不匹配小目标全丢有一次我训练一个检测PCB板上微小缺陷的模型数据集里目标都很小大部分在20x20像素以下。我用默认的YOLOv4锚框训练结果训练完之后大目标检测还行小目标几乎全丢。后来分析发现默认锚框里最小的几个是(12,16)、(19,36)、(40,28)对于20x20以下的目标来说还是太大了。解决办法是用k-means在自己的数据集上重新聚类锚框。具体做法是把所有标注框的宽高提取出来用k-means聚成9类得到9个中心点作为新的锚框。然后按大小排序重新分配给三个检测头的mask。改完之后再训练小目标的召回率明显提升。这里有个细节k-means的距离度量要用1 - IOU而不是欧氏距离。因为锚框的匹配程度是用IOU衡量的用欧氏距离聚类出来的锚框不一定IOU最优。很多开源的锚框聚类脚本用的就是1 - IOU可以直接拿来用。5.3 学习率太大loss震荡不收敛还有一次我用一个比较大的数据集训练想着数据多可以承受大一点的学习率就把learning_rate从0.0013调到了0.01。结果训练开始后loss剧烈震荡有时候降到0.3有时候又跳到2.0以上。训练了几千步之后avg loss还是居高不下。后来把学习率调回0.0013并且把burn_in打开让学习率在前1000步从0逐渐升到初始值训练就稳定多了。burn_in的作用是避免训练初期学习率过大导致权重更新过猛对于大batch训练尤其有用。YOLOv4的cfg里默认burn_in1000但如果你改了max_batchesburn_in也可以相应调整。学习率的设置没有绝对的标准但有一个经验法则如果你的batch size是64初始学习率在0.001到0.002之间比较安全。如果batch size更大可以适当增大学习率。如果训练过程中loss震荡首先考虑调小学习率。5.4 数据增强开太猛小数据集反而学不好YOLOv4默认开启了mosaic、cutmix、翻转、缩放等多种数据增强。对于大数据集这些增强能提升泛化能力。但对于小数据集比如只有几百张图开太猛的增强反而会让模型学不到东西。因为每张图被增强得面目全非模型很难从中学到有效的特征。我试过在一个只有500张图的数据集上训练默认增强全开结果训练了10000步mAP还是很低。后来把mosaic和cutmix关掉只保留翻转和缩放mAP反而上去了。所以数据增强的强度要根据数据集大小来调整。小数据集可以适当减弱增强或者用迁移学习的方式先冻结骨干网络训练检测头再解冻全部微调。6. 训练完成之后怎么判断模型能不能用6.1 用验证集算mAP别只看loss训练结束后backup目录里会有一堆权重文件。选哪个不能只看loss最低的那个因为loss低不一定mAP高。正确的做法是用验证集算mAP选mAP最高的那个权重。算mAP的命令一般是./darknet detector map obj.data yolov4-custom.cfg backup/yolov4-custom_best.weights终端会打印每个类别的AP和所有类别的mAP。mAP在0.5 IOU阈值下的值就是常说的mAP0.5。如果mAP0.5能到0.7以上基本可用如果只有0.3、0.4那说明模型还没学好需要检查数据、cfg或者训练参数。算mAP的时候要注意验证集要和训练集独立不能有重叠。如果验证集里的图片在训练集里出现过mAP会虚高实际部署效果会很差。另外验证集的数量要足够至少每个类别有几十个样本否则mAP波动会很大。6.2 实际推理测试看漏检和误检mAP只是一个统计指标实际能不能用还要看推理效果。用训练好的权重跑几张测试图./darknet detector test obj.data yolov4-custom.cfg backup/yolov4-custom_best.weights test.jpg然后看检测结果。重点关注两类问题漏检和误检。漏检就是目标没被检测出来可能是目标太小、太暗、被遮挡或者训练集里这类样本太少。误检就是把背景或者其他东西当成目标可能是训练集里负样本不够或者置信度阈值设得太低。如果漏检多可以尝试降低置信度阈值或者增大输入尺寸或者补充更多难样本。如果误检多可以提高置信度阈值或者增加负样本。这些调整都需要在验证集上验证效果不能凭感觉调。6.3 模型剪枝与量化部署前的最后一步如果模型要在边缘设备上跑可能还需要做剪枝和量化。剪枝是去掉一些不重要的通道减小模型体积和计算量。量化是把浮点权重转成定点进一步压缩模型。YOLOv4有一些开源的剪枝和量化工具但操作起来有一定门槛而且可能会损失一些精度。我的建议是如果边缘设备性能够用直接跑原版YOLOv4或者YOLOv4-tiny就行不一定非要剪枝量化。如果确实需要先在验证集上评估剪枝量化后的mAP确认精度损失在可接受范围内再部署。不要为了压缩而压缩精度才是第一位的。7. 一些让训练更顺手的实操习惯训练YOLOv4这件事说难不难说简单也不简单。cfg参数就那些但每个参数背后都有它的逻辑。我自己的习惯是每次改cfg之前先备份一份原始文件改完之后用diff对比一下确认只改了该改的地方。训练启动后先看前100个batch的loss如果正常再让它跑如果异常立刻停下来查原因不要让它白跑几个小时。另外训练日志最好重定向到文件里方便后面分析。命令大概是./darknet detector train obj.data yolov4-custom.cfg yolov4.conv.137 -gpus 0 21 | tee train.log这样终端能看到实时输出同时日志也保存下来了。训练完之后可以用脚本把avg loss提取出来画曲线直观地看收敛情况。最后说一个容易被忽略的点训练集的标注质量比什么都重要。标注框位置不准、类别标错、漏标这些都会直接影响模型效果。我见过有人训练了很久效果不好最后发现是标注文件里坐标没归一化。所以在训练之前花点时间检查标注比后面调参有用得多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑