欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

通過(guò)底層源碼理解YOLOv5的Backbone

 更新時(shí)間:2022年05月27日 11:49:55   作者:Marlowee  
yolov5的特征提取網(wǎng)絡(luò)兼顧速度與精度,將PAN與PFN深度融合,對(duì)不同尺度魯棒性強(qiáng),可以即插即用,后接不同的檢測(cè)器,下面這篇文章主要給大家介紹了關(guān)于如何通過(guò)底層源碼理解YOLOv5的Backbone的相關(guān)資料,需要的朋友可以參考下

YOLOv5的Backbone設(shè)計(jì)

在上一篇文章《YOLOV5的anchor設(shè)定》中我們討論了anchor的產(chǎn)生原理和檢測(cè)過(guò)程,對(duì)YOLOv5的網(wǎng)絡(luò)結(jié)構(gòu)有了大致的了解。接下來(lái),我們將聚焦于YOLOv5的Backbone,深入到底層源碼中體會(huì)v5的Backbone設(shè)計(jì)。

1 Backbone概覽及參數(shù)

# Parameters
nc: 80  # number of classes
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.50  # layer channel multiple

# YOLOv5 v6.0 backbone
backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2
   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
   [-1, 3, C3, [128]],
   [-1, 1, Conv, [256, 3, 2]],  # 3-P3/8
   [-1, 6, C3, [256]],
   [-1, 1, Conv, [512, 3, 2]],  # 5-P4/16
   [-1, 9, C3, [512]],
   [-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32
   [-1, 3, C3, [1024]],
   [-1, 1, SPPF, [1024, 5]],  # 9
  ]

yolov5s的backbone部分如上,其網(wǎng)絡(luò)結(jié)構(gòu)使用yaml文件配置,通過(guò)./models/yolo.py解析文件加了一個(gè)輸入構(gòu)成的網(wǎng)絡(luò)模塊。與v3和v4所使用的config設(shè)置的網(wǎng)絡(luò)不同,yaml文件中的網(wǎng)絡(luò)組件不需要進(jìn)行疊加,只需要在配置文件中設(shè)置number即可。

1.1 Param

# Parameters
nc: 80  # number of classes
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.50  # layer channel multiple

nc: 8

代表數(shù)據(jù)集中的類別數(shù)目,例如MNIST中含有0-9共10個(gè)類.

depth_multiple: 0.33

用來(lái)控制模型的深度,僅在number≠1時(shí)啟用。 如第一個(gè)C3層(c3具體是什么后續(xù)介紹)的參數(shù)設(shè)置為[-1, 3, C3, [128]],其中number=3,表示在v5s中含有1個(gè)C3(3*0.33);同理,v5l中的C3個(gè)數(shù)就是3(v5l的depth_multiple參數(shù)為1)。

width_multiple: 0.50

用來(lái)控制模型的寬度,主要作用于args中的ch_out。如第一個(gè)Conv層,ch_out=64,那么在v5s實(shí)際運(yùn)算過(guò)程中,會(huì)將卷積過(guò)程中的卷積核設(shè)為64x0.5,所以會(huì)輸出32通道的特征圖。

1.2 backbone

# YOLOv5 v6.0 backbone
backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2
   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
   [-1, 3, C3, [128]],
   [-1, 1, Conv, [256, 3, 2]],  # 3-P3/8
   [-1, 6, C3, [256]],
   [-1, 1, Conv, [512, 3, 2]],  # 5-P4/16
   [-1, 9, C3, [512]],
   [-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32
   [-1, 3, C3, [1024]],
   [-1, 1, SPPF, [1024, 5]],  # 9
  ]
  1. from:-n代表是從前n層獲得的輸入,如-1表示從前一層獲得輸入
  2. number:表示網(wǎng)絡(luò)模塊的數(shù)目,如[-1, 3, C3, [128]]表示含有3個(gè)C3模塊
  3. model:表示網(wǎng)絡(luò)模塊的名稱,具體細(xì)節(jié)可以在./models/common.py查看,如Conv、C3、SPPF都是已經(jīng)在common中定義好的模塊
  4. args:表示向不同模塊內(nèi)傳遞的參數(shù),即[ch_out, kernel, stride, padding, groups],這里連ch_in都省去了,因?yàn)檩斎攵际巧蠈拥妮敵觯ǔ跏糲h_in為3)。為了修改過(guò)于麻煩,這里輸入的獲取是從./models/yolo.py的def parse_model(md, ch)函數(shù)中解析得到的。

