第四周:卷積神經網路 part 3

yzm10發表於2020-08-15

第四周:卷積神經網路 part 3

視訊學習

語義分割中的自注意力機制和低秩重建

  • 語義分割(Semantic Segmentation)
    • 概念:語義分割是在畫素級別上的分類,屬於同一類的畫素都要被歸為一類,因此語義分割是從畫素級別來理解影像的。
    • 思路:
      • 傳統方法:
        • TextonForest和基於隨機森林分類器等語義分割方法
      • 深度學習方法:
        • Patch classification
        • 全卷積方法(FCN)
        • encoder-decoder架構
        • 空洞卷積(Dilated/Atrous)
        • 條件隨機場
    • 幾種架構:

ps:空洞卷積、池化目的都是增大感受野。

  • 自注意力機制(Self-attention Mechanism)
    • 是注意力機制的改進,其減少了對外部資訊的依賴,更擅長捕捉資料或特徵的內部相關性。

背景:

語義分割是計算機視覺幾大主任務之一,被廣泛應用到自動駕駛、遙感監測等領域中。語義分割研究中的若干成果,也被諸多相關領域沿用。自注意力機制繼在 NLP 領域取得主導地位之後,近兩年在計算機視覺領域也開始獨領風騷。自注意力機制在語義分割網路中的應用,並由之衍生出的一系列低秩重建相關的方法。

影像語義分割前沿進展

超畫素、語義分割、例項分割、全景分割的區別

既需要細節,又需要捕捉全域性資訊

  • 得到大尺度資訊方法

    • 1.Non-local modules(非區域性模組)
    • 2.self-attention(自注意力)
    • 3.Dilated convolution(空洞卷積)
    • 4.Pyramid/global pooling(金字塔/全域性池化)
  • 缺陷

    • 1、2計算資源消耗多
    • 3、4雖相對低代價,但各向同性,很難獲得各向異性

提高CNNs中遠端依賴關係建模能力的一種方法是採用self-attention機制non-local模組。然而,它們會消耗大量記憶體。而其他的遠端上下文建模方法包括:

1)擴張卷積,其目的是在不引入額外引數的情況下擴大CNNs的接受域;

2)全域性/金字塔池化,它總結了影像的全域性線索。

然而,這些方法的一個常見限制,包括擴張卷積和池化在內,它們都在方形視窗中探測輸入特徵圖。這限制了它們在捕獲廣泛存在於現實場景中的各向異性的上下文上的靈活性。

  • CVPR2020 帶狀池化(Strip Pooling)
    • 為了更有效地捕獲長依賴關係,本文在空間池化擴大CNNs的感受野和捕獲上下文資訊的基礎上,提出了條紋池化的概念,作為全域性池化的替代方案。
    • 優點:
      • 它沿著一個空間維度部署一個長條狀的池化核形狀,因此能夠捕獲孤立區域的長距離關係
      • 在其他空間維度上保持較窄的核心形狀,便於捕獲區域性上下文,防止不相關區域干擾標籤預測
    • 整合這種長而窄的池核心使語義分割網路能夠同時聚合全域性和本地上下文。這與傳統的從固定的正方形區域收集上下文的池化有本質的不同。
    • 基於條紋池化的想法,作者提出了兩種即插即用的池化模組:
      • Strip Pooling Module (SPM)
      • Mixed Pooling module (MPM)

程式碼練習

完善 HybridSN 高光譜分類網路

模型的網路結構為如下圖所示:

三維卷積部分:

  • conv1:(1, 30, 25, 25), 8個 7x3x3 的卷積核 ==>(8, 24, 23, 23)
  • conv2:(8, 24, 23, 23), 16個 5x3x3 的卷積核 ==>(16, 20, 21, 21)
  • conv3:(16, 20, 21, 21),32個 3x3x3 的卷積核 ==>(32, 18, 19, 19)

接下來要進行二維卷積,因此把前面的 32*18 reshape 一下,得到 (576, 19, 19)

二維卷積:(576, 19, 19) 64個 3x3 的卷積核,得到 (64, 17, 17)

接下來是一個 flatten 操作,變為 18496 維的向量,

接下來依次為256,128節點的全連線層,都使用比例為0.4的 Dropout,

最後輸出為 16 個節點,是最終的分類類別數。

下面是 HybridSN 類的程式碼:

class_num = 16

class SELayer(nn.Module):

  def __init__(self, channel, reduction=16):
    super(SELayer, self).__init__()
    self.avg_pool = nn.AdaptiveAvgPool2d(1)
    self.fc = nn.Sequential(
        nn.Linear(channel, channel // reduction, bias=False),
        nn.ReLU(inplace=True),
        nn.Linear(channel // reduction, channel, bias=False),
        nn.Sigmoid()
    )

  def forward(self, x):
    b, c, _, _ = x.size()
    y = self.avg_pool(x).view(b, c)
    y = self.fc(y).view(b, c, 1, 1)
    return x * y.expand_as(x)

class HybridSN(nn.Module):

  def __init__(self):
    super(HybridSN, self).__init__()
    self.conv1=nn.Conv3d(in_channels=1,out_channels=8,kernel_size=(7,3,3))
    self.bn1 = nn.BatchNorm3d(8)
    self.conv2=nn.Conv3d(in_channels=8,out_channels=16,kernel_size=(5,3,3))
    self.bn2 = nn.BatchNorm3d(16)
    self.conv3=nn.Conv3d(in_channels=16,out_channels=32,kernel_size=(3,3,3))
    self.bn3 = nn.BatchNorm3d(32)
    self.se1 = SELayer(576, 16)
    self.conv4 = nn.Conv2d(576, 64, 3)
    self.bn4 = nn.BatchNorm2d(64)
    self.se2 = SELayer(64, 16)
    self.fc1=nn.Linear(18496,256)
    self.fc2=nn.Linear(256,128)
    self.fc3=nn.Linear(128,class_num)
    self.dropout = nn.Dropout(p=0.4)
    # self.soft = nn.Softmax(dim = 1)
    
  def forward(self, x):
    x = self.conv1(x)
    # x = self.bn1(x)
    x = F.relu(x)
    x = self.conv2(x)
    # x = self.bn2(x)
    x = F.relu(x)
    x = self.conv3(x)
    # x = self.bn3(x)
    x = F.relu(x)

    x = torch.reshape(x,[x.shape[0],576,19,19])

    # x = self.se1(x)
    x = self.conv4(x)
    # x = self.se2(x)
    # x = self.bn4(x)
    x = F.relu(x)

    x = torch.flatten(x,start_dim=1)

    x = self.dropout(F.relu(self.fc1(x)))
    x = self.dropout(F.relu(self.fc2(x)))
    x = self.fc3(x)
    # x = self.soft(x)

    return x

# 隨機輸入,測試網路結構是否通
x = torch.randn(1, 1, 30, 25, 25)
net = HybridSN()
y = net(x)
print(y.shape)

準確率為 95.96%

效能良好,測試結果穩定。

也可以考慮解開程式碼註釋部分加入BN,進一步提升效能。

準確率為 96.61%

先後順序:Batch Normalization 層恰恰插入在 Conv 層或全連線層之後,而在 ReLU等啟用層之前。而對於 dropout 則應當置於 activation layer 之後。

注意:BN和Dropout單獨使用都能減少過擬合併加速訓練速度,但如果一起使用的話並不會產生1+1>2的效果,相反可能會得到比單獨使用更差的效果。

SENet 實現

該網路通過學習的方式獲取每個特徵通道的重要程度,然後依照這個重要程度去提升有用的特徵並抑制對當前任務用處不大的特徵。

將上方程式碼SE註釋部分解開,加入SE模組。

準確率為 97.36%

SE模組主要為了提升模型對channel特徵的敏感性,這個模組是輕量級的,而且可以應用在現有的網路結構中,只需要增加較少的計算量就可以帶來效能的提升。

總結:

方法 accuracy
普通HybridSN 95.96%
加入BN 96.61%
加入SENet 97.36%

其他的還可以通過新增學習率衰減函式來提升效能,這裡mark一下,以後做個實驗驗證。

ResNet預訓練模型 垃圾分類識別

AI研習社最新的比賽:垃圾分類識別

老師讓我們試一試,我找了個預訓練的ResNet模型微調了一下,加了幾個簡單的trick,結果如下:

離標準分_85還是有些距離,看來通用的網路並不比針對特定問題設計的網路表現更好。

後續我會繼續關注比賽,爭取學習更多的深度學習知識,設計出更加強大的網路。

相關文章