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

YOLOv3 正负样本划分详解

✅ YOLOv3 正负样本划分详解

一、前言

在目标检测任务中,正负样本的划分 是训练过程中的关键环节。它决定了哪些预测框参与位置回归、分类损失和置信度损失。

YOLOv3 在 YOLOv2 的基础上引入了 多尺度预测更精细的 Anchor Boxes 匹配策略,使得正样本的选择更加合理,提高了模型的召回率和定位精度。

本文将基于以下来源进行解析:

  • YOLOv3: An Incremental Improvement (论文原文)
  • AlexeyAB/darknet 开源实现

二、YOLOv3 的输出结构回顾

YOLOv3 输出三个不同层级的特征图,分别用于检测不同尺度的目标:

特征图大小每个 cell 预测的 bounding box 数量对应 anchor boxes
13×133大目标
26×263中目标
52×523小目标

每个 bounding box 的输出维度为:

(tx, ty, tw, th, confidence, class_0, ..., class_C)

三、YOLOv3 的正负样本划分机制详解

✅ 核心思想:

YOLOv3 中的正样本由以下两个条件共同决定:

  1. 该 bounding box 的 anchor 与 ground truth 的 IoU 最大
  2. 该 bounding box 所属的 grid cell 包含物体中心点

📌 注意:YOLOv3 不像 Faster R-CNN 使用 RoI Pooling 或 Proposal 机制,而是直接对每个 grid cell 的多个 anchor 进行匹配。


🔍 正样本划分流程如下(来自 Darknet 实现):

Step 1: 获取所有 ground truth 框
ground_truth_boxes = [...]  # list of (x_center, y_center, w, h) 归一化坐标
Step 2: 遍历每个 ground truth 框

对于每个真实框:

  1. 计算其相对于图像的归一化中心坐标;
  2. 确定其落在哪个 grid cell;
  3. 使用 K-Means 聚类得到的 9 个 anchors,计算每个 anchor 与该真实框的 IoU;
  4. 找出 IoU 最大的那个 anchor;
  5. 确定这个 anchor 属于哪个层级(13×13 / 26×26 / 52×52);
  6. 将该 anchor 所在的 bounding box 设为正样本;
  7. 其余 anchor 若与该真实框的 IoU > iou_thresh(如 0.5),也设为正样本(可选);

✅ 正样本选择规则总结:

条件是否为正样本
anchor 与 GT 的 IoU 最大✅ 强制标记为正样本
anchor 与 GT 的 IoU > iou_threshold(如 0.5)✅ 可选标记为正样本
无任何 GT 与其重叠❌ 负样本
仅部分重叠但不是最大匹配❌ 忽略(不参与位置损失)

⚠️ 注意:只有负责预测真实框的 bounding box 才会参与位置回归(tx, ty, tw, th)和类别概率(class probs)的损失计算。


四、YOLOv3 中各类 loss 的作用对象

Loss 类型作用对象
定位损失(Localization Loss)正样本(负责预测的真实框)
置信度损失(Confidence Loss)正样本 + 负样本
分类损失(Class Probability Loss)正样本

五、具体示例说明

假设我们有以下数据:

  • 图像尺寸:416 × 416
  • Ground Truth Box:[0.5, 0.5, 0.2, 0.2](归一化坐标)
  • Anchor Boxes(对应 52×52 特征图):
    anchors = [[10, 13], [16, 30], [33, 23]]  # 小目标 anchors
    

Step-by-step 划分逻辑:

  1. 确定 GT 中心落在哪个 grid cell?

    • cell_x = floor(0.5 * 52) = 26
    • cell_y = floor(0.5 * 52) = 26
  2. 计算每个 anchor 与 GT 的 IoU

    ious = [iou(anchor, gt_box) for anchor in anchors]
    best_anchor_idx = np.argmax(ious)
    
  3. 标记该 anchor 对应的 bounding box 为正样本

    • 假设 best_anchor_idx = 0,则第 0 个 bounding box 被标记为正样本;
    • 该 bounding box 的位置信息 (tx, ty, tw, th) 将被监督学习;
    • confidence 设为 1;
    • class prob 设置为目标类别;
  4. 其他 anchor 若与 GT 的 IoU > threshold(如 0.5),也可被标记为正样本(可选)