1.3 Exp

[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2

input:3x640x640

[ch_out, kernel, stride, padding]=[64, 6, 2, 2]

故新的通道數(shù)為64x0.5=32

根據(jù)特征圖計(jì)算公式:Feature_new=(Feature_old-kernel+2xpadding)/stride+1可得:

新的特征圖尺寸為:Feature_new=(640-6+2x2)/2+1=320

[-1, 1, Conv, [128, 3, 2]],  # 1-P2/4

input:32x320x320

[ch_out, kernel, stride]=[128, 3, 2]

同理可得:新的通道數(shù)為64,新的特征圖尺寸為160

2 Backbone組成

v6.0版本的Backbone去除了Focus模塊(便于模型導(dǎo)出部署),Backbone主要由CBL、BottleneckCSP/C3以及SPP/SPPF等組成,具體如下圖所示:

3.1 CBS

CBS模塊其實(shí)沒(méi)什么好稀奇的,就是Conv+BatchNorm+SiLU,這里著重講一下Conv的參數(shù),就當(dāng)復(fù)習(xí)pytorch的卷積操作了,先上CBL源碼:

class Conv(nn.Module):
    # Standard convolution
    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 = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False)
        self.bn = nn.BatchNorm2d(c2)
        #其中nn.Identity()是網(wǎng)絡(luò)中的占位符,并沒(méi)有實(shí)際操作,在增減網(wǎng)絡(luò)過(guò)程中,可以使得整個(gè)網(wǎng)絡(luò)層數(shù)據(jù)不變,便于遷移權(quán)重?cái)?shù)據(jù);nn.SiLU()一種激活函數(shù)(S形加權(quán)線性單元)。
        self.act = nn.SiLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity())

    def forward(self, x):#正態(tài)分布型的前向傳播
        return self.act(self.bn(self.conv(x)))

    def forward_fuse(self, x):#普通前向傳播
        return self.act(self.conv(x))

由源碼可知:Conv()包含7個(gè)參數(shù),這些參數(shù)也是二維卷積Conv2d()中的重要參數(shù)。ch_in, ch_out, kernel, stride沒(méi)什么好說(shuō)的,展開(kāi)說(shuō)一下后三個(gè)參數(shù):

padding

從我現(xiàn)在看到的主流卷積操作來(lái)看,大多數(shù)的研究者不會(huì)通過(guò)kernel來(lái)改變特征圖的尺寸,如googlenet中3x3的kernel設(shè)定了padding=1,所以當(dāng)kernel≠1時(shí)需要對(duì)輸入特征圖進(jìn)行填充。當(dāng)指定p值時(shí)按照p值進(jìn)行填充,當(dāng)p值為默認(rèn)時(shí)則通過(guò)autopad函數(shù)進(jìn)行填充:

def autopad(k, p=None):  # kernel, padding
    # Pad to 'same'
    if p is None:
        p = k // 2 if isinstance(k, int) else [x // 2 for x in k]  # auto-pad
        #如果k是整數(shù),p為k與2整除后向下取整;如果k是列表等,p對(duì)應(yīng)的是列表中每個(gè)元素整除2。
    return p

這里作者考慮到對(duì)不同的卷積操作使用不同大小的卷積核時(shí)padding也需要做出改變,所以這里在為p賦值時(shí)會(huì)首先檢查k是否為int,如果k為列表則對(duì)列表中的每個(gè)元素整除。

groups

代表分組卷積,如下圖所示

groups – Number of blocked connections from input channels to output

  • At groups=1, all inputs are convolved to all outputs.
  • At groups=2, the operation becomes equivalent to having two conv layers side by side, each seeing half the input channels, and producing half the output channels, and both subsequently concatenated.
  • At groups= in_channels, each input channel is convolved with its own set of filters, of size: ⌊(out_channels)/(in_channels)⌋.

act

決定是否對(duì)特征圖進(jìn)行激活操作,SiLU表示使用Sigmoid進(jìn)行激活。

