【YOLO系列】YOLO v3(网络结构图+代码)

您所在的位置:网站首页 x=2y-y2的图像 【YOLO系列】YOLO v3(网络结构图+代码)

【YOLO系列】YOLO v3(网络结构图+代码)

2023-05-24 01:36| 来源: 网络整理| 查看: 265

文章目录 网络结构YOLO v3YOLOv3-SPP 多尺度预测损失函数参考 最近在研究YOLO系列,打算写一系列的YOLO博文。在YOLO的发展史中,v1到v3算法思想逐渐完备,后续的系列也都以v3为基石,在v3的基础上进行改进,所以很有必要单独出一篇详细讲解v3的博文。

网络结构

从 Ali Farhadi的YOLO网站主页下载YOLOv3-320和YOLOv3-spp的权重。加了SPP结构的YOLO v3,mAP会更高,但是速度会变慢。 在这里插入图片描述 在这里插入图片描述

然后基于qqwweee/keras-yolo3项目中的convert.py文件将.weight转换成.h5格式。权重格式转换需要keras和tensorflow的环境。转换命令如下所示。

python convert.py yolov3.cfg yolov3.weights model_data/yolo.h5 python convert.py yolov3-spp.cfg yolov3-spp.weights model_data/yolov3-spp.h5

YOLO v3

权重格式转换后会打印出yolov3的各层级关联信息,基于此信息,得到下述的YOLOv3网络结构简图,从此结构简图中,可以看出,YOLO v3整体网络架构是一个全卷积神经网络,无池化层,它通过卷积的步长实现张量尺寸的变化。每个Resn起始都有一个PCBL,将卷积的步长设置为2使得输出张量尺寸是输入张量尺寸的1/2,五个Resn的总步长为32。

YOLO v3的基础组件简写为CBL,即卷积+BN+leaky relu激活函数的组合;v3中大量应用了Res_block,Resn中的n表示有几个res_unit,v3中负责提取图像特征的backbone网络主要由五个Resn组成,v3论文中称主干网络中总有53个卷积,所以backbone网络被称为Darknet-53。但是打印出来的网络结构,却有1+3(1+21)+5(1+22)+17(1+28)+17+9(1+24)=52个卷积,又下载YOLOv3-416的权重进行转换验证,主干网络仍有52个卷积。

在这里插入图片描述 backbone的keras代码表示如下所示:

def resblock_body(x, num_filters, num_blocks): '''A series of resblocks starting with a downsampling Convolution2D''' # Darknet uses left and top padding instead of 'same' mode x = ZeroPadding2D(((1,0),(1,0)))(x) # padding x = DarknetConv2D_BN_Leaky(num_filters, (3,3), strides=(2,2))(x) # 步长为2,输出尺寸为1/2输入尺寸 for i in range(num_blocks): # 残差块 y = compose( DarknetConv2D_BN_Leaky(num_filters//2, (1,1)), # 残差结构中的1*1卷积 DarknetConv2D_BN_Leaky(num_filters, (3,3)))(x) # 残差结构中的3*3卷积 x = Add()([x,y]) return x def darknet_body(x): '''Darknent body having 52 Convolution2D layers''' x = DarknetConv2D_BN_Leaky(32, (3,3))(x) x = resblock_body(x, 64, 1) #Res1 x = resblock_body(x, 128, 2) #Res2 x = resblock_body(x, 256, 8) #Res8 x = resblock_body(x, 512, 8) #Res8 x = resblock_body(x, 1024, 4) #Res4 return x YOLOv3-SPP

如下图所示,YOLOv3-SPP相比于YOLO v3多了一个空间金字塔池化SPP(Space Pyramid Pooling)结构。SPP的提出本来是为了解决剪裁、缩放等操作导致的图像失真问题,不用限制输入图像的尺寸大小,输出尺寸都是固定的。但是YOLO v3是全卷积神经网络,无全连接层,那么不需要固定尺寸的输入,为什么要加入SPP呢?而且加入SPP后能大幅提升精度?

在这里插入图片描述

YOLOv3-SPP中是由四个并行的分支构成的,三个池化层和一个跳跃连接,然后将此四个分支Concatenate,比原SPP增加了一个跳跃连接。YOLO v3通过SPP实现了局部特征和全局特征的融合,丰富了特征图的表达能力。如上图所示,SPP只被添加在第一个输出分支上,第二第三输出分支和YOLO v3保持一致。第二第三分支将两个相邻Res_block块的特征进行融合,某种程度上已经实现了不同程度的局部特征的融合,丰富了特征图的表达能力。所以,增加SPP能够提升检测的精度。

多尺度预测