六、YOLOv3 中的负样本定义

✅ 负样本的判断标准:

  • 该 bounding box 不负责预测任何真实框
  • 且与所有真实框的 IoU < threshold(通常为 0.5);
  • 只参与置信度损失(confidence loss),不参与位置和分类损失;

七、YOLOv3 中的 ignore 样本(非正非负)

✅ 定义:

  • 与某个真实框的 IoU > threshold(如 0.5),但不是最大 IoU 的那个 bounding box;
  • 被标记为“ignore”,即:
    • 不参与位置损失;
    • 不参与分类损失;
    • 参与置信度损失吗?取决于实现方式(Darknet 中默认不参与);

八、YOLOv3 中的标签分配伪代码(简化版)

for each ground_truth in image:# Step 1: 确定 GT 中心所在的 grid cellcell_x = int(gt.x_center * feature_map_width)cell_y = int(gt.y_center * feature_map_height)# Step 2: 计算每个 anchor 与 GT 的 IoUious_with_anchors = [bbox_iou(anchor, gt) for anchor in anchors]# Step 3: 找到 IoU 最大的 anchorbest_anchor_index = np.argmax(ious_with_anchors)# Step 4: 标记该 anchor 为正样本y_true[cell_y, cell_x, best_anchor_index, ...] = {"tx": tx,"ty": ty,"tw": tw,"th": th,"confidence": 1,"class_prob": one_hot_label}# Step 5: (可选)IoU > threshold 的其他 anchor 也被标记为正样本for a in range(num_anchors):if ious_with_anchors[a] > ignore_thresh and a != best_anchor_index:y_true[cell_y, cell_x, a, ...] = {"confidence": 1,  # 仅置信度,不更新位置和类别...}

九、YOLOv3 中的阈值设置(来自 darknet 源码)

在官方实现中,有两个关键参数影响正负样本划分:

参数名含义默认值
ignore_thresh若 IoU > 该阈值,则忽略(不参与损失)0.5
truth_thresh若 IoU > 该阈值,则强制作为正样本1.0(默认只使用最大 IoU 的 anchor)

📌 注意:YOLOv3 默认只使用 IoU 最大的 anchor 作为正样本,其他高 IoU 的 anchor 并不参与训练。


十、YOLOv3 中的正负样本分布特点

维度内容
✅ 正样本数量每个真实框 → 至少一个正样本
❌ 负样本数量无物体的 bounding box
🧩 ignore 样本IoU > ignore_thresh 但非最大匹配
📌 位置损失仅正样本参与
📌 置信度损失正样本 + 负样本
📌 分类损失仅正样本参与

十一、YOLOv3 中的损失函数简要回顾

YOLOv3 的损失函数分为三个部分:

⚙️ 1. 定位损失(Localization Loss)

L l o c = λ c o o r d ∑ i = 0 S 2 ∑ j = 0 B 1 i j o b j [ ( x i − x ^ i ) 2 + ( y i − y ^ i ) 2 + ( w i − w ^ i ) 2 + ( h i − h ^ i ) 2 ] \mathcal{L}_{loc} = \lambda_{coord} \sum_{i=0}^{S^2} \sum_{j=0}^{B} \mathbb{1}_{ij}^{obj} \left[ (x_i - \hat{x}_i)^2 + (y_i - \hat{y}_i)^2 + (\sqrt{w_i} - \sqrt{\hat{w}_i})^2 + (\sqrt{h_i} - \sqrt{\hat{h}_i})^2 \right] Lloc=λcoordi=0S2j=0B1ijobj[(xix^i)2+(yiy^i)2+(wi w^i )2+(hi h^i )2]

仅对正样本计算此部分损失。


⚙️ 2. 置信度损失(Confidence Loss)