one more thing:dilation

Conv2d中還有一個(gè)重要的參數(shù)就是空洞卷積dilation,通俗解釋就是控制kernel點(diǎn)(卷積核點(diǎn))間距的參數(shù),通過(guò)改變卷積核間距實(shí)現(xiàn)特征圖及特征信息的保留,在語(yǔ)義分割任務(wù)中空洞卷積比較有效。

3.2 CSP/C3

CSP即backbone中的C3,因?yàn)樵赽ackbone中C3存在shortcut,而在neck中C3不使用shortcut,所以backbone中的C3層使用CSP1_x表示,neck中的C3使用CSP2_x表示。

3.2.1 CSP結(jié)構(gòu)

接下來(lái)讓我們來(lái)好好梳理一下backbone中的C3層的模塊組成。先上源碼:

class C3(nn.Module):
    # CSP Bottleneck with 3 convolutions
    def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):  # ch_in, ch_out, number, shortcut, groups, expansion
        super().__init__()
        c_ = int(c2 * e)  # hidden channels
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c1, c_, 1, 1)
        self.cv3 = Conv(2 * c_, c2, 1)  # act=FReLU(c2)
        self.m = nn.Sequential(*[Bottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)])
        # self.m = nn.Sequential(*[CrossConv(c_, c_, 3, 1, g, 1.0, shortcut) for _ in range(n)])

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

從源碼中可以看出:輸入特征圖一條分支先經(jīng)過(guò).cv1,再經(jīng)過(guò).m,得到子特征圖1;另一分支經(jīng)過(guò).cv2后得到子特征圖2。最后將子特征圖1和子特征圖2拼接后輸入.cv3得到C3層的輸出,如下圖所示。 這里的CV操作容易理解,就是前面的Conv2d+BN+SiLU,關(guān)鍵是.m操作。

.m操作使用nn.Sequential將多個(gè)Bottleneck(圖示中我以Resx命名)串接到網(wǎng)絡(luò)中,for loop中的n即網(wǎng)絡(luò)配置文件args中的number,也就是將number×depth_multiple個(gè)Bottleneck串接到網(wǎng)絡(luò)中。那么,Bottleneck又是個(gè)什么玩意呢?

3.2.2 Bottleneck

要想了解Bottleneck,還要從Resnet說(shuō)起。在Resnet出現(xiàn)之前,人們的普遍為網(wǎng)絡(luò)越深獲取信息也越多,模型泛化效果越好。然而隨后大量的研究表明,網(wǎng)絡(luò)深度到達(dá)一定的程度后,模型的準(zhǔn)確率反而大大降低。這并不是過(guò)擬合造成的,而是由于反向傳播過(guò)程中的梯度爆炸和梯度消失。也就是說(shuō),網(wǎng)絡(luò)越深,模型越難優(yōu)化,而不是學(xué)習(xí)不到更多的特征。

為了能讓深層次的網(wǎng)絡(luò)模型達(dá)到更好的訓(xùn)練效果,殘差網(wǎng)絡(luò)中提出的殘差映射替換了以往的基礎(chǔ)映射。對(duì)于輸入x,期望輸出H(x),網(wǎng)絡(luò)利用恒等映射將x作為初始結(jié)果,將原來(lái)的映射關(guān)系變成F(x)+x。與其讓多層卷積去近似估計(jì)H(x) ,不如近似估計(jì)H(x)-x,即近似估計(jì)殘差F(x)。因此,ResNet相當(dāng)于將學(xué)習(xí)目標(biāo)改變?yōu)槟繕?biāo)值H(x)和x的差值,后面的訓(xùn)練目標(biāo)就是要將殘差結(jié)果逼近于0。

殘差模塊有什么好處呢?

1.梯度彌散方面。加入ResNet中的shortcut結(jié)構(gòu)之后,在反傳時(shí),每?jī)蓚€(gè)block之間不僅傳遞了梯度,還加上了求導(dǎo)之前的梯度,這相當(dāng)于把每一個(gè)block中向前傳遞的梯度人為加大了,也就會(huì)減小梯度彌散的可能性。
2.特征冗余方面。正向卷積時(shí),對(duì)每一層做卷積其實(shí)只提取了圖像的一部分信息,這樣一來(lái),越到深層,原始圖像信息的丟失越嚴(yán)重,而僅僅是對(duì)原始圖像中的一小部分特征做提取。這顯然會(huì)發(fā)生類似欠擬合的現(xiàn)象。加入shortcut結(jié)構(gòu),相當(dāng)于在每個(gè)block中又加入了上一層圖像的全部信息,一定程度上保留了更多的原始信息。

