深度学习

目标检测 YOLO 篇(2)

2020-05-24  本文已影响0人  zidea
machine_learning.jpg

我们先来计划一下分享内容,接下来我们分享就进入了边读源码边分析过程,大概就是这个计划,今天我们来分享网络模型,先说原理然后通过代码把网络结构实现

YOLOv3

我们对图片分别按 13 \times 1326 \times 2652 \times 52 进行分割得到图片网格,这样做好处是我们使用不同尺寸网格来实现对图像不同大小物体都可以进行目标检测,不会丢掉小的物体,例如 52 \times 52 的网格能够识别更多物体,而且物体的体积可以更小。所以我们用 13 \times 1326 \times 2652 \times 52 网格分别识别大、中和小物体。 这样做避免小物体在多次卷积之后物体信息丢失。每个网格点负责其右下角物体检测。
如果物体的中心点落在某一个网格中,那么该网格就具有该物体位置和种类信息。 这句话很重要,希望大家能够理解。

YOLOv3 实现

我们重点就是分享 YOLOv3 是如何实现目标检测,我们根据 YOLOv3 模型结构图,一步一步来分析 YOLOv3 的目标检测算法。这是一个非常优秀的目标检测算法。为什么说优秀呢,一方面是因为 YOLOv3 表现优秀,而且算法结构还不是那么复杂。



只有大家将这张图吃透,随后才能够轻松地用代码来将其一步一步实现,不然就是只能大概读懂源码,至于每一块为什么要这样做,还是 consufing。

主干网络

左边的部分是 YOLOv3 算法的主干特征提取网络,其功能就是提取特征。

预测网络

实现主体网络

from keras.models import Model
from keras.layers import Input

model_input = Input(shape(416,416,3))

model = Modle(model_input,model_output)
model_input = Input(shape(416,416,3))
model_output = body(model_input)
model = Modle(model_input,model_output)

接下来工作就是搭建 yolov3 的主题网络,也称称为 backbone 网络,用于提取不同尺寸大小的特征图,Darknet53.要写好代码我们就需要熟悉 yolo 网络结构,然后按照结构图一层一层的实现

def body(inputs,num_anchors,num_classes):

我们都已经知道主体网络用于提取特征,body 方法用于构建主体网络,接收 3 个参数分别

return [y1,y2,y3]

那么输出就是 3 种不同尺寸的


我们对照图来一层一层写代码来实现设计图中的层或块,其实我们实现深度学习算法通常做法是打开一个设计好网络结构图,然后对照图一行一行地实现。图中的乘 1 ,乘 2 表示该块重复次数,
块名称 数量 filters size output
CBL 1 32 3 \times 3 416 \times 416 \times 32
PCBL 1 32 3 \times 3/2 208 \times 208 \times 64
CBLR 1 32 1 \times 1
1 64 3 \times 3 208 \times 208 \times 64
PCBL 1 128 3 \times 3/2 104 \times 104 \times 128
CBLR 1 64 1 \times 1
8 256 3 \times 3 104 \times 104 \times 128
PCBL 1 256 3 \times 3/2 52 \times 52 \times 256
CBLR 1 128 1 \times 1
8 256 3 \times 3 52 \times 52 \times 256
PCBL 1 512 3 \times 3/2 26 \times 26 \times 512
CBLR 1 256 1 \times 1
8 512 3 \times 3 26 \times 26 \times 512
PCBL 1 1024 3 \times 3/2 13 \times 13 \times 1024
CBLR 1 512 1 \times 1
4 1024 3 \times 3 13 \times 13 \times 1024
def body(inputs,num_anchors,num_classes):
    out = []
    x = CBL(inputs,32,(3,3))
    n = [1,2,8,8,4]
    for i in range(5):
        x = PCBL(x,2**(6+i))
        for _ in range(n[i]):
            x = CBLR(x,2**(5+i))

        if i in [2,3,4]:
            out.append(x)

通过 for 循环我们将重复部分提炼出来,n = [1,2,8,8,4] 然后我们图中每一个重复块前还有一个

在 CBL 中使用到的卷积 conv

定义卷积 conv 方法

卷积用到的参数有字典参数和列表参数

def conv(x):
def conv(*args,**kwargs):
    new_kwargs = {'kernel_regularizer':l2(5e-4)}
    new_kwargs['padding'] = 'valid' if kwargs.get('strides') == (2,2) else 'same'
    new_kwargs.update(kwargs)

    return Conv2D(*args,**new_kwargs)

定义 CBL 层(块)

CBL 是我们网络结构的基础,也是出现最多结构,其结构包括以下部分

def CBL(x,*args,**kwargs):
    new_kwargs ={ 'use_bias': False}
    new_kwargs.update(kwargs)
    x = conv(*args,**new_kwargs)(x)
    x = BatchNormalization()(x)
    x = LeakyReLU(alpha=0.1)(x)

这里用到了 L2 正则,L2 正则是控制参数
我们通过卷积的步长(stride)来决定卷积,其实这些都卷积的基础知识。我们
引入依赖

from keras.regularizers import l2
from keras.layers import Conv2D

定义 PCBL 块

用于在完成每一个块对卷积结果进行一次下采样,功能等于一个池化层将通过 stride=(2,2) 将图片长宽缩小为原来的 \frac{1}{2}

def PCBL(x,num_filters):
    x = ZeroPadding2D(((1,0),(1,0)))(x)
    x = CBL(x,num_filters,(3,3),strides=(2,2))

    return x

CBLR 块

CBLR 就是我们在图中重复结构,显示一个 1 \times 1 卷积,用于对通道数减半的卷积,接下拉就是3 \times 3 卷积层同时将通道数翻倍。随后一个将输入和输出在通道上进行叠加通道数翻倍。

def CBLR(x,num_filters):
    y = CBL(x,num_filters,(1,1))
    y = CBL(y,num_filters*2,(3,3))
    x = Add()([x,y])

    return x

检测网络

屏幕快照 2020-05-24 下午3.55.08.png

接下来将主干网络提取特征通过处理输出我们之前提到的 3 中不同尺寸的矩阵

    x1 = CBL5(out[2],512)
    y1 = CBLC(x1,512,num_anchors*(num_classes+5))

    x = CBLU(x1,256)
    x = Concatenate()([x,out[1]])

    x2 = CBL5(x,256)
    y2 = CBLC(x2, 256, num_anchors * (num_classes + 5))

    x = CBLU(x2,128)
    x = Concatenate()([x, out[0]])

    x3 = CBL5(x,128)
    y3 = CBLC(x3, 128, num_anchors * (num_classes + 5))

    return [y1,y2,y3]

CBL5 层

这个解构就是

def CBL5(x,num_filters):
    x = CBL(x, num_filters, (1,1))
    x = CBL(x, num_filters*2, (3,3))
    x = CBL(x, num_filters, (1,1))
    x = CBL(x, num_filters*2, (3,3))
    x = CBL(x, num_filters, (1,1))

    return x

CBLC

def CBLC(x,num_filters,out_filters):
    x = CBL(x, num_filters * 2, (3, 3))
    x = conv(out_filters,(1,1))(x)

    return x

CBLU 层

在 CBL 层上添加一个上采样层,经过 CBLU 后宽度和长度翻倍便于参加网格较大尺寸的层输出。例如13 \times 13 会经过 CBLU 扩大为26 \times 26

def CBLU(x, num_filters):
    x = CBL(x, num_filters, (1, 1))
    x = UpSampling2D(2)(x)

    return x
上一篇下一篇

猜你喜欢

热点阅读