<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【深度學(xué)習(xí)】基于PyTorch的卷積神經(jīng)網(wǎng)絡(luò)經(jīng)典BackBone(骨干網(wǎng)絡(luò))復(fù)現(xiàn)

          共 1961字,需瀏覽 4分鐘

           ·

          2022-05-27 21:26

          ??作者丨helton_yan@CSDN(已授權(quán))
          來(lái)源丨h(huán)ttps://blog.csdn.net/SESESssss/article/details/114340066
          編輯丨極市平臺(tái)

          導(dǎo)讀

          ?

          本文基于代碼實(shí)戰(zhàn)復(fù)現(xiàn)了經(jīng)典的Backbone結(jié)構(gòu)Inception v1、ResNet-50和FPN,基于PyTorch分享一些網(wǎng)絡(luò)搭建技巧,很詳細(xì)很干貨!

          文章目錄

          • 1.VGG

          • 1.1改進(jìn):

          • 1.2 PyTorch復(fù)現(xiàn)VGG19

          • 1.2.1 小Tips:

          • 1.2.2 打印網(wǎng)絡(luò)信息:

          • Inception(GoogLeNet)

          • 2.1改進(jìn)(Inception v1)

          • 2.2.2改進(jìn)(Inception v2)

          • 2.2 PyTorch復(fù)現(xiàn)Inception v1:

          • 2.2.1 網(wǎng)絡(luò)的整體框架:

          • 2.2.2 各層的參數(shù)情況:

          • 2.2.3 pytorch復(fù)現(xiàn)Inception基礎(chǔ)模塊

          • 2.2.4 小Tips

          • ResNet

          • 3.1改進(jìn)

          • 3.2PyTorch 復(fù)現(xiàn) ResNet-50

          • 3.2.1ResNet-50網(wǎng)絡(luò)整體架構(gòu)

          • 3.2.2 Bottleneck結(jié)構(gòu)

          • 3.2.3 ResNet-50圖解及各層參數(shù)細(xì)節(jié)

          • 3.2.4 實(shí)現(xiàn)一個(gè)Bottleneck模塊:

          • 3.2.5 實(shí)現(xiàn)resnet-50

          • FPN(特征金字塔)

          • 4.1 特征的語(yǔ)義信息

          • 4.2 改進(jìn)

          • 4.3 PyTorch 復(fù)現(xiàn) FPN

          • 4.3.1 FPN網(wǎng)絡(luò)架構(gòu)

          • 4.3.2 復(fù)現(xiàn)FPN

          前言

          卷積神經(jīng)網(wǎng)絡(luò)的發(fā)展,從上個(gè)世紀(jì)就已經(jīng)開(kāi)始了,讓時(shí)間回到1998年,在當(dāng)時(shí),Yann LeCun 教授提出了一種較為成熟的卷積神經(jīng)網(wǎng)絡(luò)架構(gòu)LeNet-5,現(xiàn)在被譽(yù)為卷積神經(jīng)網(wǎng)絡(luò)的“HelloWorld”,但由于當(dāng)時(shí)計(jì)算機(jī)算力的局限性以及支持向量機(jī)(核學(xué)習(xí)方法)的興起,CNN方法并不是當(dāng)時(shí)學(xué)術(shù)界認(rèn)可的主流方法。時(shí)間推移到14年后,隨著AlexNet以高出第二名約10%的accuracy rate成為了2012年ImageNet圖像識(shí)別競(jìng)賽的第一名,深度學(xué)習(xí)以及卷積神經(jīng)網(wǎng)絡(luò)的研究熱潮被徹底引爆,從此CNN進(jìn)入了飛速發(fā)展的階段,從無(wú)人問(wèn)津到一度成為計(jì)算機(jī)視覺(jué)的主流框架,在此之后,各種基于CNN的圖像識(shí)別網(wǎng)絡(luò)開(kāi)始大放異彩。各種CNN網(wǎng)絡(luò)層出不窮。

          本次博客將介紹如今圖像識(shí)別領(lǐng)域十分經(jīng)典的一些CNN網(wǎng)絡(luò),雖然現(xiàn)在卷積網(wǎng)絡(luò)框架也隨著研究的深入變得越來(lái)越復(fù)雜,但我們?nèi)匀豢梢栽谝恍┳钚碌木W(wǎng)絡(luò)結(jié)構(gòu)中發(fā)現(xiàn)它們的身影,這些經(jīng)典CNN網(wǎng)絡(luò)有時(shí)候是整個(gè)算法提取特征的骨架(特征的質(zhì)量往往直接影響到分類結(jié)果的準(zhǔn)確度,表達(dá)能力更強(qiáng)的特征也能給模型帶來(lái)更強(qiáng)的分類能力),因此又稱為“Backbone”(骨干網(wǎng)絡(luò))。

          本次博客基于代碼實(shí)戰(zhàn)復(fù)現(xiàn)經(jīng)典的Backbone結(jié)構(gòu),并基于PyTorch分享一些網(wǎng)絡(luò)搭建技巧。

          1.VGG

          網(wǎng)絡(luò)架構(gòu):

          VGG16網(wǎng)絡(luò)由13層卷積層+3層全連接層構(gòu)成。

          1.1改進(jìn):

          1. 更小的卷積核,對(duì)比AlexNet,VGG網(wǎng)絡(luò)使用的卷積核大小不超過(guò)3x3,這種結(jié)構(gòu)相比于大卷積核有一個(gè)優(yōu)點(diǎn),就是兩個(gè)3x3的卷積核堆疊對(duì)于原圖提取特征的感受野(特征圖一個(gè)像素融合了輸入多少像素的信息決定了感受野的大小)相當(dāng)于一個(gè)5x5卷積核(如圖),并且在同等感受野的條件下,兩個(gè)3x3卷積之間加入激活函數(shù),其非線性能力比單個(gè)5x5卷積要強(qiáng)。

          2. 更深的網(wǎng)絡(luò)結(jié)構(gòu),相比于AlexNet只有5層卷積層,VGG系列加深了網(wǎng)絡(luò)的深度,更深的結(jié)構(gòu)有助于網(wǎng)絡(luò)提取圖像中更復(fù)雜的語(yǔ)義信息。

          1.2 PyTorch復(fù)現(xiàn)VGG19

          class?VGG19(nn.Module):
          ?def?__init__(self,?num_classes?=?1000):?#?num_classes?預(yù)分類數(shù)

          ??super(VGG19,?self).__init__()

          ??#構(gòu)造特征提取層:
          ??feature_layers?=?[]?#?將卷積層存儲(chǔ)在list中
          ??in_dim?=?3?#?輸入是三通道圖像
          ??out_dim?=?64?#?輸出特征的深度為64

          ??#采用循環(huán)構(gòu)造的方式,對(duì)于深度網(wǎng)絡(luò)能避免代碼形式冗余:
          ??for?i?in?range(16):#?vgg19共16層卷積
          ???feature_layers?+=?[nn.Conv2d(in_dim,?out_dim,3,1,1),?nn.ReLU(inplace?=?True)]?#?基本結(jié)構(gòu):卷積+激活函數(shù)
          ???in_dim?=?out_dim
          ???#?在第2,4,8,12,16,層卷積后增加最大池化:
          ???if?i?==?1?or?i?==?3?or?i?==?7?or?i?==?11?or?i?==?15?:
          ????feature_layers?+=?[nn.MaxPool2d(2)]
          ????if?i?11:
          ?????out_dim?*=?2
          ????self.features?=?nn.Sequential(*feature_layers)?
          ????????????????#?*表示傳入?yún)?shù)的數(shù)量不固定,否則報(bào)錯(cuò)list?is?not?a?Module?subclass


          ??#全連接層分類:
          ??self.classifier?=?nn.Sequential(
          ???nn.Linear(512?*?7?*?7,?4096),
          ???nn.ReLU(inplace?=?True),
          ???nn.Dropout(),
          ???nn.Linear(4096,4096),
          ???nn.ReLU(inplace?=?True),
          ???nn.Dropout(),
          ???nn.Linear(4096,num_classes),
          ???)

          ?#前向傳播
          ?def?forward(self,?x):
          ??x?=?self.features(x)
          ??x?=?x.view(x.size(0),?-1)
          ??x?=?self.classifier(x)
          ??return?x

          1.2.1 小Tips:

          1. 當(dāng)網(wǎng)絡(luò)的結(jié)構(gòu)重復(fù)時(shí),使用for循環(huán)構(gòu)造避免代碼形式冗余

          2. 將不同功能的網(wǎng)絡(luò)各自封裝到一個(gè)大的Sequential模塊中,結(jié)構(gòu)分明

          3. 卷積操作輸出尺寸計(jì)算公式:Out=(In-Kernel+2Padding)/Stride+1 (Kernel:卷積核尺寸,Stride:步長(zhǎng),Padding:邊界填充) 若要保證輸出尺寸和原尺寸一致,Padding可以設(shè)置為:Padding = (kernel-1)/2)

          4. 池化操作輸出尺寸計(jì)算公式同卷積操作一致

          5. 在實(shí)際深度學(xué)習(xí)框架實(shí)現(xiàn)卷積和全連接的計(jì)算中,本質(zhì)都是矩陣運(yùn)算:

            若輸入的特征圖深度是N,輸出特征圖深度是M,則卷積核的維度是:NxMxKxK(K為卷積核大小)。因此全卷積網(wǎng)絡(luò)對(duì)輸入圖像的尺寸沒(méi)有要求。

            全連接層的尺寸和輸入的特征尺寸相關(guān)(將特征圖展平成為一維向量),若輸入的特征向量是1xN,輸出是1xM,則全連接層的維度是:MxN

          1.2.2 打印網(wǎng)絡(luò)信息:

          使用torch.summary輸出網(wǎng)絡(luò)架構(gòu):

          vgg19?=?VGG19()

          #print(vgg19)?#輸出網(wǎng)絡(luò)的架構(gòu)
          summary(vgg19,?input_size?=?[(3,?224,?224)])?#輸出網(wǎng)絡(luò)架構(gòu),每一層的輸出特征尺寸,及網(wǎng)絡(luò)參數(shù)情況

          輸出網(wǎng)絡(luò)每一層的尺寸:

          for?param?in?vgg19.parameters():?#?輸出每一層網(wǎng)絡(luò)的尺寸
          ?print(param.size())


          batch_size?=?16
          input?=?torch.randn(batch_size,?3,?224,?224)?#構(gòu)建一個(gè)隨機(jī)數(shù)據(jù),模擬一個(gè)batch_size
          output?=?vgg19(input)
          print(output.shape)??#?torch.Size([16,?1000])

          2.Inception(GoogLeNet)

          2.1改進(jìn)(Inception v1)

          以往網(wǎng)絡(luò)的不足:

          1. 加深深度導(dǎo)致的網(wǎng)絡(luò)參數(shù)增加
          2. 深層網(wǎng)絡(luò)需要更多的訓(xùn)練數(shù)據(jù),容易產(chǎn)生過(guò)擬合
          3. 深層網(wǎng)絡(luò)在訓(xùn)練過(guò)程中容易導(dǎo)致梯度消失

          改進(jìn):

          1. 引入了Inception模塊作為網(wǎng)絡(luò)的基礎(chǔ)模塊,整體的網(wǎng)絡(luò)基于基礎(chǔ)模塊的堆疊;在模塊中使用了通道拼接(Concat)的方法對(duì)不同卷積核提取的特征進(jìn)行拼接

            Inception基礎(chǔ)的模塊如圖所示,使用3個(gè)不同尺寸的卷積核進(jìn)行卷積運(yùn)算,同時(shí)還包括一個(gè)最大池化,最后將這四個(gè)部分輸出的結(jié)果進(jìn)行通道拼接,傳給下一層:

          1. 使用1x1卷積進(jìn)行數(shù)據(jù)降維(減少深度),減少訓(xùn)練的參數(shù)量。

            上圖這個(gè)結(jié)構(gòu)有一個(gè)弊端,即模塊中一個(gè)分支的輸入通道數(shù)就是前一個(gè)模塊所有分支輸出通道數(shù)之和(通道合并),在多個(gè)模塊堆疊后計(jì)算的參數(shù)量將會(huì)變得十分巨大,為了解決這個(gè)問(wèn)題,作者在每一個(gè)分支的卷積層之前單獨(dú)加了一個(gè)1x1卷積,來(lái)進(jìn)行通道數(shù)的降維

          我們或許會(huì)有一個(gè)疑問(wèn),為什么不在3x3或5x5卷積輸出上直接降維特征,而非得使用1x1卷積呢,(作者認(rèn)為這樣做能夠增加網(wǎng)絡(luò)的非線性能力,因?yàn)榫矸e和卷積之間有激活函數(shù))

          1. 引入輔助分類器(在不同深度計(jì)算分類最后一并回傳計(jì)算損失)

            作者發(fā)現(xiàn)網(wǎng)絡(luò)中間層的特征和較深層的特征有很大的不同,因此在訓(xùn)練時(shí)額外在中間層增加了兩個(gè)輔助分類器。輔助分類器的結(jié)果同輸出結(jié)果一并計(jì)算損失,并且輔助分類器的損失為網(wǎng)絡(luò)總損失的0.3。作者認(rèn)為這樣的結(jié)構(gòu)有利于增強(qiáng)網(wǎng)絡(luò)在較淺層特征的分類能力,**相當(dāng)于給網(wǎng)絡(luò)加了一個(gè)額外的約束(正則化)**,并且在推理時(shí)這些輔助網(wǎng)絡(luò)的結(jié)構(gòu)將被舍棄。

          2.2.2改進(jìn)(Inception v2)

          卷積分解

          Inception v2較Inception v1將5x5的大卷積分解成兩個(gè)3x3的小卷積(效仿VGG網(wǎng)絡(luò)的處理方式,減少了參數(shù)量同時(shí)增加網(wǎng)絡(luò)的非線性能力),并加入了BN層:

          進(jìn)一步的,Inception v2將nxn卷積分解為兩個(gè)1xn和nx1卷積(空間可分離卷積Spatially Separable Convolution),在感受野相當(dāng)?shù)那闆r下,進(jìn)一步減少了網(wǎng)絡(luò)的參數(shù):


          參考:

          Inception系列之Inception_v2-v3:https://www.cnblogs.com/wxkang/p/13955363.html

          [論文筆記](méi) Xception:https://zhuanlan.zhihu.com/p/127042277

          2.2 PyTorch復(fù)現(xiàn)Inception v1:

          2.2.1 網(wǎng)絡(luò)的整體框架:

          2.2.2 各層的參數(shù)情況:

          紅色框表示用于特征降維的1x1卷積

          2.2.3 pytorch復(fù)現(xiàn)Inception基礎(chǔ)模塊

          將卷積+激活函數(shù)作為一個(gè)基礎(chǔ)的卷積組:

          #?將Conv+ReLU封裝成一個(gè)基礎(chǔ)類:
          class?BasicConv2d(nn.Module):
          ????def?__init__(self,?in_channel,?out_channel,?kernel_size,?stride=1,?padding=0):
          ????????super(BasicConv2d,?self).__init__()
          ????????self.conv?=?nn.Sequential(
          ????????????nn.Conv2d(in_channel,?out_channel,?kernel_size,
          ??????????????????????stride=stride,?padding=padding),
          ????????????nn.ReLU(True)
          ????????)

          ????def?forward(self,?x):
          ????????x?=?self.conv(x)
          ????????return?x

          構(gòu)造一個(gè)Inception模塊:

          #?構(gòu)造Inception基礎(chǔ)模塊:
          class?Inception(nn.Module):
          ????def?__init__(self,?in_dim,?out_1x1,?out_3x3_reduce,?out_3x3,?out_5x5_reduce,?out_5x5,?out_pool):
          ????????super(Inception,?self).__init__()
          ????????#?分支1:
          ????????self.branch_1x1?=?BasicConv2d(in_dim,?out_1x1,?1)
          ????????#?分支2:
          ????????self.branch_3x3?=?nn.Sequential(
          ????????????BasicConv2d(in_dim,?out_3x3_reduce,?1),
          ????????????BasicConv2d(out_3x3_reduce,?out_3x3,?3,?padding=1),
          ????????)
          ????????#?分支3:
          ????????self.branch_5x5?=?nn.Sequential(
          ????????????BasicConv2d(in_dim,?out_5x5_reduce,?1),
          ????????????BasicConv2d(out_5x5_reduce,?out_5x5,?5,?padding=2),
          ????????)
          ????????#?分支4:
          ????????self.branch_pool?=?nn.Sequential(
          ????????????nn.MaxPool2d(3,?stride=1,?padding=1),
          ????????????BasicConv2d(in_dim,?out_pool,?1),
          ????????)

          ????def?forward(self,?x):
          ????????b1?=?self.branch_1x1(x)
          ????????b2?=?self.branch_3x3(x)
          ????????b3?=?self.branch_5x5(x)
          ????????b4?=?self.branch_pool(x)

          ????????output?=?torch.cat((b1,?b2,?b3,?b4),?dim=1)??#?四個(gè)模塊沿特征圖通道方向拼接
          ????????return?output

          搭建完整的Inceptionv1:

          #?構(gòu)建Inceptionv1:
          class?Inception_v1(nn.Module):
          ????def?__init__(self,?num_classes=1000,?state="test"):
          ????????super(Inception_v1,?self).__init__()
          ????????self.state?=?state
          ????????self.block1?=?nn.Sequential(
          ????????????BasicConv2d(3,?64,?7,?stride=2,?padding=3),
          ????????????nn.MaxPool2d(kernel_size=3,?stride=2,?padding=1),
          ????????????nn.LocalResponseNorm(64),
          ????????????BasicConv2d(64,?64,?1),
          ????????????BasicConv2d(64,?192,?3,?padding=1),
          ????????????nn.LocalResponseNorm(192),
          ????????????nn.MaxPool2d(kernel_size=3,?stride=2,?padding=1),
          ????????)
          ????????self.block2?=?nn.Sequential(
          ????????????Inception(192,?64,?96,?128,?16,?32,?32),
          ????????????Inception(256,?128,?128,?192,?32,?96,?64),
          ????????????nn.MaxPool2d(kernel_size=3,?stride=2,?padding=1),
          ????????????Inception(480,?192,?96,?208,?16,?48,?64),
          ????????)
          ????????self.block3?=?nn.Sequential(
          ????????????Inception(512,?160,?112,?224,?24,?64,?64),
          ????????????Inception(512,?128,?128,?256,?24,?64,?64),
          ????????????Inception(512,?112,?144,?288,?32,?64,?64),
          ????????)
          ????????self.block4?=?nn.Sequential(
          ????????????nn.MaxPool2d(kernel_size=3,?stride=2,?padding=1),
          ????????????Inception(528,?256,?160,?320,?32,?128,?128),
          ????????????Inception(832,?256,?160,?320,?32,?128,?128),
          ????????????Inception(832,?384,?192,?384,?48,?128,?128),
          ????????????nn.AvgPool2d(3,?stride=1),
          ????????)
          ????????self.classifier?=?nn.Linear(4096,?num_classes)

          ????????if?state?==?"train":
          ????????????#?兩個(gè)輔助分類器:
          ????????????self.aux_classifier1?=?Inception_classify(
          ????????????????192?+?208?+?48?+?64,?num_classes)
          ????????????self.aux_classifier2?=?Inception_classify(
          ????????????????112?+?288?+?64?+?64,?num_classes)

          ????def?forward(self,?x):
          ????????x?=?self.block1(x)
          ????????x?=?self.block2(x)
          ????????#?插入輔助分類層1
          ????????if?self.state?==?'train':
          ????????????aux1?=?self.aux_classifier1(x)
          ????????x?=?self.block3(x)
          ????????#?插入輔助分類層2
          ????????if?self.state?==?'train':
          ????????????aux2?=?self.aux_classifier2(x)
          ????????x?=?self.block4(x)
          ????????x?=?x.view(x.size(0),?-1)
          ????????out?=?self.classifier(x)

          ????????if?self.state?==?'train':
          ????????????return?aux1,?aux2,?out
          ????????else:
          ????????????return?out

          2.2.4 小Tips

          在構(gòu)建比較復(fù)雜的網(wǎng)絡(luò)時(shí),將網(wǎng)絡(luò)重疊使用的一些基礎(chǔ)模塊封裝為一個(gè)基礎(chǔ)的類(層次分明)。

          3.ResNet

          在以往的經(jīng)驗(yàn)上,人們普遍認(rèn)為通過(guò)加深網(wǎng)絡(luò)的層數(shù)能夠使得網(wǎng)絡(luò)具有更強(qiáng)的學(xué)習(xí)能力,即使網(wǎng)絡(luò)容易產(chǎn)生過(guò)擬合/梯度消失的問(wèn)題,在現(xiàn)有方法下也可以通過(guò)增加數(shù)據(jù)集,Dropout或者正則化/加入BN層解決。但是通過(guò)實(shí)驗(yàn)數(shù)據(jù)發(fā)現(xiàn),即使加入有效的措施抑制網(wǎng)絡(luò)產(chǎn)生過(guò)擬合或者梯度消失,網(wǎng)絡(luò)的精度也會(huì)隨著深度的增加而下降,并且還不是由于過(guò)擬合引起的(實(shí)驗(yàn)數(shù)據(jù)表明越深的網(wǎng)絡(luò)training loss反而越高)

          事實(shí)上,阻礙網(wǎng)絡(luò)向深度發(fā)展的一個(gè)主要因素就是梯度不能得到有效的傳播,越深的網(wǎng)絡(luò)反傳過(guò)程中的梯度相關(guān)性會(huì)越來(lái)越差,接近于白噪聲,導(dǎo)致梯度的更新也相當(dāng)于隨機(jī)擾動(dòng)。

          Resnet到底在解決一個(gè)什么問(wèn)題呢?https://www.zhihu.com/question/64494691

          打個(gè)形象的比喻,就如我們小時(shí)候玩過(guò)的口傳悄悄話游戲,隨著參與人數(shù)的增多,最后一個(gè)人口中說(shuō)出的信息往往早已和原先紙條上的信息大相徑庭。

          3.1 改進(jìn)

          以往的瓶頸:深度網(wǎng)絡(luò)不可控的梯度消失,深層網(wǎng)絡(luò)與淺層網(wǎng)絡(luò)的梯度相關(guān)性下降,網(wǎng)絡(luò)難以訓(xùn)練。

          ResNet的改進(jìn):引入了一個(gè)殘差映射的結(jié)構(gòu)來(lái)解決網(wǎng)絡(luò)退化的問(wèn)題:

          何為殘差映射?

          假設(shè)輸入的特征為x,期望輸出的特征為H(x)。我們知道,對(duì)于一般的神經(jīng)網(wǎng)絡(luò)而言,每一層的目的無(wú)非就是對(duì)輸入x進(jìn)行非線性變換,將特征x映射到盡量趨近H(x),即,網(wǎng)絡(luò)需要直接擬合輸出H(x).

          而對(duì)于殘差映射,模塊中通過(guò)引入一個(gè)shortcut分支(恒等映射),將網(wǎng)絡(luò)需要擬合的映射變?yōu)闅埐頕(x):F(x) = H(x) - x.

          作者在論文中假設(shè):相較于直接優(yōu)化H(x),優(yōu)化殘差映射F(x)能有效緩解反向傳播過(guò)程中的梯度消失問(wèn)題,解決了深度網(wǎng)絡(luò)不可訓(xùn)練的困難:[Resnet-50網(wǎng)絡(luò)結(jié)構(gòu)詳解]https://www.cnblogs.com/qianchaomoon/p/12315906.html

          3.2 PyTorch 復(fù)現(xiàn) ResNet-50

          3.2.1 ResNet-50網(wǎng)絡(luò)整體架構(gòu)

          3.2.2 Bottleneck結(jié)構(gòu)

          論文中將Resnet-50分成了4個(gè)大的卷積組,每一個(gè)大的卷積組叫做一個(gè)Bottleneck(瓶頸)模塊(輸入和輸出的特征圖通道較多,中間的卷積層特征深度較淺,類似瓶頸的中間小兩頭大的結(jié)構(gòu))。卷積組與卷積組之間會(huì)通過(guò)一個(gè)shortcut相連。

          左:非瓶頸結(jié)構(gòu),右:瓶頸結(jié)構(gòu)

          值得注意的是,ResNet使用Bottleneck結(jié)構(gòu)主要是是為了減小網(wǎng)絡(luò)的參數(shù)量(特征降維),在實(shí)際中作者注意到,瓶頸結(jié)構(gòu)的使用同樣出現(xiàn)了普通網(wǎng)絡(luò)的退化問(wèn)題:

          3.2.3 ResNet-50圖解及各層參數(shù)細(xì)節(jié)

          對(duì)于F(x)+x,ResNet采取的是逐通道相加的形式,因此在相加時(shí)需要考慮兩者的通道數(shù)是否相同,相同的情況直接相加即可(圖實(shí)線處),若兩者通道不同,需要用1x1卷積對(duì)特征進(jìn)行升維,將通道數(shù)變?yōu)橄嗤?圖虛線處):

          3.2.4 實(shí)現(xiàn)一個(gè)Bottleneck模塊:

          #?將Conv+BN封裝成一個(gè)基礎(chǔ)卷積類:
          class?BasicConv2d(nn.Module):
          ????def?__init__(self,?in_channel,?out_channel,?kernel_size,?stride=1,?padding=0):
          ????????super(BasicConv2d,?self).__init__()
          ????????self.conv?=?nn.Sequential(
          ????????????nn.Conv2d(in_channel,?out_channel,?kernel_size,
          ??????????????????????stride=stride,?padding=padding,?bias=False),
          ????????????nn.BatchNorm2d(out_channel)
          ????????)

          ????def?forward(self,?x):
          ????????x?=?self.conv(x)
          ????????return?x

          #?一個(gè)Bottleneck模塊:
          class?Bottleneck(nn.Module):
          ????def?__init__(self,?in_channel,?mid_channel,?out_channel,?stride=1):
          ????????super(Bottleneck,?self).__init__()

          ????????self.judge?=?in_channel?==?out_channel

          ????????self.bottleneck?=?nn.Sequential(
          ????????????BasicConv2d(in_channel,?mid_channel,?1),
          ????????????nn.ReLU(True),
          ????????????BasicConv2d(mid_channel,?mid_channel,?3,?padding=1,?stride=stride),
          ????????????nn.ReLU(True),
          ????????????BasicConv2d(mid_channel,?out_channel,?1),
          ????????)
          ????????self.relu?=?nn.ReLU(True)
          ????????#?下采樣部分由一個(gè)包含BN層的1x1卷積構(gòu)成:
          ????????if?in_channel?!=?out_channel:
          ????????????self.downsample?=?BasicConv2d(
          ????????????????in_channel,?out_channel,?1,?stride=stride)

          ????def?forward(self,?x):
          ????????out?=?self.bottleneck(x)
          ????????#?若通道不一致需使用1x1卷積下采樣
          ????????if?not?self.judge:
          ????????????self.identity?=?self.downsample(x)
          ????????????#?殘差+恒等映射=輸出
          ????????????out?+=?self.identity
          ????????#?否則直接相加
          ????????else:
          ????????????out?+=?x

          ????????out?=?self.relu(out)

          ????????return?out

          3.2.5 實(shí)現(xiàn)resnet-50

          #?Resnet50:
          class?ResNet_50(nn.Module):
          ????def?__init__(self,?class_num):
          ????????super(ResNet_50,?self).__init__()
          ????????self.conv?=?BasicConv2d(3,?64,?7,?stride=2,?padding=3)
          ????????self.maxpool?=?nn.MaxPool2d(3,?stride=2,?padding=1)
          ????????#?卷積組1
          ????????self.block1?=?nn.Sequential(
          ????????????Bottleneck(64,?64,?256),
          ????????????Bottleneck(256,?64,?256),
          ????????????Bottleneck(256,?64,?256),
          ????????)
          ????????#?卷積組2
          ????????self.block2?=?nn.Sequential(
          ????????????Bottleneck(256,?128,?512,?stride=2),
          ????????????Bottleneck(512,?128,?512),
          ????????????Bottleneck(512,?128,?512),
          ????????????Bottleneck(512,?128,?512),
          ????????)
          ????????#?卷積組3
          ????????self.block3?=?nn.Sequential(
          ????????????Bottleneck(512,?256,?1024,?stride=2),
          ????????????Bottleneck(1024,?256,?1024),
          ????????????Bottleneck(1024,?256,?1024),
          ????????????Bottleneck(1024,?256,?1024),
          ????????????Bottleneck(1024,?256,?1024),
          ????????????Bottleneck(1024,?256,?1024),
          ????????)
          ????????#?卷積組4
          ????????self.block4?=?nn.Sequential(
          ????????????Bottleneck(1024,?512,?2048,?stride=2),
          ????????????Bottleneck(2048,?512,?2048),
          ????????????Bottleneck(2048,?512,?2048),
          ????????)
          ????????self.avgpool?=?nn.AvgPool2d(4)
          ????????self.classifier?=?nn.Linear(2048,?class_num)

          ????def?forward(self,?x):
          ????????x?=?self.conv(x)
          ????????x?=?self.maxpool(x)
          ????????x?=?self.block1(x)
          ????????x?=?self.block2(x)
          ????????x?=?self.block3(x)
          ????????x?=?self.block4(x)
          ????????x?=?self.avgpool(x)
          ????????x?=?x.view(x.size(0),?-1)
          ????????out?=?self.classifier(x)

          ????????return?out

          4.FPN(特征金字塔)

          4.1 特征的語(yǔ)義信息

          對(duì)于CNN網(wǎng)絡(luò),圖像通過(guò)網(wǎng)絡(luò)淺層的卷積層,輸出的特征圖往往只能表示一些簡(jiǎn)單的語(yǔ)義信息(比如一些簡(jiǎn)單的線條),越深層的網(wǎng)絡(luò),提取特征表示的語(yǔ)義信息也就越復(fù)雜(從一些紋理,到一些類別具有的相似輪廓):(圖中的特征有經(jīng)過(guò)反卷積上采樣)

          因此,傳統(tǒng)的檢測(cè)網(wǎng)絡(luò)通常只在最后一個(gè)卷積輸出上的高層語(yǔ)義特征圖進(jìn)行后續(xù)的步驟,但這也不可避免的存在一些問(wèn)題。

          4.2 改進(jìn)

          我們知道,越是深層的網(wǎng)絡(luò),特征的下采樣率也就越高,即深層的特征圖一個(gè)像素就對(duì)應(yīng)淺層特征的一片區(qū)域,這對(duì)于大目標(biāo)的檢測(cè)不會(huì)造成太大的影響。但對(duì)于圖像上的小目標(biāo),在深層特征上的有效信息較少,導(dǎo)致網(wǎng)絡(luò)對(duì)于小物體的檢測(cè)性能急劇下降,這種現(xiàn)象也被稱作多尺度問(wèn)題。

          基于多尺度問(wèn)題,一個(gè)直接的解決辦法便是利用圖像金字塔,將原始的輸入變換為多張不同尺寸的多尺度圖像,將這些圖像分別進(jìn)行特征提取,生成多尺度的特征后再進(jìn)行后續(xù)的處理,這樣一來(lái),在小尺度的特征上檢測(cè)到小目標(biāo)的幾率就大大增加。這種方法簡(jiǎn)單有效,曾大量在COCO目標(biāo)檢測(cè)競(jìng)賽上使用。但這種方法的缺點(diǎn)就在于計(jì)算量大,需要消耗大量的時(shí)間。

          對(duì)此,FPN網(wǎng)絡(luò)(Feature Pyramid Networks)針對(duì)這一問(wèn)題改進(jìn)了提取多尺度特征的方法?;?.1的介紹我們知道,卷積網(wǎng)絡(luò)不同層提取的特征尺寸各不相同,本身就類似于一個(gè)金字塔的結(jié)構(gòu),同時(shí),每一層的語(yǔ)義信息也各不相同,越淺的特征語(yǔ)義信息越簡(jiǎn)單,顯示的細(xì)節(jié)也就越多,越深層的特征顯示的細(xì)節(jié)越少,語(yǔ)義信息越高級(jí)?;诖?,FPN網(wǎng)絡(luò)在特征提取的過(guò)程中融合了不同卷積層的特征,較好的改善了多尺度檢測(cè)問(wèn)題。

          4.3 PyTorch 復(fù)現(xiàn) FPN

          4.3.1 FPN網(wǎng)絡(luò)架構(gòu)

          FPN網(wǎng)絡(luò)主要包含四個(gè)部分,自下而上網(wǎng)絡(luò),自上而下網(wǎng)絡(luò),橫向連接與卷積融合。

          1. 自下而上網(wǎng)絡(luò)(提供不同尺度的特征):

            最左側(cè)為普通的特征提取卷積網(wǎng)絡(luò)(ResNet),C2-C4代表resnet中的四個(gè)大的卷積組,包含了多個(gè)Bottleneck結(jié)構(gòu),原始圖像的輸入就從該結(jié)構(gòu)開(kāi)始。

          2. 自上而下網(wǎng)絡(luò)(提供高層語(yǔ)義特征): 在這一結(jié)構(gòu)中,首先對(duì)C5進(jìn)行1x1卷積降低通道數(shù)得到M5,接著依次上采樣得到M4,M3,M2.目的是得到與C4,C3,C2相同尺寸但不同語(yǔ)義的特征。方便特征的融合(融合的方式為逐元素相加)。

            值得注意的是,在網(wǎng)絡(luò)的上采樣過(guò)程中采用的不是反卷積或者非線性插值方法,而是普通的2倍最鄰近上采樣(可以最大程度保留特征圖的語(yǔ)義信息,得到既有良好的空間信息又有較強(qiáng)烈的語(yǔ)義信息的特征圖。):【論文筆記】FPN —— 特征金字塔:https://zhuanlan.zhihu.com/p/92005927

          1. 橫向連接:

            將高層的語(yǔ)義特征與淺層的細(xì)節(jié)特征相融合(中途使用1x1卷積使得兩者的通道數(shù)相同)

          2. 卷積融合:

            得到相加的特征后,再利用3x3卷積對(duì)M2-M4進(jìn)一步融合(論文表示這么做可以消除上采樣帶來(lái)的重疊效應(yīng))

          4.3.2 復(fù)現(xiàn)FPN網(wǎng)絡(luò)

          #?導(dǎo)入resnet50
          resnet?=?models.resnet50(pretrained=True)
          #?分塊,?以便提取不同深度網(wǎng)絡(luò)的特征
          layer1?=?nn.Sequential(
          ????resnet.conv1,
          ????resnet.bn1,
          ????resnet.relu,
          ????resnet.maxpool,
          )
          layer2?=?resnet.layer1
          layer3?=?resnet.layer2
          layer4?=?resnet.layer3
          layer5?=?resnet.layer4


          class?FPN(nn.Module):
          ????def?__init__(self):
          ????????super(FPN,?self).__init__()
          ????????#?3x3?卷積融合特征
          ????????self.MtoP?=?nn.Conv2d(256,?256,?3,?1,?1)
          ????????#?橫向連接,?使用1x1卷積降維
          ????????self.C2toM2?=?nn.Conv2d(256,?256,?1,?1,?0)
          ????????self.C3toM3?=?nn.Conv2d(512,?256,?1,?1,?0)
          ????????self.C4toM4?=?nn.Conv2d(1024,?256,?1,?1,?0)
          ????????self.C5toM5?=?nn.Conv2d(2048,?256,?1,?1,?0)
          ????#?特征融合方法
          ????def?_upsample_add(self,?in_C,?in_M):
          ????????H?=?in_M.shape[2]
          ????????W?=?in_M.shape[3]
          ????????#?最鄰近上采樣方法
          ????????return?F.upsample_bilinear(in_C,?size=(H,?W))?+?in_M

          ????def?forward(self,?x):
          ????????#?自下而上
          ????????C1?=?layer1(x)
          ????????C2?=?layer2(C1)
          ????????C3?=?layer3(C2)
          ????????C4?=?layer4(C3)
          ????????C5?=?layer5(C4)
          ????????#?自上而下+橫向連接
          ????????M5?=?self.C5toM5(C5)
          ????????M4?=?self._upsample_add(M5,?self.C4toM4(C4))
          ????????M3?=?self._upsample_add(M4,?self.C3toM3(C3))
          ????????M2?=?self._upsample_add(M3,?self.C2toM2(C2))
          ????????#?卷積融合
          ????????P5?=?self.MtoP(M5)
          ????????P4?=?self.MtoP(M4)
          ????????P3?=?self.MtoP(M3)
          ????????P2?=?self.MtoP(M2)
          ????????#?返回的是多尺度特征
          ????????return?P2,?P3,?P4,?P5

          如發(fā)現(xiàn)本文中存在任何錯(cuò)誤或是有不解的地方,歡迎在評(píng)論區(qū)留言~

          往期精彩回顧






          瀏覽 56
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  京熱大亂交无碼大亂交在线 | 在线观看亚州视频 | 中文字幕日韩人妻在线 | 亚洲天堂福利视频 | 波多野结衣不打码视频 |