YOLOV5代码阅读

yolo.py目录

v FILE

v ROOT

c Detect(nn.Module)

m __init__(self, nc=80, anchors=(), ch=(), inplace=True)

m forward(self, x)

m _make_grid(self, nx=20, ny=20, i=0, torch_1_10=check_version(torch.__version__, '1.10.0'))

f anchor_grid

f dynamic

f export

f grid

f inplace

f m

f nc

f nl

f nc

f no

f stride

c Segment(Detect)

m __init__(self, nc=80, anchors=(), nm=32, npr=256, ch=(), inplace=True)

m forward(self, x)

f detect

f m

f nm

f no

f npr

f proto

c BaseModel(nn.Module)

m forward(self, x, profile=False, visualize=False)

m _forward_once(self, x, profile=False, visualize=False)

m _profile_one_layer(self, m, x, dt)

m fuse(self)

m info(self, verbose=False, img_size=640)

m _apply(self, fn)

c DetectionModel(BaseModel)

m __init__(self, cfg='yolov5s.yaml', ch=3, nc=None, anchors=None)

m forward(self, x, augment=False, profile=False, visualize=False)

m _forward_augment(self, x)

m _descale_pred(self, p, flips, scale, img_size)

m _clip_augmented(self, y)

m _initialize_biases(self, cf=None)

f inplace

f model

f names

f save

f stride

f yaml

f yaml_file

v Model

c SegmentationModel(DetectionModel)

m __init__(self, cfg='yolov5s-seg.yaml', ch=3, nc=None, anchors=None)

c ClassificationModel(BaseModel)

m __init__(self, cfg=None, model=None, nc=1000, cutoff=10)

m _from_detection_model(self, model, nc=1000, cutoff=10)

m _from_yaml(self, cfg)

f model

f nc

f save

f stride

f parse_model(d, ch)


common.py 

class SPPF(nn.Module):
    # Spatial Pyramid Pooling - Fast (SPPF) layer for YOLOv5 by Glenn Jocher实现空间金字塔池化
    def __init__(self, c1, c2, k=5):  # equivalent to SPP(k=(5, 9, 13))
        super().__init__()
        c_ = c1 // 2  # hidden channels
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c_ * 4, c2, 1, 1)
        self.m = nn.MaxPool2d(kernel_size=k, stride=1, padding=k // 2)

    def forward(self, x):
        x = self.cv1(x)
        with warnings.catch_warnings():
            warnings.simplefilter('ignore')  # suppress torch 1.9.0 max_pool2d() warning
            y1 = self.m(x)
            y2 = self.m(y1)
            return self.cv2(torch.cat((x, y1, y2, self.m(y2)), 1))

这个类具有两个主要部分:初始化函数__init__和前向传播函数forward

__init__函数中,首先计算了隐藏通道数c_,然后初始化了两个卷积层(cv1cv2),最后定义了一个最大池化层self.m

forward函数中,输入x首先通过cv1卷积层处理,然后经过两次池化操作(self.m(x)self.m(y1)),最后将结果拼接起来并通过cv2卷积层处理。

代码中用到了警告处理,用于忽略特定类型的警告,这里是PyTorch 1.9.0版本的中max_pool2d()函数的警告。

总的来说,这个SPPF类是为了在YOLOv5中实现空间金字塔池化(Spatial Pyramid Pooling)。这种池化方式可以在不同尺度上提取特征,从而使模型能够更好地理解和处理输入数据的多样性。


class Focus(nn.Module):
    # Focus wh information into c-space
    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True):  # ch_in, ch_out, kernel, stride, padding, groups
        super().__init__()
        self.conv = Conv(c1 * 4, c2, k, s, p, g, act=act)
        # self.contract = Contract(gain=2)

    def forward(self, x):  # x(b,c,w,h) -> y(b,4c,w/2,h/2)
        return self.conv(torch.cat((x[..., ::2, ::2], x[..., 1::2, ::2], x[..., ::2, 1::2], x[..., 1::2, 1::2]), 1))
        # return self.conv(self.contract(x))

init函数接受7个参数(c1,c2,k,s,p,g,act)(输入通道数、输出通道数、核数、步长、是否填充、组数、是否使用激活函数),并且这些参数可以用于配置Conv函数。

前向传播函数定义了输入数据x通过网络时的前向传播过程。它对输入的四分之三的空间信息用torch.cat进行连接,然后通过卷积层进行运算。


class GhostConv(nn.Module):
    # Ghost Convolution https://github.com/huawei-noah/ghostnet
    def __init__(self, c1, c2, k=1, s=1, g=1, act=True):  # ch_in, ch_out, kernel, stride, groups
        super().__init__()
        c_ = c2 // 2  # hidden channels
        self.cv1 = Conv(c1, c_, k, s, None, g, act=act)
        self.cv2 = Conv(c_, c_, 5, 1, None, c_, act=act)

    def forward(self, x):
        y = self.cv1(x)
        return torch.cat((y, self.cv2(y)), 1)

