当前位置: 首页 > news >正文

从YOLOv1到v3全解析:原理演进+PyTorch实战训练(超详细

YOLO(You Only Look Once)作为单阶段目标检测的开山之作,凭借速度快、端到端、工程友好的优势,成为实时检测领域的标配算法。本文从v1→v2→v3梳理核心演进逻辑,并手把手带你用YOLOv3完成自定义数据集训练,理论+实战一步到位。

一、YOLO核心定位:单阶段检测的王者

1.目标检测分为两大流派:

• Two-stage:Faster R-CNN/Mask R-CNN → 精度高、速度慢(≈5FPS)

• One-stage:YOLO/SSD → 速度极快、适合实时检测,精度持续追赶

YOLO的本质:把检测变成回归问题,一次前向推理直接输出目标位置+类别+置信度,无需候选框生成,这是它快的根本原因。

2. IOU(交并比)

IOU(Intersection over Union)用来衡量预测框与真实框的重叠程度,是目标检测最基础的评价标准。

公式:IOU = 交集面积 / 并集面积

  • 交集:两个框重叠区域
  • 并集:两个框覆盖的所有区域
  • 取值范围:0 ~ 1
  • 常用阈值:0.5(mAP50)、0.5~0.95(mAP50-95)
  • IOU = 1:完全重合
  • IOU ≥ 0.5:通常认为检测正确
  • IOU = 0:无重叠,完全错误

3. mAP(平均精度均值)

mAP(Mean Average Precision)是综合衡量检测模型好坏的核心指标,比单纯看精确率 / 召回率更全面。

先看懂 4 个基础值(混淆矩阵)
  • TP(真正例):预测正确,框住目标
  • FP(假正例):预测错误,把背景当目标
  • FN(假反例):漏检,有目标没框出来
两个基础率
  • 精确率 Precision = TP / (TP+FP)预测结果里,有多少是对的
  • 召回率 Recall = TP / (TP+FN)真实目标里,有多少被找出来
常用 mAP 定义
  • mAP50:IoU=0.5 时的 mAP(宽松、常用)
  • mAP50-95:IoU 从 0.5 到 0.95、步长 0.05 的平均 mAP(更严格、更全面)

二、YOLOv1:开创单阶段检测时代

1. 核心思想

• 图像划分为 S×S网格(默认7×7),目标中心点落在哪个网格,该网格就负责预测此目标。

• 每个网格预测 2个边界框 + 置信度 + 20类概率,最终输出 7×7×30 张量。

• 置信度 = 有无目标 × 预测框与真实框IoU。

2. 网络结构

• 基于GoogLeNet改进:24个卷积层 + 2个全连接层

• 输入尺寸:448×448

• 无先验框,纯回归定位。

3. 损失函数(三大组成)

总损失 = 坐标损失(x,y,w,h) + 置信度损失(有无目标) + 分类损失(类别概率)

• 对有目标框的坐标损失加大权重

• 对无目标框的置信度损失降低权重,缓解样本不均衡。

4. YOLOv1优缺点

优点:速度快(45FPS)、端到端、简单易用
缺点:小目标差、重叠目标漏检、每个网格只能预测1类、框精度一般

三、YOLOv2(YOLO9000):精度与速度双升级

v2针对性解决v1缺陷,是工程化里程碑版本。

1. 关键改进

1. Batch Norm:卷积层后全加BN,放弃Dropout,mAP↑2%。

2. 高分辨率分类器:训练用448×448,适配检测分辨率,mAP↑4%。

3. Anchor先验框:用K-Means聚类训练集框得到5种先验框,回归偏移量,稳定收敛。

4. Darknet-19:轻量主干,1×1降维+3×3提取特征,参数更少、速度更快。

5. Passthrough细粒度特征:融合26×26浅层特征,改善小目标检测。

6. 多尺度训练:输入320~608(32倍数),提升鲁棒性。

2. 核心效果

• VOC mAP:63.4(v1) → 78.6(v2)

• 速度保持实时,精度逼近Two-stage算法。

四、YOLOv3:工业界最实用版本(本文实战主角)

v3是平衡速度/精度/工程化的巅峰,至今仍广泛落地。

1. 革命性改进

1. Darknet-53主干:全卷积+残差连接,更深但更快,特征更强。

2. FPN多尺度预测:3个输出层,分别检测大/中/小目标

◦ 13×13:大目标(感受野最大)

◦ 26×26:中目标

◦ 52×52:小目标(感受野最小)

3. 9种先验框:3尺度×3种,聚类自COCO数据集,适配更多形状目标。

4. Logistic替代Softmax:支持多标签分类(如“人+行人”),每个类别独立概率。

5. 多标签损失:用BCEWithLogitsLoss,适配多类别共存场景。

2. 为什么选YOLOv3做实战?

• 速度:416尺寸≈50FPS,满足实时

• 精度:COCO mAP50≈55.3%,足够工业落地

• 代码成熟、部署简单、适配自定义数据集零门槛

五、YOLOv3自定义数据集训练实战(PyTorch版)

本文基于PyTorch-YOLOv3复现,从环境→标注→配置→训练→测试全流程。

1. 环境准备
# 基础依赖 pip install torch torchvision pillow pyqt5 labelme # 下载项目 git clone https://github.com/eriklindernoren/PyTorch-YOLOv3.git cd PyTorch-YOLOv3
2. 数据集构建(核心步骤)

(1)数据标注(Labelme)

pip install labelme labelme # 启动GUI

• 标注:矩形框标记目标,保存json

• 转换:json → YOLO格式(class_id x y w h,均归一化)

(2)配置文件修改

1)classes.names

