yolov3前向传播(一)-- darknet53网络解析与实现

一、darknet53网络解析与实现

一、darknet53网络结构组成部分

darknet53网络是由 darknet块 下采样卷积块组成的

1、darknet块

1.1 darknet块网络结构

1.2 darknet块网络实现代码
def _darknet53_block(inputs,filters):
    '''
    :param inputs: tensor  形状[batch, height_in, width_in, channels].channel 要等于 filters*2 保证最后可以相加
    :param filters: 卷积核数量  int类型
    :return: darknet块输出 tensor 形状[batch, height_in, width_in, channels]
    '''
    shortuct = inputs
    # 正常的 1x1步长为1的卷积 卷积核数为filters 只改变通道数没有改变输入的形状 通道数变为 filters
    # 权重默认初始化 weights_initializer=initializers.xavier_initializer()
    # 偏置值默认初始化 biases_initializer=init_ops.zeros_initializer()
    # 默认激活函数 activation_fn=nn.relu
    inputs = slim.conv2d(inputs, filters, 1, stride=1, padding='SAME')
    # 正常卷积3x3步长为1的卷积 卷积核数为filters*2,只改变通道数没有改变输入的形状 通道数变为 filters*2
    inputs = slim.conv2d(inputs, filters*2, 3, stride=1, padding='SAME')
    inputs = inputs + shortuct
    return inputs

2、下采样卷积块

2.1、下采样卷积说明

每两个darknet块中间都有一个单独的卷积层,他们都是下采样卷积,
他们是通过将原有的输入补0,再通过步长为2,卷积核为3的VALID卷积来实现

2.1.1 输入补0的实现
def _fixed_padding(inputs,kernel_size,*args,mode = 'CONSTANT',**kwargs):
    '''
    :param inputs: 输入  类型tensor  形状 [batch, height_in, width_in, channels].
    :param kernel_size: 卷积核数量  int类型
    :param mode: 填补模式
    :return:
    '''
    # 计算填补的行列个数
    pad_total = kernel_size - 1
    pad_beg = pad_total // 2
    pad_end = pad_total - pad_beg
    # 使用tf.pad(tensor,paddings,mode='CONSTANT',name=None,constant_values=0)函数填充  其参数如下
    # tensor      被填充的张量
    # paddings    填充的格式
    # mode        填充模式:"CONSTANT"、"REFLECT"、"SYMMETRIC"
    # name        该操作张量的名称
    # constant_values 用于在"CONSTANT"模式下,设置的填充值
    # pad = np.array([[‘上’,‘下’], [‘左’,‘右’]])
    # pad_上边补1行 = np.array([[1, 0], [0, 0]])
    # pad_下边补2行 = np.array([[0, 2], [0, 0]])
    # pad_左边补3行 = np.array([[0, 0], [3, 0]])
    # pad_右边补4行 = np.array([[0, 0], [0, 4]])
    # pad1 = np.array([[‘顶’,‘底’],[‘上’,‘下’], [‘左’,‘右’ ]])
    # pad_top = np.array([[1, 0], [0, 0], [0, 0]])      顶补0
    # pad_left = np.array([[0, 0], [0, 0], [3, 0]])     底补0
    padded_inputs = tf.pad(inputs, [[0, 0], [pad_beg, pad_end], [pad_beg, pad_end], [0, 0]], mode = mode)
    # [0, 0] 第一个维度两边不补 [pad_beg, pad_end]第二个维度一边补pad_beg个0另一边补pad_end个0
    # [pad_beg, pad_end]第三个维度一边补pad_beg个0另一边补pad_end个0 [0, 0] 第四个维度两边不补
    return padded_inputs
2.2、下采样卷积块实现

使用自定义函数实现下采样卷积

def _conv2d_fixed_padding(inputs,filters,kernel_size,strides):
    '''
    :param inputs: 输入  类型tensor  形状 [batch, height_in, width_in, channels].
    :param filters: 卷积核数量  int类型
    :param kernel_size: 卷积核的大小 类型tensor 形状 [h w]
    :param strides: 卷积步长 默认是 1
    :return: 下采样卷积结果  类型tensor  形状[batch, height_in, width_in, channels]
    '''
    assert strides > 1  # 表达式为真程序执行 否则报错
    inputs = _fixed_padding(inputs,kernel_size)  # 外围填充0,支持VALID卷积
    inputs = slim.conv2d(inputs,filters,kernel_size,stride=strides,padding='VALID')
    return inputs

二、darknet53网络实现

1、darknet53网络结构

在这里插入图片描述

2、darknet53网络实现

def darknet53(inputs):
    '''
    :param inputs:  输入  类型tensor  形状 [batch, height_in, width_in, channels].
    :return: 返回3中不同尺度的特征图
    '''
    # 假设输入inputs 大小为 416*416
    # 正常卷积 conv_3x3_32 ,卷积核默认初始化
    inputs = slim.conv2d(inputs, 32, 3, stride=1, padding='SAME')
    # 下采样卷积 卷积后的形状为(-1,208,208,64)
    inputs = _conv2d_fixed_padding(inputs, 64, 3, strides=2)
    # darknet块 输出形状(-1,208,208,64)
    inputs = _darknet53_block(inputs, 32)
    # 下采样卷积 卷积后的形状为(-1,104,104,128)
    inputs = _conv2d_fixed_padding(inputs, 128, 3, strides=2)

    # 2次darknet块 输出形状(-1,104,104,128)
    for i in range(2):
        inputs = _darknet53_block(inputs,64)
    # 下采样卷积,输出形状(-1, 52, 52, 256)
    inputs = _conv2d_fixed_padding(inputs, 256, 3, strides=2)

    # 8次darknet块 ,输出形状(-1, 52, 52, 256)
    for i in range(8):
        inputs = _darknet53_block(inputs, 128)
    route_1 = inputs
    # ====================================================== 特征图1形状(-1, 52, 52, 256)
    # 下采样卷积,输出形状(-1,26,26,512)
    inputs = _conv2d_fixed_padding(inputs, 512, 3, strides=2)

    # 8次darknet块 ,输出形状(-1, 26, 26, 512)
    for i in range(8):
        inputs = _darknet53_block(inputs, 256)
    route_2 = inputs
    # ====================================================== 特征图2形状(-1, 26, 26, 512)
    # 下采样卷积,输出形状(-1,13,13,1024)
    inputs = _conv2d_fixed_padding(inputs, 1024, 3, strides=2)

    for i in range(4):
        inputs = _darknet53_block(inputs, 512)
    # ====================================================== 特征图3形状(-1,13,13,1024)
    return route_1, route_2, inputs

三、测试darknet53网络是否能跑通

我们使用生成的随机数来模拟图片输入网络,看一下输出结果是否是我们想要的

batch_size = 5
height, width = 416, 416
inputs = tf.random_uniform((batch_size, height, width, 3))  # 模拟图片
a,b,c = darknet53(inputs)

init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)
a,b,c = sess.run([a,b,c])
print(sess.run([tf.shape(a),tf.shape(b),tf.shape(c)]))

输出结果:
在这里插入图片描述

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值