YOLOV3函数详细笔记(1)


@如有侵权,联系我删除

代码复写加记录

代码来自 qqwweee,以及看了另一个博主Bubbliiiing的讲解.复现读懂以后也记录一下自己的理解,方便以后回顾。

训练需要的文件或函数

utils.py

首先是utils.py文件下的函数,除去letterbox_image这个函数是用在预测图片的时候的,其余这个文件中的函数在训练的时候都会用到。
首先是compose函数,用在模型搭建的时候,用于连接DarknetConv2D、BatchNormalization与LeakyReLU组成DBL块。

from functools import reduce
# 连接Darknet中的层,例如DBL块的组成
def compose(*funcs):
    if funcs:
        return reduce(lambda f, g: lambda *a, **kw: g(f(*a, **kw)), funcs)
    else:
        raise ValueError('Composition of empty sequence not supported.')

用这个函数的时候只需要将需要连接的操作放入其中即可,例如compose( DarkNetConv2D(), BatchNormalization(), LeakyReLU()),其实就是简化了手写序列模型一步一步将这三个操作连接到一起,功能是一样的,只是这个函数看着简单而且高级。
rand(a=0.0, b=1.0)函数只是用来随机出一个a-b区间的值。
get_random_data是对图片进行图片增强,大小调整,旋转,颜色抖动,归一化。涉及到的参数:

  • max_boxes:一张图片上最多有多少个真实框。
  • jitter:长宽比的随机比例系数,0~1之间。
  • hue,sat,val:颜色抖动是从RGB->HSV->RGB,这三个参数值给定了,有颜色抖动方面经验的可以修改,默认值也没什么问题。

yolov3_model

我将yolov3模型搭建所需要的用到的函数都放在了这里,方便。
先来写构建模型的基础网络块。
首先是DarkNet卷积操作,改写了Conv2D,进行了正则,并定义了padding在不同的strides时的值。
DarkNetConv2D

from functools import wraps
from tensorflow.keras.layers import Conv2D, BatchNormalization, LeakyReLU, ZeroPadding2D
from tensorflow.keras.regularizer import l2

@wraps(Conv2D)
def DarknetConv2D(*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)

DBL(简称:DarkNetConv2D + BatchNormalization + ReLU)
不使用偏差b

def DBL(*arg, **kwargs):
    no_bias_kwargs = {'use_bias': False}
    no_bias_kwargs.update(kwargs)
    return compose(
        DarkNetConv2D(*arg, **no_bias_kwargs),
        BatchNormalization(),
        LeakyReLU(alpha=0.1)
    )

residual(ResNet结构)

