1. 程式人生 > 其它 >DeepLab 系列總結

DeepLab 系列總結

本文是基於一篇部落格的學習筆記
部落格原文:https://blog.csdn.net/fanxuelian/article/details/85145558

一、DeepLab 系列

(一)DeepLab V1

1. 基礎:VGG16

參考:https://blog.csdn.net/qq_43636375/article/details/114917772

輸入影象大小:224x224x3

VGG16的卷積層池化層可以劃分為5個Block

  • Block1:conv3-64 -> conv3-64 -> maxpool
    • in_size=(224,224,3)
    • 2個卷積層,kernel_size=3,out_channels=64
    • 1個最大池化層,kernel_size=2
    • out_size=(112,112,64)
  • Block2:conv3-128 -> conv3-128 -> maxpool
    • 2個卷積層,kernel_size=3,out_channels=128
    • 1個最大池化層,kernel_size=2
    • out_size=(56,56,128)
  • Block3:conv3-256 -> conv3-256 -> conv3-256 -> maxpool
    • 3個卷積層,kernel_size=3,out_channels=256
    • 1個最大池化層,kernel_size=2
    • out_size=(28,28,256)
  • Block4:conv3-512 -> conv3-512 -> conv3-512 -> maxpool
    • 3個卷積層,kernel_size=3,out_channels=512
    • 1個最大池化層,kernel_size=2
    • out_size=(14,14,512)
  • Block5:conv3-512 -> conv3-512 -> conv3-512 -> maxpool
    • 3個卷積層,kernel_size=3,out_channels=512
    • 1個最大池化層,kernel_size=2
    • out_size=(7,7,512)

VGG16是多個卷積層和池化層交替組成的,最後做以多次全連線,這樣的結構類似LeNet和AlexNet,前半部分利用了卷積層去觀察全域性的特徵,後半部分利用線性層進行分類輸出,拋棄了位置特徵

2. 改進

參考:
https://zhuanlan.zhihu.com/p/104562658
https://blog.csdn.net/u011984148/article/details/109759574

  • 去掉了最後的全連線層:即改為 FCN 網路,語義分割全卷積網路的大勢所趨

  • 去掉了最後兩個池化層

    • 池化層的作用:縮小特徵層的尺寸快速擴大感受野。(擴大感受野,可以利用更多的上下文資訊進行分析)
    • 去除原因:
      • 傳統的深度卷積網路 DCNN 需要完成的任務是分類,需要給出的結果是圖片是什麼,而並不關心圖片中東西的位置,這與語義分割,這一關注識別的畫素級別的具體位置的需求背道而馳
      • 在 DCNN 中,要求網路具有平移不變性,這就是卷積和池化的特徵之一。pooling 的實際上是一個模糊位置的過程,增強了平移不變性這一特徵,而這反而不利於語義分割,語義分割需要更精確的資訊
    • 解決感受野不足的問題:在去掉 pooling 層後,感受野會隨之下降,解決方法是引入空洞卷積(Atrous Convolution),這樣可以在不增加計算量的情況下擴大感受野。而且更進一步,相比於先pooling後再卷積,使用空洞卷積可以讓特徵更密(因為pooling減少了解析度,這使得空洞卷積和普通卷積的位置不再是一一對應的了)
  • 引入條件隨機場CRF提高分類精度
    • 引入目的:在已有的語義分割網路如 U-net 中都存在形成預測畫素的“孤島”的微小不連續分類的問題,CRF 的引入目的在於解決這些誤差的生成
    • 原理:CRF 的方法可以理解為某種程度上的馬爾可夫(個人理解),如果體現在 NLP 領域即為通過上下文單詞更精確的識別當前單詞的詞性,也就是把當前物件周圍資訊納入對該物件的標籤預測中去
    • 效果:在語義分割中,目標是輸出每個畫素都被打上分類標籤的分割圖,那麼 CRF 的效果則為,使具有相似位置和顏色特徵的兩個畫素被打上相同標籤的概率更大,被分割的可能性更小,一定程度上避免了“孤島”的產生
    • 個人理解,條件隨機場在本質上是一個輸入和輸出尺寸相同的全連線層,在全域性上考慮了各個畫素之間的位置關係
3. 總處理流程
  • 輸入影象
  • 經歷基於 VGG 改造的 DCNN 網路得到粗糙的 score map(按我理解叫 heat map)
  • 使用雙線性取樣進行上取樣,提高 score map 的解析度
  • 使用 CRF 進行優化,去除“孤島”
  • 輸出分割圖

(二)DeepLab V2

1. 基礎:ResNet-101

參考:https://blog.csdn.net/qq_45649076/article/details/120494328