隐藏通道数为c2的一半,forward前向传播函数先进行一次卷积,再将卷积结果进行第二次卷积,并将两次的卷积结果通过torch.cat 拼接。提高网络性能和模型精度的轻量级卷积方法。


class GhostBottleneck(nn.Module):
    # Ghost Bottleneck https://github.com/huawei-noah/ghostnet
    def __init__(self, c1, c2, k=3, s=1):  # ch_in, ch_out, kernel, stride
        super().__init__()
        c_ = c2 // 2
        self.conv = nn.Sequential(
            GhostConv(c1, c_, 1, 1),  # pw
            DWConv(c_, c_, k, s, act=False) if s == 2 else nn.Identity(),  # dw
            GhostConv(c_, c2, 1, 1, act=False))  # pw-linear
        self.shortcut = nn.Sequential(DWConv(c1, c1, k, s, act=False), Conv(c1, c2, 1, 1,
                                                                            act=False)) if s == 2 else nn.Identity()

    def forward(self, x):
        return self.conv(x) + self.shortcut(x)

定义了一个名为'conv'的序列,它包括以下三个部分:

  1. 一个GhostConv层,作为第一个部分,它输入的通道数为'c1',输出的通道数为'c_',卷积核大小和步长都为1。
  2. 一个DWConv层或一个Identity,作为第二个部分。如果步长为2,就使用DWConv层,否则使用Identity。这个层的输入通道数为'c_',输出的通道数也为'c_',卷积核大小和步长分别为给定的'k'和's'。如果步长为2,这个部分之后还有一个GhostConv层,输入的通道数为'c_',输出的通道数为'c2',卷积核大小和步长都为1。
    所有这些部分通过nn.Sequential连接起来。

接下来,定义了一个名为'shortcut'的序列,如果步长为2,它包括一个DWConv层和一个Conv层,否则它只包括一个Identity。

最后,在'forward'方法中,模块的前向传播被定义。输入数据'x'首先通过'conv'序列进行计算,然后与通过'shortcut'序列计算的输出相加。


class Contract(nn.Module):
    # Contract width-height into channels, i.e. x(1,64,80,80) to x(1,256,40,40)
    def __init__(self, gain=2):
        super().__init__()
        self.gain = gain

    def forward(self, x):
        b, c, h, w = x.size()  # assert (h / s == 0) and (W / s == 0), 'Indivisible gain'
        s = self.gain
        x = x.view(b, c, h // s, s, w // s, s)  # x(1,64,40,2,40,2)
        x = x.permute(0, 3, 5, 1, 2, 4).contiguous()  # x(1,2,2,64,40,40)
        return x.view(b, c * s * s, h // s, w // s)  # x(1,256,40,40)

gain参数指定了宽高缩放的比例。这个比例将被用于将输入的张量'x'的宽度和高度进行缩小,并将通道数增加为原来的gain的平方倍。

前向传播函数forward :使用view将(b,c,h,w)变为(b,c,h//s,s,w//s,s),再使用permute将其顺序改变,最后使用view输出(b,c,c*s*s,h//s,w//s)


class Expand(nn.Module):
    # Expand channels into width-height, i.e. x(1,64,80,80) to x(1,16,160,160)
    def __init__(self, gain=2):
        super().__init__()
        self.gain = gain

    def forward(self, x):
        b, c, h, w = x.size()  # assert C / s ** 2 == 0, 'Indivisible gain'
        s = self.gain
        x = x.view(b, s, s, c // s ** 2, h, w)  # x(1,2,2,16,80,80)
        x = x.permute(0, 3, 4, 1, 5, 2).contiguous()  # x(1,16,80,2,80,2)
        return x.view(b, c // s ** 2, h * s, w * s)  # x(1,16,160,160)

gain参数指定了增益,即宽度和高度将增加原来的gain的平方倍,通道数将减少到原来的1/s的平方倍。

这个模块的主要作用就是将输入的张量进行宽度和高度增加,并减少通道数。

class Concat(nn.Module):
    # Concatenate a list of tensors along dimension
    def __init__(self, dimension=1):
        super().__init__()
        self.d = dimension

    def forward(self, x):
        return torch.cat(x, self.d)

init函数有一个参数'dimension',默认值为1。这个参数用于指定连接张量列表时的维度。

前向传播函数forward,接收一个参数'x',这是一个张量列表。然后使用PyTorch的'torch.cat'函数将这个列表中的所有张量沿着指定的维度(self.d)连接起来。

这个'Concat'类可以沿着指定的维度连接一个张量列表。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

苑苑圆圆

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

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

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

打赏作者

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

抵扣说明:

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

余额充值