YOLOv1详解:从那只狗开始...

YOLOv1详解:从那只狗开始...
abinng😶🌫️前言
在学习YOLO之前,请务必要有一定图像分类的深度学习基础,从LeNet到ResNet,基本就可以了,如果你还没学可以去学一下哦(本博客中也有滴)
背景
论文:[1506.02640] You Only Look Once: Unified, Real-Time Object Detection
YOLO全称 You Only Look Once(你只看一眼),是Joseph Redmon大神在2016年提出的目标检测方法,开创了“一眼看全图”的新时代。
主要在于,快且准,他是单阶段,检测到目标位置的同时分类。区分于先检测出物体,再进行分类的R-CNN,Fast-RCNN。
网络结构
大致看看
先大致看看结构图
….好像和前面学的LeNet, AlexNet没啥区别呢,都是(卷积, 池化, … ,
全连接层),就是最后有一块
没错,前面的本质上就和之前学习的图像分类的处理差不多,最后
另外,yolo的输出是
细看
一些小细节:
- 除最后一层(输出层) 也就是
的那个全连接层使用了线性激活函数以外,其余层均为Leaky ReLU激活函数 - 训练中使用了Dropout与数据增强的方法来防止过拟合。参数太多了
- 对于最后一个卷积层,它输出一个形状为(7, 7, 1024)的张量。然后张量展开,使用2个全连接层作为一种线性回归的形式,它输出1470个参数,然后reshape为(7, 7, 30)。
参数
利用公式
结果
怎么来的
结果最后
对于每个grid cell:
- 如果某个物体的中心落在该网格中,那么这个网格就负责预测这个物体
- 预测B个边界框(bounding box)(在yolov1中选择2个边界框作为预测结果)。因为可能会多个物体中心落在一个格子中
- B个边界框中,每个边界框包含5个元素,分别为,中心坐标:x, y;检测框的宽和高:w, h;对应检测框的置信度c
- 每个网格,还要预测C个类别的分数,也就是概率p
- 所以这里是
结果解析
将结果
先看左图:
基准:大红色框代表grid cell,蓝色点表示该grid cell的左上角坐标,为(0, 0);
结果:
- 深红色和绿色框代表该grid cell包含的两个bounding box,深红点和绿色点表示这两个bounding box的中心坐标(bounding box的中心坐标一定在该grid cell内部)。
- x, y坐标值为归一化后的坐标值,在0-1之间,以当前grid cell的左上坐标(0, 0)为参考。因此,绿色边界框的坐标为(0.5, 0.5)。深红色边界框的坐标为(0.35, 0.85)。
再看右图:
- w, h:是指该bounding box的宽和高,也归一化到了0-1之间,表示相较于原始图像的宽和高(即448个像素)。
- 图中的bounding box预测的框宽为w=0.43,高为h=0.40。
一个小概念,
在目标检测任务中,
一个小概念,置信度
置信度作用定义有两重:
- 代表当前box是否有对象,这个概率值为1或者0,注意,这里是对象,不是某个类别的对象,也就是说它用来说明当前box内只是个背景(backgroud)还是有某个物体(对象)
- 表示当前的box有对象时,它自己预测的box与物体真实的box之间的
交并比,注意:这里所说的物体真实的box实际是不存在的,这只是模型表达自己框出了物体的自信程度。 因此此时置信度的公式为:
- 训练时,我们是有真实的框的,所以逻辑很顺畅。
- 预测时,没有真实的框,不需要计算公式,直接读取网络输出的
中的这个 值。这个 是神经元计算出来的,已经经过成百上千训练的不断迭代,各种参数能保证他的准确性。 - 当它前面的卷积层传来“这里像是一片蓝天”的信号时,它的权重参数会让它输出一个接近 0 的值。
- 当它前面的卷积层传来“这里有狗头纹理”的信号时,它的权重参数会让它输出一个接近 1 的值。
当然越形象就越偏离正确过程,这里是帮助理解的例子。
最后是
每个grid cell都会有20个概率,这个概率是通过
到这里,如果你突然对置信度
一句话:置信度对应框,概率对应类别;;;后面筛选目标会用到一个类别置信度,就在预测时筛选的第二步。
前面我们说过,YOLO,即You Only Look Once,只看一眼就可以检测到目标位置的同时分类,好像还真是。
损失函数
分成一块一块来看
首先我之前没见过这个
- 真实框的中心点落在这个网格
中。 - 这个预测框
是该网格两个框中与真实框 更大的那个。 - 也就是不止限制grid cell,还只取一个框。其余情况均为0。
我们先称
然后看出现很多次的
之后看那个
我们还发现有两个参数:
在一张图片中,绝大多数网格都是背景(负样本)。如果不加控制,这些负样本的
Loss 会淹没掉少数正样本的 Loss,导致网络学不到东西。
解决方案:YOLOv1 给负样本的置信度 Loss
乘了一个很小的权重
现在分别来看三个损失,普通的就说了,通过上面的符号解析也能很轻松看出来:
坐标损失:有一个开根的操作,为什么呢,其实是模拟一个真实情况,看下图
对于小目标和大目标,当偏移相同距离(即
置信度损失:当
类别损失:这个没啥好说的
怎么筛选出目标
大概计算一下,发现应该是
Thinking…..
分为训练时和预测时:
训练时:
我们手中有真实的框,所以就分为了两类grid cell,一种是真实框的中心落到grid cell的(正样本),另一种是没落到grid cell的(负样本)
对于正样本,有两个框,选出一个
对于负样本,不计算坐标误差和类别误差,因为框里面没东西呀。对于置信度误差就是正常用公式计算就好,其
预测时:
这是由于98个框经过了筛选和后处理,大致为三步:
一、根据置信度来进行筛选
每个预测框(Bounding Box)都包含一个置信度分数 (Confidence Score)。这个分数由网络预测,代表两层含义。
- 框里有物体的概率
。(有=1, 无=0) - 框的位置准不准 (预测框与真实框的
)。
我们可以设定一个阈值,比如0.1。框的置信度分数低于这个阈值,直接扔掉
二、根据类别分数筛选
Yolov1中,每个网格(grid cell)预测了一组类别概率
所以,如果一个框虽然置信度很高(觉得有东西),但是算出来的“是狗的概率”、“是猫的概率”都很低,那么它也会被过滤掉。
三、非极大值抑制 (Non-Maximum Suppression, NMS)
经过前两步,虽然过滤掉了很多背景框,但对于同一个物体(比如那只狗),往往会有多个框保留下来。
- 有的框只框住了狗头。
- 有的框偏左了一点。
- 有的框是最佳的。
我们既然要检测目标,这时候就需要 NMS 来去除重复的框,只保留最好的那一个。
NMS 的逻辑是这样的:
- 排序: 把所有剩下的框,按照类别置信度从高到低排列。
- 选高分: 取出类别置信度最高的那个框(假设是框 A),把它作为最终保留的“赢家”。
- 筛低分: 拿框 A 去和后面所有的框比较。如果后面的某个框 B 和框 A 的重叠度(IoU)很高(比如超过 0.5),我们就认为框 B 和框 A 预测的是同一个物体,既然框 A 分数更高,那框 B 就是多余的,直接删掉框 B。
- 循环: 对剩下的没被删除的框堆,重复上述过程,直到所有框堆都被处理完。
训练过程
分两个阶段:分类和检测
第一阶段:在ImageNet分类数据集上预训练分类模型。首先将yolov1的模型转化为分类模型;利用前20卷积作为模型的特征提取网络。随后利用全局平均池化层进行池化操作,随后利用全连接层进行1000分类。此时模型的输入为224x224,对该网络进行了大约一周的训练,并在ImageNet2012验证集上实现了单个作物前5名的准确率达到88%,与传统的图像识别方法相当。
第二阶段:将网络的输入调整为448x448。并将模型调整为检测模型,那么此时检测模型的参数如右图所示,及去除全局平均池化加入4个卷积层和两个全连接层,最后将模型的输出调整为7×7×30这样的向量大小。在分类模型参数上继续finetune网络(135轮)
优势和局限
优势:
YOLO非常快,因为将物体检测定义为回归问题, 所以检测也不需要复杂的组件。 YOLO基于全图进行检测,所以不像滑动窗口和预 选区技术,YOLO中隐含着隐式编码的上下文信息。
局限:
群体小目标:因为一个网格只能预测 2 个框且只能属于 1 个类别,所以如果两个物体靠得很近(比如一群鸟),YOLOv1 效果很差。 泛化能力:对长宽比不常见的物体检测效果一般。 定位误差:由于直接回归坐标,相比于 R-CNN 系列的 Anchor 机制,定位不够精准。
代码
我目前暂未实现,贴一个别人的 PyTorch 实现:abeardear/pytorch-YOLO-v1: an experiment for yolo-v1, including training and testing.




















