《零基础入门AI:YOLOv2算法解析》
一、前情回顾
1. K-Means算法
概念:
-
K:用户预先指定的想要得到的簇的数量。这是算法最重要的参数。
-
质心:每个簇的中心。其坐标由该簇内所有数据点的均值计算得出。这也是“K-Means”这个名字的由来(K个均值点)。
-
距离度量:通常使用欧氏距离来衡量数据点之间的相似度。距离越近,相似度越高。公式如下(对于二维空间):
距离 = √[(x₁ - x₂)² + (y₁ - y₂)²]
核心思想:物以类聚。算法认为,相似的数据点应该聚集在一起,形成一个个的“簇”。
目标:将给定的数据集划分为 K
个互不相交的簇,使得簇内的数据点尽可能相似(距离小),而簇间的数据点尽可能不同(距离大)。
最终输出:
K
个簇的中心点(称为质心)。- 每个数据点被分配到的簇的标签。
如何选择K值?
既然K需要预先指定,如何确定最佳的K呢?常用方法:
-
肘部法则:
- 做法:计算不同K值对应的聚类结果的误差平方和(SSE),即每个数据点到其所属簇的质心的距离的平方和。
- 原理:随着K增大,SSE会减小(因为每个簇更精细)。当K增加到真实簇数时,SSE的下降幅度会骤减,然后随着K继续增加而缓慢下降。这个拐点像“手肘”一样,对应的K值就是最佳值。
- 缺点:有时“肘部”不明显,难以判断。
-
轮廓系数:
- 结合了内聚度(一个点与自身簇内其他点的相似度)和分离度(该点与其他簇的相似度)来评估聚类的质量。
- 轮廓系数取值范围为
[-1, 1]
,值越大表示聚类效果越好。通常选择使轮廓系数最大的K值。
2. 上采样和下采样
2.1 下采样
概念:
下采样,也称为降采样或缩小,是指通过某种方法降低数据尺寸或数据量的过程。其目标是保留最重要、最具代表性的信息,同时丢弃冗余或次要的细节。
作用:
- 降低计算成本:更少的数据点意味着更快的处理速度和更低的内存占用。
- 防止过拟合:在机器学习中,减少特征数量或样本数量可以简化模型,使其更专注于核心模式。
- 提取关键特征:忽略细节噪声,抓住宏观趋势。
- 匹配不同分辨率:将高分辨率数据调整到与低分辨率数据相同的尺度进行处理。
常见方法:
(在信号/图像处理中):
- 最邻近插值:直接丢弃多余像素。速度最快,但可能导致严重的锯齿(Aliasing)和块状效应。
- 池化:在卷积神经网络中极为常见。
- 最大池化:取一个窗口(如2x2)内的最大值。能更好地保留纹理特征。
- 平均池化:取一个窗口内的平均值。能产生更平滑的效果。
- 抗混叠滤波 + 采样:这是最科学的方法。先使用一个低通滤波器(如高斯模糊)平滑信号,去除高频成分(防止采样后出现混叠失真),然后再进行间隔采样。
(在机器学习/数据挖掘中):
- 针对特征:主成分分析(PCA)、特征选择等,减少特征维度。
- 针对样本:处理类别不平衡问题。例如,从多数类中随机删除一部分样本,使其数量与少数类接近。
缺点
- 信息丢失:这是最主要的代价。下采样是不可逆的,丢失的细节无法从下采样后的数据中恢复。
- 混叠失真:如果下采样前没有进行适当的滤波,高频信号会混叠成低频信号,造成失真。
2.2 上采样
概念:
上采样,也称为升采样或放大,是指通过某种方法增加数据尺寸或数据量的过程。其目标是根据已有的低分辨率信息,推断和重建出高分辨率信息。
作用:
- 提高分辨率:如图像超分辨率、音频高保真还原。
- 数据扩充:生成更多样本以供训练,特别是在数据稀缺的情况下。
- 恢复原始尺寸:在神经网络中,经过多次下采样后,需要将特征图恢复到原始图像尺寸以进行像素级预测(如图像分割)。
- 处理不平衡数据:对少数类样本进行上采样,复制或生成新样本,以平衡数据集。
常见方法:
(在信号/图像处理中):
- 插值:利用已知数据点来估计未知数据点的值。
- 最邻近插值:将新点的值设置为离它最近的原始点的值。速度快,但效果粗糙,会产生块状。
- 双线性插值:在二维网格中,在x和y方向分别进行线性插值。效果比最邻近好,速度较快。
- 双三次插值:使用更多的邻近点(通常4x4)进行三次插值。能产生更平滑、更高质量的图像,是常用的图像放大算法。
- 转置卷积:也称为反卷积。是深度学习中的方法,通过可学习的参数来“填充”像素之间的空隙。它不是简单的插值,而是从数据中学习如何上采样,效果通常远优于传统插值。
(在机器学习/数据挖掘中):
- SMOTE:一种经典的针对类别不平衡的上采样技术。它不是简单复制少数类样本,而是在少数类样本的特征空间中进行插值,合成新的样本。
- 生成式模型:如生成对抗网络(GANs) 或 扩散模型,可以学习训练数据的分布,并生成全新的、与原始数据相似的高分辨率样本。这是目前图像超分辨率等领域最先进的方法。
缺点
- 无法创造真实信息:上采样是“无中生有”,新增的细节是基于已有信息的猜测和估计,不一定是真实的。可能会产生模糊或伪影。
- 计算成本高:尤其是基于深度学习的方法,需要大量的计算资源。
- 可能引入噪声:错误的插值或生成方法会引入不希望的 artifacts(伪影)。
二、YOLOv2详解
YOLOv2 论文地址:【https://arxiv.org/pdf/1612.08242#page=4.24】
YOLOv2 论文中文对照地址:【https://blog.csdn.net/qq_42755230/article/details/125820723】
1. 概述
YOLOv2是Joseph Redmon等人在2017年提出的YOLO算法的第二个版本。其论文名为《YOLO9000: Better, Faster, Stronger》。顾名思义,它的目标有三个:
- Better: 比YOLOv1更准确,逼近甚至超越当时最先进的Faster R-CNN。
- Faster: 保持极快的速度。
- Stronger: 能够检测超过9000种类别的物体(YOLO9000)。
YOLOv2并非革命性的重构,而是通过一系列巧妙且有效的增量改进,显著提升了基础YOLO模型的性能。下面我们将逐一分解这些改进。
2. 整体网络结构(Backbone: Darknet-19)
YOLOv2采用了名为Darknet-19的新主干特征提取网络,其结构如下表所示:
类型 | 过滤器 | 尺寸/步长 | 输出尺寸 |
---|---|---|---|
Convolutional | 32 | 3x3 | 224x224x32 |
Maxpool | 2x2/2 | 112x112x32 | |
Convolutional | 64 | 3x3 | 112x112x64 |
Maxpool | 2x2/2 | 56x56x64 | |
Convolutional | 128 | 3x3 | 56x56x128 |
Convolutional | 64 | 1x1 | 56x56x64 |
Convolutional | 128 | 3x3 | 56x56x128 |
Maxpool | 2x2/2 | 28x28x128 | |
Convolutional | 256 | 3x3 | 28x28x256 |
Convolutional | 128 | 1x1 | 28x28x128 |
Convolutional | 256 | 3x3 | 28x28x256 |
Maxpool | 2x2/2 | 14x14x256 | |
Convolutional | 512 | 3x3 | 14x14x512 |
Convolutional | 256 | 1x1 | 14x14x256 |
Convolutional | 512 | 3x3 | 14x14x512 |
Convolutional | 256 | 1x1 | 14x14x256 |
Convolutional | 512 | 3x3 | 14x14x512 |
Maxpool | 2x2/2 | 7x7x512 | |
Convolutional | 1024 | 3x3 | 7x7x1024 |
Convolutional | 512 | 1x1 | 7x7x512 |
Convolutional | 1024 | 3x3 | 7x7x1024 |
Convolutional | 512 | 1x1 | 7x7x512 |
Convolutional | 1024 | 3x3 | 7x7x1024 |
- 特点:
- 包含19个卷积层和5个最大池化层,比VGG16更小,但性能相当。
- 大量使用3x3卷积,并在池化后通过1x1卷积来压缩特征通道数以降低计算量。
- 使用全局平均池化(Global Average Pooling)代替全连接层进行ImageNet分类任务,大大减少了参数量并防止过拟合。
- 所有卷积层后都跟了批量归一化(BN)层。
用于检测:在Darknet-19的基础上,移除最后一个卷积层,添加三个3x3
(1024 filters)的卷积层,最后接一个1x1
卷积层来输出预测张量。
3. 批量归一化(Batch Normalization)
- 是什么: 批量归一化(Batch Normalization, BN)是一种通过对每一层的输入进行归一化(减去均值,除以标准差)来稳定和加速深度网络训练的技术。
- 在YOLOv2中的应用: YOLOv2在所有的卷积层之后、激活函数之前都加入了BN层。
- 带来的好处:
- 显著改善收敛性: 训练过程更加稳定,不再那么依赖精细的参数初始化。
- 正则化效果: 一定程度上减少了模型对Dropout正则化的需求。YOLOv2在加入BN后移除了YOLOv1中的Dropout层,但并未出现严重的过拟合。
- 提升mAP: 这一项改进直接带来了超过2%的mAP提升。
4. 高分辨率分类器(High Resolution Classifier)
- 问题: YOLOv1先在ImageNet(224x224)上训练分类网络,然后在检测任务(448x448)上微调。这种分辨率的突然切换使得网络难以快速适应。
- YOLOv2的改进:
- 首先在ImageNet上以448x448的分辨率对分类网络进行10个epoch的微调。
- 然后再用这个高分辨率预训练好的模型在检测数据集上进行训练。
- 带来的好处: 让网络在转入检测任务前就已经适应了更高的分辨率,为后续的检测任务提供了更好的特征基础。这项改进带来了约4%的mAP提升。
5. 锚框(Anchor Boxes)【重点】
这是YOLOv2最核心的改进之一,它改变了YOLO的边界框预测机制。
- YOLOv1的问题: YOLOv1直接在每个网格上预测边界框的坐标(
(x, y, w, h)
)。由于没有先验,模型需要艰难地学习如何输出合适的框,这导致模型在定位精度上较差,尤其是对小物体的检测。 - YOLOv2的解决方案: 借鉴Faster R-CNN的锚框(Anchor Boxes) 机制。
- 是什么: 锚框是一组预先定义好的、具有不同宽高比的边界框,它们作为预测的“参考”或“先验”。
- 如何工作:
- 移除YOLOv1中的全连接层,使用卷积层进行预测。
- 将输入图片划分为
S x S
的网格(例如13x13
)。 - 在每个网格上放置
k
个锚框(k=5
是论文中通过k-means聚类得到的推荐值)。 - 网络不再直接预测框的绝对坐标,而是预测相对于锚框的偏移量和置信度。
- 预测公式:
b_x = σ(t_x) + c_x
b_y = σ(t_y) + c_y
b_w = p_w * e^(t_w)
b_h = p_h * e^(t_h)
- 其中
(t_x, t_y, t_w, t_h)
是网络预测的4个值,σ
是sigmoid函数(将偏移限制在0~1,防止框偏移到其他网格),(c_x, c_y)
是网格的左上角坐标,(p_w, p_h)
是锚框的宽和高,(b_x, b_y, b_w, b_h)
是最终预测框的中心坐标和宽高。
- 带来的好处:
- 极大提升召回率(Recall): 模型现在只需要判断“这个锚框框住的区域里有没有物体?”以及“这个锚框需要如何微调才能更准?”,任务变得更容易学习。召回率从YOLOv1的81%提升到了88%。
- 简化学习目标: 网络只需学习如何微调锚框,而不是从零开始猜测框的位置,使学习过程更容易。
6. 细粒度特征(Fine-Grained Features)
- 问题: 经过多层卷积和下采样后,特征图的分辨率变得很低(如
13x13
),很多细粒度的特征(对小物体检测至关重要)已经丢失。 - YOLOv2的解决方案: Passthrough层。
- 是什么: 将前面一层更高分辨率(
26x26
)的特征图直接“传递”到后面的低分辨率特征图中进行融合。 - 如何工作: 将
26x26x512
的特征图拆分成4个13x13x512
的切片(按空间位置隔点采样),然后将其与原本的13x13x2048
特征图在通道维度上进行拼接,形成13x13x(2048+512*4)=13x13x3072
的新特征图。 - 带来的好处: 为最终的低分辨率特征图提供了更丰富的细粒度信息,显著改善了小物体的检测性能,带来了约1%的mAP提升。
- 是什么: 将前面一层更高分辨率(
7. 多尺度训练(Multi-Scale Training)
- 目标: 让模型对不同尺寸的输入图像都具有良好的鲁棒性。
- 方法: 在训练过程中,每经过10个batch,就随机选择一个新的输入图像尺寸。由于YOLOv2的网络下采样总步长为32,因此选择的尺寸必须是32的倍数(如
320, 352, ..., 608
)。 - 带来的好处:
- 同一个模型可以在不同分辨率下运行: 用户可以在速度和精度之间进行灵活权衡。用小尺寸(如
288x288
)输入,速度极快;用大尺寸(如544x544
)输入,精度更高。 - 泛化能力更强: 迫使模型学习在不同尺度下都能很好地提取特征。
- 同一个模型可以在不同分辨率下运行: 用户可以在速度和精度之间进行灵活权衡。用小尺寸(如
8. 推理实现
YOLOv2的推理过程非常简洁高效,是典型的“单阶段”检测器。
- 输入: 一张图片(如调整为416x416或任何多尺度尺寸)。
- 前向传播: 图片通过Darknet-19主干网络,得到最终的特征图(如
S x S x (B*(5+C))
,其中S=13, B=5, C=类别数)。 - 解码预测:
- 对于特征图上的每一个网格,每一个锚框,都会输出一个预测向量:
[t_x, t_y, t_w, t_h, obj_score, class_1, class_2, ..., class_N]
。 - 使用前面锚框部分提到的公式,将
(t_x, t_y, t_w, t_h)
解码为最终的边界框绝对坐标(b_x, b_y, b_w, b_h)
。 - 将目标置信度
obj_score
与类别概率class_i
相乘,得到每个框对于每个类别的最终置信度分数:confidence = obj_score * class_i
。这个分数同时包含了“框内是否有物体”的概率和“是什么物体”的概率。
- 对于特征图上的每一个网格,每一个锚框,都会输出一个预测向量:
- 后处理:
- 置信度阈值过滤: 设定一个阈值(如0.5),滤掉所有置信度分数低于该阈值的预测框。
- 非极大值抑制(NMS): 对剩下的框进行NMS操作,去除那些针对同一个物体的重复框,只保留得分最高的那一个。
- 输出:最终输出一系列带有类别标签和置信度分数的边界框。