L c o n f = ∑ i = 0 S 2 ∑ j = 0 B [ 1 i j o b j ⋅ ( confidence i j − confidence ^ i j ) 2 + λ n o o b j ⋅ ( 1 − 1 i j o b j ) ⋅ ( confidence i j ) 2 ] \mathcal{L}_{conf} = \sum_{i=0}^{S^2} \sum_{j=0}^{B} \left[ \mathbb{1}_{ij}^{obj} \cdot (\text{confidence}_i^j - \hat{\text{confidence}}_i^j)^2 +\lambda_{noobj} \cdot (1 - \mathbb{1}_{ij}^{obj}) \cdot (\text{confidence}_i^j)^2 \right] Lconf=i=0S2j=0B[1ijobj(confidenceijconfidence^ij)2+λnoobj(11ijobj)(confidenceij)2]

所有 bounding box 都参与此项损失,但负样本权重较低。


⚙️ 3. 分类损失(Class Probability Loss)

L c l s = ∑ i = 0 S 2 ∑ j = 0 B 1 i j o b j ⋅ ∑ c ∈ classes ( p i ( c ) − p ^ i ( c ) ) 2 \mathcal{L}_{cls} = \sum_{i=0}^{S^2} \sum_{j=0}^{B} \mathbb{1}_{ij}^{obj} \cdot \sum_{c \in \text{classes}} (p_i(c) - \hat{p}_i(c))^2 Lcls=i=0S2j=0B1ijobjcclasses(pi(c)p^i(c))2

仅正样本参与分类损失。


十二、YOLOv3 的样本划分总结

样本类型IoU 条件是否参与位置损失是否参与置信度损失是否参与分类损失
正样本IoU 最大 或 IoU > threshold(可选)✅ 是✅ 是✅ 是
ignore 样本IoU > threshold 但非最大❌ 否❌ 否(Darknet 默认不参与)❌ 否
负样本IoU < threshold❌ 否✅ 是(降低 confidence)❌ 否

十三、结语

YOLOv3 的正负样本划分机制相比 YOLOv2 更加精细,主要体现在:

  • 引入多尺度预测,提升小目标召回;
  • 使用 anchor boxes 提升边界框匹配合理性;
  • 通过 IoU 匹配选择最合适的 bounding box;
  • 保留传统做法(仅最大 IoU 为正样本),避免过拟合;
  • 支持 ignore 阈值,防止低 IoU 框干扰训练;

📌 欢迎点赞 + 收藏 + 关注我,我会持续更新更多关于目标检测、YOLO系列、深度学习等内容!

http://www.xdnf.cn/news/14436.html

相关文章:

  • OpenIPC-aviateur上位机程序编译环境配置
  • 【AI大模型】Elasticsearch9 + 通义大模型实现语义检索操作详解
  • Logos心法:一份认知进化的活地图
  • Spring Boot 实训项目 - 图书信息网站
  • 哪些元器件对信号频率比较敏感
  • 从混沌到宝藏:数据治理、清洗与资产化的炼金术
  • 【图像质量评价技术专题】-PSNR和SSIM
  • 从代码学习深度学习 - 词的相似性和类比任务 PyTorch版
  • linux 阻塞和非阻塞
  • 【JAVA】支付,积分相关代码开发总结
  • Linux信号机制:进程异步通信的秘密
  • 黑马python(六)
  • 【Canvas与艺术】三只堂前燕
  • DAY49 超大力王爱学Python
  • 深度解析Vue路由原理与实战指南
  • AUTOSAR Adaptive系统如何进行时间同步与延迟分析?
  • YOLOv11改进 | Conv/卷积篇 | 2024最新ECCV最新大感受野的小波卷积WTConv助力YOLOv11有效涨点(二次创新C3k2)
  • 【 C++ 模板中 `template<typename T>` 与 `template<class T>` 的深度解析】
  • springboot测试类原理
  • AI编程:正在拉开新一轮“人与人”的差距
  • Kafka多副本机制
  • python 将字典的值替换为键名作为变量名的形式(带缩进)
  • 基于51单片机的直流电动控制速度系统proteus仿真
  • leetcode 分割回文串 java
  • 总结用ubuntu一直以来遇到的问题
  • 加盐加密算法
  • 浏览器基础及缓存
  • 【Linux】Linux 信号驱动I/O
  • Git 配置 SSH 密钥与私钥教程(跨平台完整指南)
  • 京东API接口最新指南:店铺所有商品接口的接入与使用