在resnet中,人們可以使用帶有shortcut的殘差模塊搭建幾百層甚至上千層的網(wǎng)絡(luò),而淺層的殘差模塊被命名為Basicblock(18、34),深層網(wǎng)絡(luò)所使用的的殘差模塊,就被命名為了Bottleneck(50+)。


Bottleneck與Basicblock最大的區(qū)別是卷積核的組成。 Basicblock由兩個(gè)3x3的卷積層組成,Bottleneck由兩個(gè)1x1卷積層夾一個(gè)3x3卷積層組成:其中1x1卷積層降維后再恢復(fù)維數(shù),讓3x3卷積在計(jì)算過(guò)程中的參數(shù)量更少、速度更快。

第一個(gè)1x1的卷積把256維channel降到64維,然后在最后通過(guò)1x1卷積恢復(fù),整體上用的參數(shù)數(shù)目:1x1x256x64 + 3x3x64x64 + 1x1x64x256 = 69632,而不使用bottleneck的話就是兩個(gè)3x3x256的卷積,參數(shù)數(shù)目: 3x3x256x256x2 = 1179648,差了16.94倍。

Bottleneck減少了參數(shù)量,優(yōu)化了計(jì)算,保持了原有的精度。

說(shuō)了這么多,都是為了給CSP中的Bottleneck做前情提要,我們?cè)倩仡^看CSP中的Bottleneck其實(shí)就更清楚了:

class Bottleneck(nn.Module):
    # Standard bottleneck
    def __init__(self, c1, c2, shortcut=True, g=1, e=0.5):  # ch_in, ch_out, shortcut, groups, expansion
        super().__init__()
        c_ = int(c2 * e)  # hidden channels
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c_, c2, 3, 1, g=g)
        self.add = shortcut and c1 == c2

    def forward(self, x):
        return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))

可以看到,CSP中的Bottleneck同resnet模塊中的類似,先是1x1的卷積層(CBS),然后再是3x3的卷積層,最后通過(guò)shortcut與初始輸入相加。但是這里與resnet的不通點(diǎn)在于:CSP將輸入維度減半運(yùn)算后并未再使用1x1卷積核進(jìn)行升維,而是將原始輸入x也降了維,采取concat的方法進(jìn)行張量的拼接,得到與原始輸入相同維度的輸出。其實(shí)這里能區(qū)分一點(diǎn)就夠了:resnet中的shortcut通過(guò)add實(shí)現(xiàn),是特征圖對(duì)應(yīng)位置相加而通道數(shù)不變;而CSP中的shortcut通過(guò)concat實(shí)現(xiàn),是通道數(shù)的增加。二者雖然都是信息融合的主要方式,但是對(duì)張量的具體操作又不相同.

其次,對(duì)于shortcut是可根據(jù)任務(wù)要求設(shè)置的,比如在backbone中shortcut=True,neck中shortcut=False。
當(dāng)shortcut=True時(shí),Resx如圖:

當(dāng)shortcut=False時(shí),Resx如圖:

這其實(shí)也是YOLOv5為人稱贊的地方,代碼更體系、代碼冗余更少,僅需要指定一個(gè)參數(shù)便可以將Bottleneck和普通卷積聯(lián)合在一起使用,減少了代碼量的同時(shí)也使整體感觀得到提升。

3.3 SSPF

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))

SSPF模塊將經(jīng)過(guò)CBS的x、一次池化后的y1、兩次池化后的y2和3次池化后的self.m(y2)先進(jìn)行拼接,然后再CBS提取特征。 仔細(xì)觀察不難發(fā)現(xiàn),雖然SSPF對(duì)特征圖進(jìn)行了多次池化,但是特征圖尺寸并未發(fā)生變化,通道數(shù)更不會(huì)變化,所以后續(xù)的4個(gè)輸出能夠在channel維度進(jìn)行融合。這一模塊的主要作用是對(duì)高層特征進(jìn)行提取并融合,在融合的過(guò)程中作者多次運(yùn)用最大池化,盡可能多的去提取高層次的語(yǔ)義特征。