ResNet 可以理解為是 U-net 的疊加部分或者 FCN 中的 skip 相加部分(有異曲同工之處),都是將之前層的資料疊加到新的層上,這樣可以兼顧淺層卷積的解析度資訊和深層卷積的位置資訊,對於語義分割是有益的

基本模組(兩種不同的residual):BasicBlock 和 BottleNeck
  • 雙層的殘差結構 BasicBlock 很容易理解
  • 三層的殘差結構 BottleNeck :先用1x1卷積降通道 channel=256 -> 64,再進行3x3卷積,然後用1x1卷積升通道 channel=64 -> 256,這樣以來模組的輸入尺寸和卷積輸出尺寸一致,利用 short cut 相加得到模組輸出。這樣一降一升通道數的好處在於可以減少訓練引數,訓練速度更快

    CNN引數個數 = 卷積核尺寸 × 卷積核深度 × 卷積核組數 = 卷積核尺寸 × 輸入特徵矩陣深度 × 輸出特徵矩陣深度

  • 在實際應用的網路中最好採用 BottleNeck 模組為基本單元
  • 實際使用的 ResNet 網路中,有時需要讓通過 BottleNeck 模組後通道數下降,這時就需要對 short cut 進行1x1卷積的降通道處理

以18層的 ResNet 為例:

其他型別的 ResNet:(V2的基礎為其中的101-layer)

2. 改進:空洞空間金字塔池化 ASPP

參考:https://blog.csdn.net/qq_41731861/article/details/122560247

空洞卷積存在的劣勢:

  • 區域性資訊丟失:由於空洞卷積的計算方式類似於棋盤格式,某一層得到的卷積結果,來自上一層的獨立的集合,沒有相互依賴,卷積結果之間沒有相關性
  • 遠距離獲取的資訊沒有相關性:由於空洞卷積稀疏的取樣輸入訊號,使得遠距離卷積得到的資訊之間沒有相關性
class ASPP(nn.Module):
    def __init__(self, in_channel=512, depth=256):
        super(ASPP,self).__init__()
        self.mean = nn.AdaptiveAvgPool2d((1, 1)) #(1,1)means ouput_dim
        self.conv = nn.Conv2d(in_channel, depth, 1, 1)
        self.atrous_block1 = nn.Conv2d(in_channel, depth, 1, 1)
        self.atrous_block6 = nn.Conv2d(in_channel, depth, 3, 1, padding=6, dilation=6)
        self.atrous_block12 = nn.Conv2d(in_channel, depth, 3, 1, padding=12, dilation=12)
        self.atrous_block18 = nn.Conv2d(in_channel, depth, 3, 1, padding=18, dilation=18)
        self.conv_1x1_output = nn.Conv2d(depth * 5, depth, 1, 1)
 
    def forward(self, x):
        size = x.shape[2:]
 
        image_features = self.mean(x)
        image_features = self.conv(image_features)
        image_features = F.upsample(image_features, size=size, mode='bilinear')
 
        atrous_block1 = self.atrous_block1(x)
        atrous_block6 = self.atrous_block6(x)
        atrous_block12 = self.atrous_block12(x)
        atrous_block18 = self.atrous_block18(x)
 
        net = self.conv_1x1_output(torch.cat([image_features,
                                              atrous_block1, 
                                              atrous_block6,
                                              atrous_block12, 
                                              atrous_block18], 
                                              dim=1))
        return net

結合 ASPP 的程式碼來看:

  • ASPP 層先對輸入做一系列不同 padding 和 dilation 的空洞卷積,這些卷積通過調整這兩個引數以滿足輸出通道數和尺寸保持一致
  • 讓這些空洞卷積的輸出通過 concat 相加,得到 ASPP 層的輸出

ASPP 層解決了空洞卷積資訊丟失的劣勢,也同時增大了感受野,從不同的尺度上提取特徵

將 ASPP 融合入 ResNet-101:

即讓卷積6分裂為一系列的空洞卷積,分別進行後續的卷積操作,然後將所有的輸出 concat 在一起

(三)DeepLab V3

1. 基礎:DeepLab V2 ResNet-101
2. 改進
  • 捨棄 CRF:我覺得有必要研究一下

    因為分類結果精度已經提高到不需要CRF了(也可能是CRF不起作用了,誰知道呢)

  • 改進 ASPP 方案一:拓展網路的寬度
    • 在空洞卷積之後使用 batch normalization:待定
    • 增加了1x1卷積分支和 image pooling 分支:
      • 目的:解決使用空洞卷積帶來的問題,即隨著rate的增大,一次空洞卷積覆蓋到的有效畫素(特徵層本身的畫素,相應的補零畫素為非有效畫素)會逐漸減小到1也就是說太大的 padding 和 dilation 帶來了非中心取樣點位置過於偏僻,要麼太遠,要麼延申到 padding 補0區域,這些畫素取樣是沒有意義的。這就與我們擴充套件感受野獲取更大範圍的特徵的初衷相背離了
      • 措施:
        • 使用1x1的卷積:即當rate增大以後3x3卷積的退化形式,替代3x3卷積,減少引數個數
        • 增加image pooling:即全域性池化,來補充全域性特徵。具體做法是對每一個通道的畫素取平均,之後再上取樣到原來的解析度
  • 改進 ASPP 方案二:加深空洞卷積的深度

