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

          基于PyTorch的卷積神經(jīng)網(wǎng)絡(luò)經(jīng)典BackBone(骨干網(wǎng)絡(luò))復(fù)現(xiàn)

          共 30248字,需瀏覽 61分鐘

           ·

          2024-07-29 10:05

          點(diǎn)擊上方小白學(xué)視覺(jué)”,選擇加"星標(biāo)"或“置頂

          重磅干貨,第一時(shí)間送達(dá)

          作者丨helton_yan@CSDN(已授權(quán))
          來(lái)源丨h(huán)ttps://blog.csdn.net/SESESssss/article/details/114340066

          導(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 * 74096),
             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 = [(3224224)]) #輸出網(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, 3224224#構(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(3647, stride=2, padding=3),
                      nn.MaxPool2d(kernel_size=3, stride=2, padding=1),
                      nn.LocalResponseNorm(64),
                      BasicConv2d(64641),
                      BasicConv2d(641923, padding=1),
                      nn.LocalResponseNorm(192),
                      nn.MaxPool2d(kernel_size=3, stride=2, padding=1),
                  )
                  self.block2 = nn.Sequential(
                      Inception(1926496128163232),
                      Inception(256128128192329664),
                      nn.MaxPool2d(kernel_size=3, stride=2, padding=1),
                      Inception(48019296208164864),
                  )
                  self.block3 = nn.Sequential(
                      Inception(512160112224246464),
                      Inception(512128128256246464),
                      Inception(512112144288326464),
                  )
                  self.block4 = nn.Sequential(
                      nn.MaxPool2d(kernel_size=3, stride=2, padding=1),
                      Inception(52825616032032128128),
                      Inception(83225616032032128128),
                      Inception(83238419238448128128),
                      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(3647, stride=2, padding=3)
                  self.maxpool = nn.MaxPool2d(3, stride=2, padding=1)
                  # 卷積組1
                  self.block1 = nn.Sequential(
                      Bottleneck(6464256),
                      Bottleneck(25664256),
                      Bottleneck(25664256),
                  )
                  # 卷積組2
                  self.block2 = nn.Sequential(
                      Bottleneck(256128512, stride=2),
                      Bottleneck(512128512),
                      Bottleneck(512128512),
                      Bottleneck(512128512),
                  )
                  # 卷積組3
                  self.block3 = nn.Sequential(
                      Bottleneck(5122561024, stride=2),
                      Bottleneck(10242561024),
                      Bottleneck(10242561024),
                      Bottleneck(10242561024),
                      Bottleneck(10242561024),
                      Bottleneck(10242561024),
                  )
                  # 卷積組4
                  self.block4 = nn.Sequential(
                      Bottleneck(10245122048, stride=2),
                      Bottleneck(20485122048),
                      Bottleneck(20485122048),
                  )
                  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)了提取多尺度特征的方法。基于4.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(256256311)
                  # 橫向連接, 使用1x1卷積降維
                  self.C2toM2 = nn.Conv2d(256256110)
                  self.C3toM3 = nn.Conv2d(512256110)
                  self.C4toM4 = nn.Conv2d(1024256110)
                  self.C5toM5 = nn.Conv2d(2048256110)
              # 特征融合方法
              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



               
          下載1:OpenCV-Contrib擴(kuò)展模塊中文版教程
          在「小白學(xué)視覺(jué)」公眾號(hào)后臺(tái)回復(fù):擴(kuò)展模塊中文教程即可下載全網(wǎng)第一份OpenCV擴(kuò)展模塊教程中文版,涵蓋擴(kuò)展模塊安裝、SFM算法、立體視覺(jué)、目標(biāo)跟蹤、生物視覺(jué)、超分辨率處理等二十多章內(nèi)容。

          下載2:Python視覺(jué)實(shí)戰(zhàn)項(xiàng)目52講
          小白學(xué)視覺(jué)公眾號(hào)后臺(tái)回復(fù):Python視覺(jué)實(shí)戰(zhàn)項(xiàng)目,即可下載包括圖像分割、口罩檢測(cè)、車道線檢測(cè)、車輛計(jì)數(shù)、添加眼線、車牌識(shí)別、字符識(shí)別、情緒檢測(cè)、文本內(nèi)容提取、面部識(shí)別等31個(gè)視覺(jué)實(shí)戰(zhàn)項(xiàng)目,助力快速學(xué)校計(jì)算機(jī)視覺(jué)。

          下載3:OpenCV實(shí)戰(zhàn)項(xiàng)目20講
          小白學(xué)視覺(jué)公眾號(hào)后臺(tái)回復(fù):OpenCV實(shí)戰(zhàn)項(xiàng)目20講,即可下載含有20個(gè)基于OpenCV實(shí)現(xiàn)20個(gè)實(shí)戰(zhàn)項(xiàng)目,實(shí)現(xiàn)OpenCV學(xué)習(xí)進(jìn)階。

          交流群


          歡迎加入公眾號(hào)讀者群一起和同行交流,目前有SLAM、三維視覺(jué)、傳感器、自動(dòng)駕駛、計(jì)算攝影、檢測(cè)、分割、識(shí)別、醫(yī)學(xué)影像、GAN算法競(jìng)賽等微信群(以后會(huì)逐漸細(xì)分),請(qǐng)掃描下面微信號(hào)加群,備注:”昵稱+學(xué)校/公司+研究方向“,例如:”張三 + 上海交大 + 視覺(jué)SLAM“。請(qǐng)按照格式備注,否則不予通過(guò)。添加成功后會(huì)根據(jù)研究方向邀請(qǐng)進(jìn)入相關(guān)微信群。請(qǐng)勿在群內(nèi)發(fā)送廣告,否則會(huì)請(qǐng)出群,謝謝理解~


          瀏覽 51
          點(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>
                  国产婷婷五月综合亚洲 | 日本一道本高清在线一区二区 | 影音先锋资源亚洲在线 | 国产视频一区在线 | 免费观看成人 |