您现在的位置是:首页 >技术教程 >深度学习中的一阶段目标检测网站首页技术教程

深度学习中的一阶段目标检测

心随而动 2023-06-08 08:00:02
简介深度学习中的一阶段目标检测

 博主简介

博主是一名大二学生,主攻人工智能研究。感谢让我们在CSDN相遇,博主致力于在这里分享关于人工智能,c++,Python,爬虫等方面知识的分享。 如果有需要的小伙伴可以关注博主,博主会继续更新的,如果有错误之处,大家可以指正。

专栏简介:   本专栏主要研究计算机视觉,涉及算法,案例实践,网络模型等知识。包括一些常用的数据处理算法,也会介绍很多的Python第三方库。如果需要,点击这里订阅专栏   。

给大家分享一个我很喜欢的一句话:“每天多努力一点,不为别的,只为日后,能够多一些选择,选择舒心的日子,选择自己喜欢的人!”


目录

前言

YOLO网络

YOLO起源

YOLO原理

YOLOv2网络

 YOLOv3网络

SSD网络

1.1 模型

1.2 训练


前言

我们前面说的,两阶段目标检测本质上就是训练俩个网络,分别对两个问题进行求解,这两个网络有什么区别喃?在网络结构上没有本质的区别,在特征输入上也没有任何的区别,唯一的区别就是网络的目标不同,或者说是使用的损失函数不同,所以我们完全可以将两个网络合并,将输出向量也拼接在一起,并且使用不同的损失函数对不同部分的输出进行拟合。

一阶段目标检测主要的网络有YOLO网络和SSD网络。下面我们就进入这两个网络的学习。

YOLO网络

作为目标检测最优秀的网络结构:YOLO。全名叫you look only once,意思是你只需看一次,就能完成整个目标检测。

YOLO起源

YOLO的发展其实是一个毫无波澜的发展,在两阶段目标检测发展的时候,YOLO开始悄悄的发展,可以说在YOLO真正公布的前一天都没人注意到这个,然而YOLO网路一经问世,就异军突起,当然,和他一起出世的还有SSD网络,但是把,他们的准确率还是有很大的有待提升。之后经过一段时间,YOLOv2诞生,增加了输出类别,成就了YOLO9000,此时,YOLO网络已经稳居第一,不过,一段时间后,YOLOv3也被推出,可以说是横扫武林。

YOLO原理

对于目标识别问题,我们最后进行分类的时候,就是根据最后一层的概率值用作分类。于是,在YOLO网络的最后一层,我们在预测类别的基础上,加入预测位置的部分。

为了预测位置,我们输出五个值:x,y,w,h,p,这五个值分别对应候选框的左下角坐标(或者候选框的中心)、候选框的宽度和高度,以及候选框中存在物体的置信概率。置信概率的计算是,如果候选框中存在物体,则置信概率为候选框与真实物体框的交并比(IOU),否则为0.

我们开始的时候把图片分成SxS格(默认为7),每个格子用来预测中心点落在其中哪一个物体上。当然分成SxS也是由于网络的最后一层特征层的大小为SxS,也就是说最后一层特征层的每个像素对应一个候选框。当然,这个分成SxS个格子只是抽象的说法,实际测试的时候并不会真正的划分,就像磁感线一样,只是为了方便我们的学习和计算。

一般来说,一个格子会输出置信概率最大的B个候选框(B默认值为2),测试时我们会选取概率最大的那个作为预测结果。也就是说,我们总共可预测的候选框为SxSxB(98).当然,每个格子还需要C个物体类别预测(C默认值为20),这C个类别预测其实是条件概率:P(某一类物体|存在物体),这是由于前面我们已经预测了物体的置信概率P(存在物体),所以两者相乘就得到P(某一类物体),于是每个方格输出Bx5+C维度的数据,也就是说我们最后一共输出维度为SxSx(Bx5+C)的张量进行回归预测。

在YOLO中,分类损失采取类别概率的平方损失,在YOLO计算中,只计算有物体的候选框的分类损失,而忽略背景框,所以分类损失为:

sumsum(p(c)-p(c))^{2}

对于边框预测中的x和y,我们可以利用欧几里得距离来计算位置损失,但是对于w和h就不行,因为w和h的绝对值很小,他们的欧几里得距离误差就会很大。所以这里定义一个位置损失式:

sum sum (x-hat{x})^{2}+(y-hat{y})^{2}+(sqrt{w}-hat{sqrt{w}})^{2}+(sqrt{h}-hat{sqrt{h}})^{2}

最后就是置信概率p的损失函数,我们还是用拼房损失函数,不过不含物体的框怎么处理喃?我们可以给他一个很小的权重,这样就可以解决正负样本不均衡的问题。下面给出置信概率的损失函数:

sum sum (c-hat{c})^{2}+lambda sum sum (c-hat{c})^{2}

第一个是有物体的候选框,第二个是无物体的候选框。

上面这个图就是YOLO网络损失函数的设计图。

对于网络预测层与原图的映射关系,我们可以有以下几个步骤:

1.首先,需要对图片层经过卷积层和最大池化层的组合层,最后变成7x7x1024的张量,最后再进过两个全连接层,变成我们前面讲过的7x7x30的张量,再有它进行损失函数的计算即可。只有最后一层采用线性激活函数,其他层都采用Leaky ReLU激活函数。

2.由于数据集样本较少,YOLO先使用ImageNet数据集对前20层卷积网络进行预训练,然后使用完整的网络,在PASCAL VOC数据集上进行物体分类和候选框位置的训练和预测。训练中采用dropout和数据增强来防止过拟合。

最后,我们来分析一下YOLO的优缺点:

1.预测速度快,超过了一般的网络预测速度。

2.对边框的预测精度不高,总体的预测精度低于Fast R-CNN、类网络。 

YOLOv2网络

YOLOv2的全名是YOLO9000:Better、Faster、Stronger。我们来讲解一下YOLOv2网络的改变,1.首先就是将YOLO网络层中的Dropout层转换为BN层(Batch Normalization),也叫做批归一化层。这是一个非常好的正则化方法。

2.其次就是,增加图像的分辨率,YOLOv2增加了在ImageNet数据集上使用448x448(原来为224x224)来训练分类过程,使用高频率的分类器,模型就更加准确。

 3.为了改变YOLO中的候选框个数太少的问题,YOLOv2使用了Faster R-CNN网络的先验框策略,并且把最后一层全连接层去除,改为卷积层。召回率也会得到很大的提升。

4.YOLOv2还改进了先验框的选取方式,它使用了K-means方法对锚框做了聚类分析。

 5.最后,YOLOv2约束了测边框的位置,YOLOv2调整了预测公式,将预测边框的中心约束在特定的网格内。

 除了上面说的这些,YOLOv2还提出了一中passthrough层来获取特征图,可以说,YOLOv2已经是非常优秀的网络结构,采用了很多优秀的方式,除了我上面列举的这些,还有其他很多的优点。

就像我上面说的,除了上面列举的这些YOLOv2网络还做出了很多的优化,比如损失函数优化,结构i优化等,例如我下面给出YOLOv2的损失函数的优化:

经过了这些的优化,YOLOv2网络的效率得到了很大的提升,我们可以看一下他们的效果对比:

可以说,YOLOv2已经是非常的完美了,但是,YOLO网络的作者又推出了YOLOv3网络,这也就奠定了YOLO网络不败的地步,下面我们来看看YOLOv2的网络结构代码:

#YOLOv2代码实现:
def darknet(images, n_last_channels=425):
    net = conv2d(images, 32, 3, 1, name="conv1")
    net = maxpool(net, name="pool1")
    net = conv2d(net, 64, 3, 1, name="conv2")
    net = maxpool(net, name="pool2")
    net = conv2d(net, 128, 3, 1, name="conv3_1")
    net = conv2d(net, 64, 1, name="conv3_2")
    net = conv2d(net, 128, 3, 1, name="conv3_3")
    net = maxpool(net, name="pool3")
    net = conv2d(net, 256, 3, 1, name="conv4_1")
    net = conv2d(net, 128, 1, name="conv4_2")
    net = conv2d(net, 256, 3, 1, name="conv4_3")
    net = maxpool(net, name="pool4")
    net = conv2d(net, 512, 3, 1, name="conv5_1")
    net = conv2d(net, 256, 1, name="conv5_2")
    net = conv2d(net, 512, 3, 1, name="conv5_3")
    net = conv2d(net, 256, 1, name="conv5_4")
    net = conv2d(net, 512, 3, 1, name="conv5_5")
    shortcut = net
    net = maxpool(net, name="pool5")
    net = conv2d(net, 1024, 3, 1, name="conv6_1")
    net = conv2d(net, 512, 1, name="conv6_2")
    net = conv2d(net, 1024, 3, 1, name="conv6_3")
    net = conv2d(net, 512, 1, name="conv6_4")
    net = conv2d(net, 1024, 3, 1, name="conv6_5")
    # ---------
    net = conv2d(net, 1024, 3, 1, name="conv7_1")
    net = conv2d(net, 1024, 3, 1, name="conv7_2")
    # shortcut
    shortcut = conv2d(shortcut, 64, 1, name="conv_shortcut")
    shortcut = reorg(shortcut, 2)
    net = tf.concat([shortcut, net], axis=-1)
    net = conv2d(net, 1024, 3, 1, name="conv8")
    # detection layer
    net = conv2d(net, n_last_channels, 1, batch_normalize=0,
                 activation=None, use_bias=True, name="conv_dec")
    return net
def decode(detection_feat, feat_sizes=(13, 13), num_classes=80,
           anchors=None):
    H, W = feat_sizes
    num_anchors = len(anchors)
    detetion_results = tf.reshape(detection_feat, [-1, H * W, num_anchors,num_classes + 5])
    bbox_xy = tf.nn.sigmoid(detetion_results[:, :, :, 0:2])
    bbox_wh = tf.exp(detetion_results[:, :, :, 2:4])
    obj_probs = tf.nn.sigmoid(detetion_results[:, :, :, 4])
    class_probs = tf.nn.softmax(detetion_results[:, :, :, 5:])
    anchors = tf.constant(anchors, dtype=tf.float32)
    height_ind = tf.range(H, dtype=tf.float32)
    width_ind = tf.range(W, dtype=tf.float32)
    x_offset, y_offset = tf.meshgrid(height_ind, width_ind)
    x_offset = tf.reshape(x_offset, [1, -1, 1])
    y_offset = tf.reshape(y_offset, [1, -1, 1])
    # decode
    bbox_x = (bbox_xy[:, :, :, 0] + x_offset) / W
    bbox_y = (bbox_xy[:, :, :, 1] + y_offset) / H
    bbox_w = bbox_wh[:, :, :, 0] * anchors[:, 0] / W * 0.5
    bbox_h = bbox_wh[:, :, :, 1] * anchors[:, 1] / H * 0.5
    bboxes = tf.stack([bbox_x - bbox_w, bbox_y - bbox_h,
                       bbox_x + bbox_w, bbox_y + bbox_h], axis=3)
    return bboxes, obj_probs, class_probs

 YOLOv3网络

前面说到YOLOv2已经是非常完美的网络模型,所以YOLOv3对于YOLOv2的改变并没有太多,只是对4个方面进行了改变。

1.使用多级预测,以前的YOLO只是用最后一张特征图作为预测结果,在YOLOv3中,使用最后三张特征图(13x13,26x26,52x52),用较大的特征图预测小物体,因为较大的特征图划分的更加细致,较小的特征图预测大物体,从而提高准确率。

2.将物体分类的损失改为逻辑回归损失,也就是说对每一个类别做预测,而不是以往的只输出概率最大的类别,采用复合标签更加的准确。

3.加深网络结构,从YOLOv2的darknet-19变成了YOLOv3的darkent-53,其实就是提高了算力。

4.YOLOv3使用K-means方法,将锚点框聚成9类,得到9类锚点框大小为:10x13,16x30,33x23,30x61,62x45,59x119,116x90,156x198和373x326.