def resblock_body(x, num_filters: int, num_blocks: int):
    x = ZeroPadding2D(((1, 0), (1, 0)))(x)
    x = DBL(num_filters, (3, 3), strides=(2, 2))(x)
    for _ in range(num_blocks):
        y = DBL(num_filters // 2, (1, 1))(x)
        y = DBL(num_filters, (3, 3))(y)
        x = Add()([x, y])
    return x

至此构建网络模型的基础函数就写完了,接下来就是安网络图开始构建模型了。
先写DarkNet53部分的函数,依据网络图,返回的是DarkNet需要向外连接的层。

def DarkNet_body(x):
    x = DBL(32, (3, 3))(x)
    x = resblock_body(x, 64, 1)
    x = resblock_body(x, 128, 2)
    x = resblock_body(x, 256, 8)
    feat1 = x  # (batch_size, 52, 52, 256) 非最后的输出层,而是darknet主体中需要向外连接的层
    x = resblock_body(x, 512, 8)
    feat2 = x  # (batch_size, 26, 26, 512)
    x = resblock_body(x, 1024, 4)
    feat3 = x  # (batch_size, 13, 13, 1024)
    return feat1, feat2, feat3

对于返回的三个feat,我们要分别对其进行处理,进行上采样和拼接等操作,就需要写一个make_last_layers函数。

def make_last_layers(x, num_filters: int, out_filters: int):
    x = DBL(num_filters, (1, 1))(x)
    x = DBL(num_filters * 2, (3, 3))(x)
    x = DBL(num_filters, (1, 1))(x)
    x = DBL(num_filters * 2, (3, 3))(x)
    x = DBL(num_filters, (1, 1))(x)

    y = DBL(num_filters * 2, (3, 3))(x)
    y = DBL(out_filters, (1, 1))(y)
    return x, y

上面的函数写完终于到最后的网络模型图整体还原了。yolo_body就是对整个yoloV3网络图的还原,它的输出即网络图的三个输出特征层。

def yolo_body(inputs, num_anchors: int, num_classes: int):
    darnet_body = Model(inputs, DarkNet_body(inputs))
    feat1, feat2, feat3 = darnet_body.output

    # y1 (batch_size, 13, 13, 3*25)
    x, y1 = make_last_layers(feat3, 512, num_anchors * (num_classes + 5))

    x = compose(
        DBL(256, (1, 1)),
        UpSampling2D(2)
    )(x)
    x = Concatenate()([x, feat2])

    # y2 (batch, 26, 26, 3*25)
    x, y2 = make_last_layers(x, 256, num_anchors * (num_classes + 5))

    x = compose(
        DBL(128, (1, 1)),
        UpSampling2D(2)
    )(x)
    x = Concatenate()([x, feat1])

    # y3 (batch_size, 52, 52, 3*25)
    x, y3 = make_last_layers(x, 128, num_anchors * (num_classes + 5))

    return Model(inputs, [y1, y2, y3])

inputs:网络的输入,一般为网络模型图上的(416, 416, 3)
y1, y2, y3:对应网络模型图的三个输出特征层
tiny_yolo_body
这是额外的模型,为什么说是额外的?因为上面是一个完整的yoloV3的构建,但由于DarkNet53网络层相对有一定的深度,若没有好一点的GPU支持,很难有效运行,因此就有一个简单版本的yoloV3,思想上借鉴了YOLOV3的思想,但模型相对简单了许多,参数量也小了很多。
如果用tiny_yolo_body,就不需要写Darknet_bodymake_last_layers这两个函数了,因为不需要DarkNet53这个主体了。

def tiny_yolo_body(inputs, num_anchors, num_classes):
    x1 = compose(
            DBL(16, (3,3)),
            MaxPooling2D(pool_size=(2,2), strides=(2,2), padding='same'),
            DBL(32, (3,3)),
            MaxPooling2D(pool_size=(2,2), strides=(2,2), padding='same'),
            DBL(64, (3,3)),
            MaxPooling2D(pool_size=(2,2), strides=(2,2), padding='same'),
            DBL(128, (3,3)),
            MaxPooling2D(pool_size=(2,2), strides=(2,2), padding='same'),
            DBL(256, (3,3)))(inputs)
    x2 = compose(
            MaxPooling2D(pool_size=(2,2), strides=(2,2), padding='same'),
            DBL(512, (3,3)),
            MaxPooling2D(pool_size=(2,2), strides=(1,1), padding='same'),
            DBL(1024, (3,3)),
            DBL(256, (1,1)))(x1)
    y1 = compose(
            DBL(512, (3,3)),
            DarkNetConv2D(num_anchors*(num_classes+5), (1,1)))(x2)

    x2 = compose(
            DBL(128, (1,1)),
            UpSampling2D(2))(x2)
    y2 = compose(
            Concatenate(),
            DBL(256, (3,3)),
            DarkNetConv2D(num_anchors*(num_classes+5), (1, 1)))([x2, x1])

    return Model(inputs, [y1, y2])

后记

这就是模型的构建代码过程及代码了,模型图网上很多,就不放了。主要还是对每个函数的理解是最重要的,想要做什么事情,怎样去完善其中的细节,理解代码的含义,然后就是对代码的改进了。
这个代码是github上一位大神的代码,也就是我开头写的那位,不过由于他当时写的时候是使用的TensorFlow1作为后端,前端代码使用的是keras,而现在这个代码也是经过修改以后可以适配TensorFlow2版本了,网上也有一些大佬开源了TensorFlow2版本的YOLOV3,我感觉那些代码还是看着比较费劲(个人能力不行,怪我自己)。还是这个代码比较便于理解,以后还会改进代码,让代码更适应于TensorFlow2版本,并且性能效率上也要有一定的提升,毕竟上层代码灵活性较低,对于没有好GPU的我来说确实难受,VGG网络是根本就跑不动的,直接炸显存。
代码从大佬那学的,本篇博主要还是分享一下代码的详细过程,因为自己在看YOLOV3的时候苦于没有详细的一步一步诱导的那种教程,啃的极其费劲,一度想放弃。略懂了一点还是要分享一下的,共同促进成长。
兴趣使然~

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据引用和引用的内容,YOLOv8是一种目标检测模型。与YOLOv5相比,YOLOv8的yaml配置文件改动较小。YOLOv8采用了Anchor-Free的思想,使用VFL Loss、DFL Loss和CIOU Loss作为分类损失函数,并采用了Task-Aligned Assigner匹配方式进行样本匹配。此外,YOLOv8还引入了YOLOv8 Nano(速度最快)和YOLOv8 Extra Large(准确性最高)等不同规模的模型。 如果你想学习YOLOv8的相关知识,可以参考官方文档或者专业的教程。这些资源可以帮助你理解YOLOv8的原理、配置文件和模型性能,并帮助你开始使用和学习YOLOv8。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [YOLOv8模型学习笔记](https://blog.csdn.net/pengxiang1998/article/details/129151514)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [YOLOv8学习笔记](https://blog.csdn.net/GoodTime1110/article/details/129767920)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值