keras-yolo3项目之YOLO3主网络层的实现及解析

YOLOV3的网络结构

在YOLOV3的论文中,给出的网络结构(Darknet-53)如下:
在这里插入图片描述
上图中,Convolutional表示卷积层,左侧的数字(1,2,8,8,4)表示所框选的卷积层重复的次数,由此可得卷积层共有52个;Residual 表示残差结构,以上图为例,第1个残差结构出现在第5行,表示第2行卷积运算之后的结果与第4行的卷积运算结果进行相加。

注,每行中数字的含义,以第二行为例:该层卷积核的大小为 3 ∗ 3 3*3 33,卷积核移动的步长为2(默认为1),最终输出64张128*128的单通道图像。

YOLOV3主网络层的代码实现

from functools import wraps,reduce

import numpy as np
import tensorflow as tf
from tensorflow.keras.utils import plot_model
from tensorflow.keras import backend as K
from tensorflow.keras.layers import Conv2D,Add,ZeroPadding2D,UpSampling2D,Concatenate,MaxPooling2D,LeakyReLU,BatchNormalization,Input,Lambda
from tensorflow.keras.models import Model
from tensorflow.keras.regularizers import l2

def compose(*funcs):
    """
    Compose arbitrarily many functions, evaluated left to right.
    组合多个函数,从左到右进行计算
    Reference: https://mathieularose.com/function-composition-in-python/
    """
    # return lambda x: reduce(lambda v, f: f(v), funcs, x)
    if funcs:
        # 函数嵌套,后一个函数套前一个函数,即将前一个函数的输出作为后一个参数的输入,从前往后按顺序计算
        return reduce(lambda f, g: lambda *a, **kw: g(f(*a, **kw)), funcs)
    else:
        raise ValueError('Composition of empty sequence not supported.')

@wraps(Conv2D)
def DarknetConv2D(*args, **kwargs):
    """
    Wrapper to set Darknet parameters for Convolution2D.
    2维卷积层参数
    args:长度可变的参数列表
    kwargs:带参数名称的、长度可变的参数列表
    """
    darknet_conv_kwargs = {'kernel_regularizer': l2(5e-4)}
    darknet_conv_kwargs['padding'] = 'valid' if kwargs.get('strides')==(2,2) else 'same'
    darknet_conv_kwargs.update(kwargs)
    
    return Conv2D(*args, **darknet_conv_kwargs)

def DarknetConv2D_BN_Leaky(*args, **kwargs):
    """Darknet Convolution2D followed by BatchNormalization and LeakyReLU."""
    no_bias_kwargs = {'use_bias': False}
    no_bias_kwargs.update(kwargs)
    return compose(
        DarknetConv2D(*args, **no_bias_kwargs),
        BatchNormalization(),
        LeakyReLU(alpha=0.1))

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)
    x = DarknetConv2D_BN_Leaky(num_filters, (3,3), strides=(2,2))(x)
    for i in range(num_blocks):
        y = compose(
                DarknetConv2D_BN_Leaky(num_filters//2, (1,1)),
                DarknetConv2D_BN_Leaky(num_filters, (3,3)))(x)
        x = Add()([x,y])
    return x

def darknet_body(x):
    '''Darknent body having 52 Convolution2D layers'''
    x = DarknetConv2D_BN_Leaky(32, (3,3))(x)    #1
    x = resblock_body(x, 64, 1)    #3
    x = resblock_body(x, 128, 2)    #5
    x = resblock_body(x, 256, 8)    #17
    x = resblock_body(x, 512, 8)    #17
    x = resblock_body(x, 1024, 4)    #9
    return x

def make_last_layers(x, num_filters, out_filters):
    '''6 Conv2D_BN_Leaky layers followed by a Conv2D_linear layer'''
    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 = 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))
    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],name="yolov3_model")

YOLOV3主网络层可视化

在这里插入图片描述
上图中:

  1. input_1:InputLayer对应输入层,输入是一张 416 ∗ 416 416*416 416416 3 3 3通道图像(在深度学习中,通常将其理解为一张 416 ∗ 416 416*416 416416的图像,该图像有 3 3 3个特征分别是:R、G、B);
  2. conv2d:Conv2Dadd_22:Add层的输出,对应的是yolo_body函数的第一行(darknet_body函数),即,Darknet-53模型的实现;
  3. add_22:Addconv2d_58:Conv2D对应yolo_body函数中的make_last_layers函数,其中leaky_re_lu56:LeakyReLu的输出对应xconv2d_58:Conv2D的输出对应y1
  4. conv2d_59:Conv2Dconv2d_66:Conv2D对应yolo_body函数中的y2add_18:Add层对应的是yolo_body函数中的darknet.layers[152]
  5. conv2d_74:Conv2D的输出对应yolo_body函数中的y3add_10:Add层对应的是yolo_body函数中的darknet.layers[92]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

great-wind

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值