YOLOv5s的Backbone總覽

最后,結(jié)合上述的講解應(yīng)該就不難理解v5s的backbone了

總結(jié)

到此這篇關(guān)于通過(guò)底層源碼理解YOLOv5中Backbone的文章就介紹到這了,更多相關(guān)YOLOv5 Backbone詳解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Django中幾種重定向方法

    Django中幾種重定向方法

    這篇文章主要介紹了Django中幾種重定向方法,本文講解了使用HttpResponseRedirect、redirect、reverse以及配置文件中配置URL等方法,需要的朋友可以參考下
    2015-04-04
  • Python程序員面試題 你必須提前準(zhǔn)備!

    Python程序員面試題 你必須提前準(zhǔn)備!

    Python程序員面試,這些問(wèn)題你必須提前準(zhǔn)備!供廣大Python程序員參考,預(yù)祝大家順利通過(guò)面試。
    2018-01-01
  • Python常用數(shù)據(jù)類型之列表使用詳解

    Python常用數(shù)據(jù)類型之列表使用詳解

    列表是Python中的基礎(chǔ)數(shù)據(jù)類型之一,其他語(yǔ)言中也有類似于列表的數(shù)據(jù)類型,比如js中叫數(shù)組,他是以[ ]括起來(lái),每個(gè)元素以逗號(hào)隔開(kāi),而且他里面可以存放各種數(shù)據(jù)類型。本文將通過(guò)示例詳細(xì)講解列表的使用,需要的可以參考一下
    2022-04-04
  • python 布爾操作實(shí)現(xiàn)代碼

    python 布爾操作實(shí)現(xiàn)代碼

    python布爾操作也是我們經(jīng)常寫(xiě)代碼需要用到的,首先我們需要明白在python里面,哪些被解釋器當(dāng)做真,哪些當(dāng)做假
    2013-03-03
  • python實(shí)現(xiàn)QQ郵箱/163郵箱的郵件發(fā)送

    python實(shí)現(xiàn)QQ郵箱/163郵箱的郵件發(fā)送

    這篇文章主要為大家詳細(xì)介紹了Python實(shí)現(xiàn)QQ郵箱和163郵箱的郵件發(fā)送,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • 學(xué)會(huì)這29個(gè)常用函數(shù),你就是Pandas專家

    學(xué)會(huì)這29個(gè)常用函數(shù),你就是Pandas專家

    Pandas?無(wú)疑是?Python?處理表格數(shù)據(jù)最好的庫(kù)之一,但是很多新手無(wú)從下手,這里總結(jié)出最常用的?29?個(gè)函數(shù),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2022-11-11
  • Python爬蟲(chóng)之Spider類用法簡(jiǎn)單介紹

    Python爬蟲(chóng)之Spider類用法簡(jiǎn)單介紹

    這篇文章主要介紹了Python爬蟲(chóng)之Spider類用法簡(jiǎn)單介紹,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • Python?虛擬環(huán)境的價(jià)值和常用命令詳解

    Python?虛擬環(huán)境的價(jià)值和常用命令詳解

    在實(shí)際項(xiàng)目開(kāi)發(fā)中,我們通常會(huì)根據(jù)自己的需求去下載各種相應(yīng)的框架庫(kù),如Scrapy、Beautiful?Soup等,但是可能每個(gè)項(xiàng)目使用的框架庫(kù)并不一樣,或使用框架的版本不一樣,今天給大家分享下Python?虛擬環(huán)境的價(jià)值和常用命令,感興趣的朋友一起看看吧
    2022-05-05
  • pytorch中[..., 0]的用法說(shuō)明

    pytorch中[..., 0]的用法說(shuō)明

    這篇文章主要介紹了pytorch中[..., 0]的用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-05-05
  • python繪制箱型圖

    python繪制箱型圖

    這篇文章主要為大家詳細(xì)介紹了python繪制箱型圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-04-04

最新評(píng)論