从上述简图中,可以看出YOLO v3是在3个不同尺寸的特征图上进行预测的,这是YOLO v3的一个基本特征,多尺度预测,有助于获得更精细的检测框,可以大大改善对小物体的检测。如果输入的图像大小为 416 × 416 416\times 416 416×416,那么最后三个输出特征图的大小从上往下分别是 13 × 13 13 \times 13 13×13, 26 × 26 26 \times 26 26×26和 52 × 52 52 \times 52 52×52。每种尺度的特征图上每个网格预测3个bbox,对于COCO数据集,每个特征图将的预测张量大小 N × N × [ 3 ∗ ( 4 + 1 + 80 ) ] N \times N \times [ 3 * (4 + 1 + 80)] N×N×[3∗(4+1+80)]。其中N的取值是[12,26,52],4是bbox的4个偏移量,1是物体预测置信度,80是COCO物体类别数量。 在这里插入图片描述

v3是通过上采样的方式实现多尺度的特征图。backbone中的每一个Res_block中第一个卷积会将步长设为2,使得特征图的尺寸缩小1倍。从上述的YOLO v3特征图中,我们可以看到有两次上采样,上采样操作将特征图的尺寸扩大一倍,这样得到的特征图尺寸就可以和上一个Res_block的特征图尺寸相同,将两个特征图进行Concatenate操作后,再经过5个CBL和CBL->C操作后就得到最后的输出特征图。

下述代码描述了yolov3的模型结构,make_last_layers为每个尺度分支最后的卷积层,x和y分别对应上述结构图中的CBL*5和CBL->C。yolo_body函数中,第一次上采样得到的特征图和darknet.layers[152].output(backbone中的第二个Res8输出)进行合并操作;第二次上采样的特征图和darknet.layers[92].output(backbone中的第一个Res8输出)进行合并操作。最后的输出有三个分别是y1,y2和y3。

def make_last_layers(x, num_filters, out_filters): '''6 Conv2D_BN_Leaky layers followed by a Conv2D_linear layer''' # x为上述结构图中的CBL*5 x = compose( DarknetConv2D_BN_Leaky(num_filters, (1,1)), DarknetConv2D_BN_Leaky(num_filters*2, (3,3)), DarknetConv2D_BN_Leaky(num_filters, (1,1)), DarknetConv2D_BN_Leaky(num_filters*2, (3,3)), DarknetConv2D_BN_Leaky(num_filters, (1,1)))(x) # y为上述结构图中的CBL->C y = compose( DarknetConv2D_BN_Leaky(num_filters*2, (3,3)), DarknetConv2D(out_filters, (1,1)))(x) return x, y def yolo_body(inputs, num_anchors, num_classes): """Create YOLO_V3 model CNN body in Keras.""" darknet = Model(inputs, darknet_body(inputs)) # backbone x, y1 = make_last_layers(darknet.output, 512, num_anchors*(num_classes+5)) # 第一次上采样 x = compose( DarknetConv2D_BN_Leaky(256, (1,1)), UpSampling2D(2))(x) x = Concatenate()([x,darknet.layers[152].output]) x, y2 = make_last_layers(x, 256, num_anchors*(num_classes+5)) # 第二次上采样 x = compose( DarknetConv2D_BN_Leaky(128, (1,1)), UpSampling2D(2))(x) x = Concatenate()([x,darknet.layers[92].output]) x, y3 = make_last_layers(x, 128, num_anchors*(num_classes+5)) return Model(inputs, [y1,y2,y3])

YOLO v3中仍然沿用了v2中用k-means聚类确定bbox的尺寸大小,v3中选了如下9种anchors。

10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326

九种anchor,三种不同尺度的输出特征图,每个尺度特征图中的每个grid cell预测3个bbox,那也就是说每种尺度的输出特征图上分配到3个anchors。下采样的倍数越大,其对应的感受野(特征图上的某个点能看到的输入图像的区域)也就越大,那么其对应的特征图更适合检测大物体;相反,下采样的倍数越小,其对应的感受野越小,那么相对应的特征图包含的特征趋向于局部和细节,更适合小物体的检测。 下述代码将真实框转换成训练的输入格式,从下述代码中,我们也可以看出anchor的大小与不同尺度输出特征图的对应关系。

def preprocess_true_boxes(true_boxes, input_shape, anchors, num_classes): '''Preprocess true boxes to training input format Parameters ---------- true_boxes: array, shape=(m, T, 5) Absolute x_min, y_min, x_max, y_max, class_id relative to input_shape. input_shape: array-like, hw, multiples of 32 anchors: array, shape=(N, 2), wh num_classes: integer Returns ------- y_true: list of array, shape like yolo_outputs, xywh are reletive value ''' assert (true_boxes[..., 4]


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3