person animal

2)custom.data

classes=2 train=data/custom/train.txt valid=data/custom/val.txt names=data/custom/classes.names

3)生成自定义cfg

bash create_custom_model.sh 2 # 2为类别数
3. 启动训练
from models import * # from utils.logger import * from utils.utils import * from utils.datasets import * from utils.parse_config import * from test import evaluate import warnings warnings.filterwarnings("ignore") from terminaltables import AsciiTable import os import time import datetime import argparse import torch from torch.utils.data import DataLoader from torch.autograd import Variable """配置参数: --model_def config/yolov3-custom.cfg --data_config config/custom1.data --pretrained_weights weights/darknet53.conv.74 """ if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("--epochs", type=int, default=10, help="number of epochs") #训练次数 parser.add_argument("--batch_size", type=int, default=1, help="size of each image batch") #batch的大小 parser.add_argument("--gradient_accumulations", type=int, default=1, help="number of gradient accums before step")#在每一步(更新模型参数)之前累积梯度的次数” parser.add_argument("--model_def", type=str, default="config/yolov3.cfg", help="path to model definition file") #模型的配置文件 parser.add_argument("--data_config", type=str, default="config/coco.data", help="path to data config file") #数据的配置文件 parser.add_argument("--pretrained_weights", type=str, help="if specified starts from checkpoint model") #预训练文件 parser.add_argument("--n_cpu", type=int, default=0, help="number of cpu threads to use during batch generation")#数据加载过程中应使用的CPU线程数。 parser.add_argument("--img_size", type=int, default=416, help="size of each image dimension") parser.add_argument("--checkpoint_interval", type=int, default=1, help="interval between saving model weights")#隔多少个epoch保存一次模型权重 parser.add_argument("--evaluation_interval", type=int, default=1, help="interval evaluations on validation set")#多少个epoch进行一次验证集的验证 parser.add_argument("--compute_map", default=False, help="if True computes mAP every tenth batch") parser.add_argument("--multiscale_training", default=True, help="allow for multi-scale training")#允许多尺寸特征图融合的训练 opt = parser.parse_args() print(opt) # logger = Logger("logs")#日志文件 device = torch.device("cuda" if torch.cuda.is_available() else "cpu") os.makedirs("output", exist_ok=True) os.makedirs("checkpoints", exist_ok=True) # Get data configuration data_config = parse_data_config(opt.data_config) train_path = data_config["train"] valid_path = data_config["valid"] class_names = load_classes(data_config["names"]) # Initiate model model = Darknet(opt.model_def).to(device) model.apply(weights_init_normal)#model.apply(fn)表示将fn函数应用到神经网络的各个模块上,包括该神经网络本身。这通常在初始化神经网络的参数时使用,本处用于初始化神经网络的权值 # If specified we start from checkpoint if opt.pretrained_weights: if opt.pretrained_weights.endswith(".pth"): #用于检查字符串是否以指定的后缀结束。如果字符串以指定的后缀结束,则返回True,否则返回False。 model.load_state_dict(torch.load(opt.pretrained_weights)) else: model.load_darknet_weights(opt.pretrained_weights) # Get dataloader dataset = ListDataset(train_path, augment=True, multiscale=opt.multiscale_training) dataloader = torch.utils.data.DataLoader( dataset, batch_size=opt.batch_size, #1个样本打包成一个batch进行加载 shuffle=True, #对数据进行随机打乱, num_workers=opt.n_cpu, #用于指定子进程的数量,用于并行地加载数据。默认情况下,num_workers的值为0,表示没有使用子进程,所有数据都会在主进程中加载。当设置num_workers大于0时,DataLoader会创建指定数量的子进程,每个子进程都会负责加载一部分数据,然后主进程负责从这些子进程中获取数据。 # 使用子进程可以加快数据的加载速度,因为每个子进程可以并行地加载一部分数据,从而充分利用多核CPU的计算能力。但是需要注意的是,使用子进程可能会导致数据的顺序被打乱,因此如果需要保持数据的原始顺序,应该将shuffle参数设置为False。 # num_workers的值应该根据具体情况进行调整。如果数据集较大,可以考虑增加num_workers的值以充分利用计算机的资源。但是需要注意的是,如果num_workers的值过大,可能会导致内存消耗过大或者CPU负载过重,从而影响程序的性能。因此,需要根据实际情况进行调整。 pin_memory=True, #指定是否将加载进内存的数据的指针固定(pin),这个参数在某些情况下可以提高数据加载的速度。 # 当设置pin_memory=True时,DataLoader会将加载进内存的数据的指针固定,即不进行移动操作。这样做的目的是为了提高数据传输的效率。因为当数据从磁盘或者网络等地方传输到内存中时,如果指针不固定,可能会导致数据在传输过程中被移动,从而需要重新读取,浪费了时间。而固定指针可以避免这种情况的发生,从而提高了数据传输的效率。 # 需要注意的是,pin_memory参数的效果与操作系统和硬件的性能有关。在一些高性能的计算机上,固定指针可能并不会带来太大的性能提升。但是在一些内存带宽较小的计算机上,固定指针可能会显著提高数据加载的效率。因此,需要根据实际情况进行调整。 collate_fn=dataset.collate_fn, # collate_fn是一个函数,用于对每个batch的数据进行合并。这个函数的输入是一个batch的数据,输出是一个合并后的数据。 # collate_fn函数的主要作用是对每个batch的数据进行预处理,例如将不同数据类型的张量合并成一个张量,或者对序列数据进行padding操作等。这样可以使得每个batch的数据格式一致,便于模型进行训练。 # 在默认情况下,collate_fn函数会将每个batch的数据按照第一个元素的张量形状进行合并。例如,如果一个batch的数据中第一个元素的张量形状是[ # 3, 224, 224],那么collate_fn函数会将该batch的所有数据都调整为这个形状。 ) optimizer = torch.optim.Adam(model.parameters()) metrics = [ "grid_size", "loss", "x", "y", "w", "h", "conf", "cls", "cls_acc", "recall50", "recall75", "precision", "conf_obj", "conf_noobj", ] for epoch in range(opt.epochs): model.train() start_time = time.time() for batch_i, (_, imgs, targets) in enumerate(dataloader): batches_done = len(dataloader) * epoch + batch_i imgs = Variable(imgs.to(device)) #Variable类是PyTorch中的一个包装器,它将张量和它们的梯度信息封装在一起。当我们对一个张量进行操作时,PyTorch会自动地创建一个对应的Variable对象,其中包含了原始张量、梯度等信息。通过使用Variable,我们可以方便地进行自动微分和优化。 targets = Variable(targets.to(device), requires_grad=False) print ('imgs',imgs.shape) print ('targets',targets.shape) loss, outputs = model(imgs, targets) loss.backward() if batches_done % opt.gradient_accumulations: # Accumulates gradient before each step optimizer.step() optimizer.zero_grad() # ---------------- # Log progress # ---------------- log_str = "\n---- [Epoch %d/%d, Batch %d/%d] ----\n" % (epoch, opt.epochs, batch_i, len(dataloader)) metric_table = [["Metrics", *[f"YOLO Layer {i}" for i in range(len(model.yolo_layers))]]] # Log metrics at each YOLO layer for i, metric in enumerate(metrics): formats = {m: "%.6f" for m in metrics} formats["grid_size"] = "%2d" formats["cls_acc"] = "%.2f%%" row_metrics = [formats[metric] % yolo.metrics.get(metric, 0) for yolo in model.yolo_layers] metric_table += [[metric, *row_metrics]] # Tensorboard logging tensorboard_log = [] for j, yolo in enumerate(model.yolo_layers): for name, metric in yolo.metrics.items(): if name != "grid_size": tensorboard_log += [(f"{name}_{j+1}", metric)] tensorboard_log += [("loss", loss.item())] # logger.list_of_scalars_summary(tensorboard_log, batches_done) log_str += AsciiTable(metric_table).table log_str += f"\nTotal loss {loss.item()}" # Determine approximate time left for epoch epoch_batches_left = len(dataloader) - (batch_i + 1) time_left = datetime.timedelta(seconds=epoch_batches_left * (time.time() - start_time) / (batch_i + 1)) log_str += f"\n---- ETA {time_left}" print(log_str) model.seen += imgs.size(0) if epoch % opt.evaluation_interval == 0: print("\n---- Evaluating Model ----") # Evaluate the model on the validation set precision, recall, AP, f1, ap_class = evaluate( model, path=valid_path, iou_thres=0.5, conf_thres=0.5, nms_thres=0.5, img_size=opt.img_size, batch_size=8, ) evaluation_metrics = [ ("val_precision", precision.mean()), ("val_recall", recall.mean()), ("val_mAP", AP.mean()), ("val_f1", f1.mean()), ] # logger.list_of_scalars_summary(evaluation_metrics, epoch) # Print class APs and mAP ap_table = [["Index", "Class name", "AP"]] for i, c in enumerate(ap_class): ap_table += [[c, class_names[c], "%.5f" % AP[i]]] print(AsciiTable(ap_table).table) print(f"---- mAP {AP.mean()}") if epoch % opt.checkpoint_interval == 0: torch.save(model.state_dict(), f"checkpoints/yolov3_ckpt_%d.pth" % epoch)
4. 训练参数说明(train.py核心)