(四)DeepLab V3+

1. 基礎:Xception

參考:https://www.jianshu.com/p/9a0ba830af37?utm_source=oschina-app

Xception 是由 Inception v3 直接演變而來。其中引入了 Residual learning 的結構(Residual learning 在 CNN 模型中的使用可帶來收斂速度的加快)

其中 Inception v3 可以如圖表示,這樣的網路與 DeepLab V2 的 ASPP 先分後合的思想有異曲同工之處

在此基礎上

Xception 引入了 Entry/Middle/Exit 三個 flow ,每個 flow 內部使用不同的重複模組

  • 最核心的是中間不斷分析、過濾特徵的 Middel flow。
  • Entry flow 主要是用來不斷下采樣,減小空間維度
  • Middel flow 是不斷學習關聯關係,優化特徵
  • Exit flow 是彙總、整理特徵,用於交由FC(fully connected layer)來進行表達
2. 改進

參考:https://zhuanlan.zhihu.com/p/165632315

  • 使用更深的網路

  • 將所有的卷積層和池化層用深度可分離卷積(depthwise separable convolution / sep conv)進行替代

    • 深度可分離卷積主要分為逐通道卷積逐點卷積兩個過程
    • 逐通道卷積(Depthwise Convolution):每個 channel 使用一個一維3x3卷積核,卷積生成一個單維 map 輸出
    • 逐點卷積(Pointwise Convolution):所有 map 構建一個多維輸入,使用多維的1x1卷積核進行普通卷積,輸出指定通道數的多維張量
    • 優勢:從理論上講可以降低計算量,可以在運算量不增加的情況下把卷積網路做的更深,但是這樣的優勢僅僅侷限在理論上,因為這樣的卷積形式不能有效的利用硬體,所以實際上計算量雖小,效率並沒有明顯提升,個人見解,這樣的意義不大
  • 在每一次3x3的 sep conv 之後使用 Batch Normalization 和 ReLU

3. 網路架構總體改良:引入了 Encoder-Deconder 結構

之前的三個版本中,重點使用了 ASPP 的方法,總體上結構是一步步卷積池化,進行下采樣,然後再在最終得到的 feature map 上進行上取樣,這樣的在一個方向複雜而另一個方向簡單的方法有些粗糙了

V3+ 版本在此基礎上要引入類似 U-net 的 Encoder-Deconder 結構,即單方面複雜化了在 feature map 上進行上取樣的過程,這裡的具體操作方式與 FCN 的 skip 方法基本上一模一樣,即上取樣的到一定的解析度,然後與相同尺寸的收縮路徑中的某一層的輸出進行 concat,然後繼續如此上取樣,直到解析度達到端資料的要求

二、對於 DeepLab 系列的理解與總結

首先必須指出 DeepLab 網路的工作的端到端輸入輸出,輸入影象,輸出與影象在畫素級別對應的等大小分割圖,這就使得 DeepLab 必定是一個先下采樣提煉特徵,再上取樣恢復解析度的過程,從這個巨集觀的尺寸變化上,我認為是非常類似 Encoder-Deconder 結構的。這個意義上來看,不妨借用 U-net 的說法,稱兩個過程為收縮路徑和擴張路徑

  • V1 版本的總體結構是樸素的 VGG 網路,在收縮路徑上引入了擴大感受野的方式——空洞卷積,在擴張路徑上引入了 CRF 技術來優化“孤島”的問題
  • V2 版本有兩個重大改進,一個是引入了類似 skip 的 ResNet 殘差結構,來更好的匹配位置資訊和影象內容;另一個是引入了 ASPP 的先分後合的空洞卷積模型,來建立卷積結果之間的相關性
  • V3 版本在 V2 版本的基礎上改進了 ASPP,選擇性拓展了網路的寬度或深度,並且捨去了 CRF 技術
  • V3+ 版本在收縮路徑上改進了卷積方法,引入了深度可分離卷積來減少計算量,加深網路深度,在每一層的卷積完成後加入了 Batch Normalization 和 ReLU 來避免梯度消失;在擴張路徑上進行了改進,完整引入了 Encoder-Deconder 結構,用 skip 的方法使擴張路徑與收縮路徑建立聯絡,更細化了網路的輸出