SSD网络

SSD检测网络,全名为Single Shot MultiBox Detector。总的来说,和YOLO相比,SSD相比较差,但是比一般的网络模型强了太多,唯一的缺点就是速度慢,但是模型非常的完美。下面我们来介绍一下SSD网络:

1.1 模型

SSD方法基于前馈卷积网络,生成固定大小的边界框集和这些框中存在物体类别的置信度,接着使用非最大化抑制产生最终的检测结果。位于网络前面的一些层是基于做高质量图像分类的标准架构(截取该框架分类层之前的层),我们将其称为基础网络。然后,我们向网络添加辅助结构来利用下边的主要特征来生成感知器:

多尺度特征图检测:我们将卷积特征层添加到截断了的基础网络的尾端。这些层的尺寸逐渐减小并且允许多尺度的预测。用于检测的卷积模型对于每个特征层是不同的(而Overfeat [4]和YOLO[5]是在单个尺度特征图上操作的。

用于检测的卷积预测器:每个添加的特征层(或者基础网络的特征层)使用一系列卷积滤波器(filter)可以产生一系列固定的预测。这些在图2中SSD网络架构已指出。对于p通道大小为m*n的特征层,对于一个可能的检测,它的预测参数的基本元素是一个3*3*p的核,这个核产生决定每个类别的置信度或生成相对于默认框坐标的偏移量。在m*n的特征图的每个位置均应用这个卷积核,各自产生一个输出值。边界框偏移输出值与默认框相关,而默认框位置又是与每个特征图的位置相关(参见YOLO [5]的架构,它在这个步骤使用全连接层而不是卷积滤波器)

默认框与宽高比:我们为网络顶部的多个特征图的每个特征单元都关联固定的一组默认框。默认框以卷积形式作用于特征图,使得每个框相对于其对应的单元格的位置是固定的。我们为每个特征图单元预测相对于该单元格的默认框的偏移量,以及为每个类别预测反映框中该物体类别存在的置信度得分。具体来说,对于一个给定的位置的k个框中的每个框,我们都计算c个类的分数和相对于原始默认框的4个偏移值。这样致使总共有(c+4)k个滤波器作用于特征图中的每个位置,若特征图的大小为m*n,则会产生(c+4)*k*m*n个输出。有关默认框的说明,请参考图1。我们的默认框类似于Faster R-CNN [2]中使用的锚检查框(anchor boxes),但不同的是,我们将其应用于几个不同分辨率的特征图。在多个特征图上使用不同形状的默认框,致使有效地离散可能的输出框的形状的空间。

1.2 训练

训练SSD和训练使用区域候选框(region proposal)的典型分类器的主要不同点在于,真实标签需要被分配到固定的一组检测器输出中的某个特定的输出。YOLO [5]的训练阶段,Faster R-CNN [2]和MultiBox [7]的region proposal阶段也需要类似这样的操作。一旦把真实标签分配好,损失函数和反向传播就能端对端地应用。训练还包括选择一系列的默认框和用于检测的特征图尺度,以及难分样本挖掘(hard negative mining)和数据增强策略

匹配策略:在训练时,我们需要确定哪些默认框和哪个真实标签框关联,然后据此进行训练。对于每个真实标签框,我们选择一些位置、长宽比和吃尺寸大小都不同的默认框。开始时,我们把每个真实标签框与默认框中与之具有最佳的雅可比重叠值(best jaccard overlap )(跟MultiBox [7]的方法一样)的框匹配。与MultiBox不同的是,我们之后又将默认框与所有的真实标签框( ground truth box) 配对,只要两者之间的雅可比重叠值(jaccard overlap) 大于某个阈值(本文的阈值为 0.5)。 这样做简化了学习问题,它使得网络能够为多个重叠的默认框预测高的置信度,而不是要求它只选择具有最大重叠值的那个框。

训练目标:SSD训练的目标函数从MultiBox[7,8]中导出,但它进一步扩展到处理多个物体类别。

成为一个指示第i个默认框与类别p的第j个真实标签框的匹配指示器。根据上述的匹配策略,我们可以得到

,整体的目标损失函数是一个位置损失与置信度损失的加权和:

其中,N是匹配的默认框的数目,如果N=0,我们把loss设为0,位置损失是smooth l1 loss,这是一个介于预测框与真实框之间的参数,类似于faster r-cnn我们将对默认框的中心与框的长宽进行回归。

置信度损失是softmax 多类别分类损失函数

选择默认框的比例和宽高比:为了处理多个尺寸的物体,有些算法[4,9]提议处理具有不同尺寸的多张图片,然后把结果综合起来。但是用一个网络的不同层的特征图,也可以得到类似的效果,同时让所有不同尺寸的物体间能共享参数。之前的工作[10,11]已经表明使用较低层的特征图可以提高语义分割的质量,因为较低层能捕获到输入目标的更精细的细节。类似地,[12]指出,增加特征图的全局上下文池化有助于平滑分割结果。受这些方法启发,我们既用低层也用高层的特征图进行检测预测。图1展现了框架中使用的两个特征图(8×8和4×4)实例。在实践中,我们可以使用更多计算开销小的特征图。

通常网络中不同层次的特征图具有不同大小的感受野[13]。幸运的是,对于SSD框架,默认框不需要与每层的实际感受野对应。我们可以设计默认框的平铺(tiling),使得特定的特征图学习响应特定的物体尺度。假设我们要使用m个特征图做预测。每个特征图的默认框的尺寸可用下式计算:

其中Smin是0.2,Smax是0.9,意味着最底层是0.2,最高层是0.9,期间所有的层按规律递增,我们为默认的bbox应用了不同的长宽比,标记为

{1,2,3,0.5,0.3333},我们可以计算每个默认的bbox的长度与宽度

,对于长宽比为1的,我们也加了一个默认的bbox,尺度为

,特征图的每个位置有6个默认的box,我们设置每个bbox的中心为

其中|Fk|是第k个特征图的尺寸,在实际中,为了适应特定的数据集,大家也可以设置不同尺寸与长宽比的默认框,如何最优的设计这些也是一个开放的问题。

通过组合多个特征图在所有位置的不同尺寸和长宽比的所有默认框的预测,我们得到涵盖各种输入物体尺寸和形状的多样性的预测集。例如,图 1中的狗被匹配到4×4特征图中的某个默认框,但没有匹配到8×8特征图中的任何默认框。这是因为那些框具有不同的尺度,但都与狗的框不匹配,因此在训练期间这些框被认为是负的。

难分样本挖掘 :在匹配步骤后,大多数默认框都是负的,特别是当可能的默认框数量很大时。这导致了正负训练样本的严重不平衡。我们没有使用所有的负样本,而是先把负样本根据置信度损失进行从大到小排序,然后为每个默认框只选择分值最高的那些样本,这样做的目的是使得正负样本的比例不超过1:3. 我们发现这样还可以使得优化更快,训练更平稳

数据增强:为了使模型对不同大小、形状的输入目标更具鲁棒性,对每个图像通过随机采取以下策略之一进行采样:

  1. 使用整张原始输入图像
  2. 采样一个片段,使得与目标物体的最小的雅可比重叠为0.1,0.3,0.5,0.7,0.9之一。
  3. 随机采样一个部分

每个采样部分的大小为原图的[0.1,1],长宽比在1/2和2之间。如果真实标签框的中心位于采样部分内,则保留重叠部分。在上述采样步骤之后,将每个采样片大小调整为固定大小,并以0.5的概率进行水平翻转,还有对图片做一些跟[14]所描述的光度扭曲的操作。

 

对于SSD网络,他的闪耀点远远不及YOLO网络,但是他的闪光点依旧是存在的,他的模型是非常完美的,只是在运行速度上较慢,相比较于YOLO网络,SSD可以说是生不逢时,它本身是非常完美的,但是却和YOLO网络同时期。所以这里只是简单的介绍了一下。本节的只是就到此结束了,至于网络的搭建,后面的神经网络专栏会介绍的。拜拜了您嘞!

点赞加关注不迷路

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。