• epochs:训练轮数,建议100+

• batch_size:按GPU显存调整(16G→8/16)

• img_size:建议416(32倍数,多尺度友好)

• pretrained_weights:用Darknet53预训练权重,加速收敛

六、YOLOv1→v3演进总结表

版本主干网络先验框输出尺度核心亮点mAP
YOLOv1GoogLeNet7×7单阶段开创
YOLOv2Darknet-195 种13×13BN、Anchor、多尺度
YOLOv3Darknet-539 种13/26/52残差、FPN、多标签

七、总结

YOLO从v1到v3,完成了从概念验证→工程实用的蜕变:

• v1:定义单阶段检测范式

• v2:补齐精度短板,落地可用

• v3:多尺度+残差+多标签,成为工业标配

本文配套YOLOv3完整训练流程,可直接用于口罩检测、行人计数、车辆检测等真实场景,改类别数和数据集即可快速复用。

http://www.jsqmd.com/news/684540/

相关文章:

  • 别再死记硬背了!用‘浏览器缓存淘汰’和‘Redis内存回收’两个真实案例,彻底搞懂LRU算法
  • 2026年4月新疆硅酸盐净化板实力厂家专业推荐与选型指南 - 2026年企业推荐榜
  • 别再让SysTick偷走电量!深入FreeRTOS Tickless源码,看它如何“欺骗”系统时钟
  • 别再乱传了!Vue Router中Query和Params传参的实战避坑指南(附TypeScript示例)
  • 三招解锁Slurm集群管理新境界:从命令行到可视化智能监控的蜕变之旅
  • Qwen2-VL-2B-Instruct助力数学公式识别:与MathType结合辅助学术文档处理
  • 桌面图标打乱
  • 2026年当前,福建企业合同纠纷解决优选:天衡陈川律师团队解析 - 2026年企业推荐榜
  • 2026河北学校塑胶跑道选型top5推荐:河北学校塑胶跑道,河北混合型塑胶跑道,河北田径场跑道,实力盘点! - 优质品牌商家
  • Wi-Fi CSI传感技术:非接触式人体活动识别原理与应用
  • 从SIRAL高度计的三种模式说起:CryoSat-2如何成为海冰厚度测量的‘游戏规则改变者’
  • 2026年4月更新:隔热玻璃棉行业深度解析与帅辉建材实力推荐 - 2026年企业推荐榜
  • AI在网络安全中的实战应用与ROI优化策略
  • 智能机器狗开发深度解析:从机械骨骼到感知大脑的技术演进之旅
  • 2026年最新市场解析:江津附近挖机租赁,为何众多工程方选择玖业茂工程机械? - 2026年企业推荐榜
  • Gitee Pages+Markdown:打造个人技术博客,彻底解决图片外链失效难题
  • ESP32-S2上LVGL v7.11主题色和字体修改实战:告别默认界面,5分钟打造个性化UI
  • NSC_BUILDER:Switch游戏文件批量处理工具的深度技术评测
  • 华为交换机安全加固必做项:手把手教你配置CPU防攻击,防住OSPF/BGP协议泛洪
  • 2026年专业真空吸料机厂家排行:pet干燥机,tpu干燥机,中央供料系统,双层保温干燥机,优选指南! - 优质品牌商家
  • 2026年AI抢人大战:这5个高薪岗位,你准备好了吗?
  • 2026头部技术AI生成式引擎优化技术服务商优势对比
  • 给Windows小白的保姆级教程:在VMware里装Ubuntu 20.04.3,从镜像下载到配置Python环境一条龙
  • 2026年4月宿州打包箱采购指南:如何甄选靠谱供应商与实力厂家推荐 - 2026年企业推荐榜
  • 【国产化替代实战指南】:Docker镜像仓库从Docker Hub迁移到华为云SWR的7步避坑法
  • 智能对话系统开发:从架构设计到生产部署
  • CSS项目开发如何提速_应用BEM规范建立可复用的样式库.txt
  • Linux RT 调度器的 task_woken:RT 任务唤醒后的处理
  • 2026年拉萨名酒回收机构选购全流程技术指南 - 优质品牌商家
  • 量子纠错解码器切换框架:高效解决量子计算纠错难题