CNN常見問題總結

前言

在初次學習深度學習的時候,必不可少的接觸卷積神經網絡(CNN),本篇文章就記錄一下通過應用CNN來做分類時,自己遇到的一些問題和踩到的一些坑。

  • 本文使用的時Pytorch 1.1.0版本,更多關於pytorch的資料可到pytorch官網和pytorch中文網查找資料,有CUDA 10.1版本來進行GPU加速(搞深度學習沒GPU基本完蛋)。

CNN原理

CNN網絡是一種用來處理局部和整體相關性的計算網絡結構,被應用在圖像識別(CV)、自然語言處理(NLP)甚至是語音識別領域,因爲圖像數據具有顯著的局部與整體關係,其在圖像識別領域的應用獲得了巨大的成功。

其實說白了CNN能在CV領域取得巨大成功最重要的就兩個點:

  • 局部連接
    局部連接的思想,是受啓發於生物學裏的視覺系統結構,視覺皮層的神經元就是僅用局部接受信息。對於二維圖像,局部像素關聯性較強。這種局部連接保證了訓練後的濾波器能夠對局部特徵有最強的響應,使神經網絡可以提取數據的局部特徵; 下圖是一個很經典的圖示,左邊是全連接,右邊是局部連接。
    在這裏插入圖片描述

  • 權值共享
    權值共享,即計算同一深度的神經元時採用的卷積核參數是共享的。

在這裏插入圖片描述

  • 總結:這裏就體現了卷積神經網絡的奇妙之處,使用少量的參數,卻依然能有非常出色的性能。上述僅僅是提取圖像一種特徵的過程。如果要多提取出一些特徵,可以增加多個卷積核,不同的卷積核能夠得到圖像不同尺度下的特徵,稱之爲特徵圖(feature map)。

CNN的結構

以圖像分類任務爲例,CNN一般包含5種類型的網絡層次結構:

  1. 輸入層(input)。一般輸入層都是對原始圖像經過數據的預處理之後的像素矩陣,往往數據預處理的越好,結果就越好。
  2. 卷積層(conv2d)。局部連接,權值共享,說白了就是做特徵提取,卷積層越深提取到的特徵就越豐富,分類也就越準確。
  3. 批歸一化層(Batch Normalization)。雖然我們對輸入數據進行了歸一化處理,但是輸入數據經過 σ(WX+b) 這樣的矩陣乘法以及非線性運算之後,其數據分佈很可能被改變,而隨着深度網絡的多層運算之後,數據分佈的變化將越來越大。如果我們能在網絡的中間也進行歸一化處理,是否對網絡的訓練起到改進作用呢?答案是肯定的。
  4. 激活層(ReLU)。激活層(Activation Layer)負責對卷積層抽取的特徵進行激活,由於卷積操作是由輸入矩陣與卷積核矩陣進行相差的線性變化關係,需要激活層對其進行非線性的映射。激活層主要由激活函數組成,即在卷積層輸出結果的基礎上嵌套一個非線性函數,讓輸出的特徵圖具有非線性關係。
  5. 池化層(Pooling)。作用是對感受域內的特徵進行篩選,提取區域內最具代表性的特徵,能夠有效地降低輸出特徵尺度,進而減少模型所需要的參數量。
  6. 全連接(FC)。負責對卷積神經網絡學習提取到的特徵進行彙總,將多維的特徵輸入映射爲二維的特徵輸出通常低維度特徵對應任務的學習目標。

CNN卷積層的基本參數

卷積層中需要用到卷積核(濾波器或特徵檢測器)與圖像特徵矩陣進行點乘運算,利用卷積核與對應的特徵感受域進行劃窗式運算時,需要設定卷積覈對應的大小、步長、個數以及填充的方式。以最簡單的例子進行說明:輸入信號的形式爲(N,Cin,H,W)(N,C_in ,H,W)NN表示batch size,CinC_in表示channel個數,HWH,W分別表示特徵圖的高和寬。

  1. in_channels(int) – 輸入信號的通道
  2. out_channels(int) – 卷積產生的通道
  3. kerner_size(int or tuple) - 卷積核的尺寸
  4. stride(int or tuple, optional) - 卷積步長
  5. padding(int or tuple, optional) - 輸入的每一條邊補充0的層數
  6. dilation(int or tuple, optional) – 卷積核元素之間的間距
  7. groups(int, optional) – 從輸入通道到輸出通道的阻塞連接數
  8. bias(bool, optional) - 如果bias=True,添加偏置

參數存在如下關係:

input:(N,Cin,Hin,Win)(N,C_in,H_in,W_in)
output:(N,Cout,Hout,Wout)(N,C_out,H_out,W_out)
Hout=floor((Hin+2padding[0]dilation[0](kernerlsize[0]1)1)/stride[0]+1)H_{out}=floor((H_{in}+2padding[0]-dilation[0](kernerl_size[0]-1)-1)/stride[0]+1)

Wout=floor((Win+2padding[1]dilation[1](kernerlsize[1]1)1)/stride[1]+1)W_{out}=floor((W_{in}+2padding[1]-dilation[1](kernerl_size[1]-1)-1)/stride[1]+1)

採坑問題系列

1.深度學習爲什麼要“深”?

前提:在一定範圍內。

  1. 深度神經網絡是一種特徵遞進式的學習算法,淺層的神經元直接從輸入數據中學習一些低層次的簡單特徵,例如邊緣、紋理等。而深層的特徵則基於已學習到的淺層特徵繼續學習更高級的特徵,從計算機的角度學習深層的語義信息。
  2. 在神經元數量相同的情況下,深層網絡結構具有更大容量,分層組合帶來的是指數級的表達空間,能夠組合成更多不同類型的子結構,這樣可以更容易地學習和表示各種特徵。同時也意味着由激活函數帶來的非線性變換的嵌套層數更多,就能構造更復雜的映射關係。

2.CNN不適合那些問題?

這個問題可是困惑了我好久好久。最終得出一個結論:理論指導實踐
CNN之所以這麼火,在其原理上:局部連接,權值共享,所以多用於圖像領域,效果顯著。原因就在於這“局部連接”,圖片是像素你可以理解是相互獨立的,沒有關聯的。而像文本、音頻等數據是相互依賴的,解決思路更多的是RNN(TextCNN,LSTM等)。
由於本人一開始跟風,上來就直接來了個ResNet-18來對截面數據進行分類,結果準確率低得可伶……

綜上:CNN跟適合CV領域,RNN跟適合NLP領域,機器學習更適合日誌數據領域。

3.batch size的設置與網絡的關係?

批次大小指定一次性流入模型的數據樣本個數,根據任務和計算性能限制判斷實際取值,在一些圖像任務中往往由於計算性能和存儲容量限制只能選取較小的值。在相同迭代次數的前提下,數值越大模型越穩定,泛化能力越強,損失值曲線越平滑,模型也更快地收斂。

  1. 內存利用率提高了,大矩陣乘法的並行化效率提高。
  2. 跑完一次 epoch(全數據集)所需的迭代次數減少,對於相同數據量的處理速度進一步加快。
  3. 在一定範圍內,一般來說 Batch_Size 越大,其確定的下降方向越準,引起訓練震盪越小,損失值曲線越平滑,模型也更快地收斂。

4.kernel_size的大小設置?

卷積核的大小定義了卷積的感受野,在早期的卷積神經網絡中(如AlexNet、ZFNet),用到了一些較大的卷積核(11×11和7×7),這種大卷積核反而會導致計算量大幅增加,不利於訓練更深層的模型,相應的計算性能也會降低。後來的卷積神經網絡(VGG、GoogLeNet等),發現通過堆疊2個3×3卷積核可以獲得與5×5卷積核相同的感受視野,同時參數量會更少,因此可以認爲,在大多數情況下通過堆疊較小的卷積核比直接採用單個更大的卷積核會更加有效。

但是,這並不是表示更大的卷積核就沒有作用,在某些領域應用卷積神經網絡時仍然可以採用較大的卷積核。譬如在自然語言處理領域,由於文本內容不像圖像數據可以對特徵進行很深層的抽象,往往在該領域的特徵提取只需要較淺層的神經網絡即可。在將卷積神經網絡應用在自然語言處理領域時,通常都是較爲淺層的卷積層組成,但是文本特徵有時又需要有較廣的感受域讓模型能夠組合更多的特徵(如詞組和字符),此時直接採用較大的卷積核將是更好的選擇。

總結:

  1. kernel_size不是越大越好,對於CV領域,應採取較小卷積核(3x3)來加深網絡結構;對於NLP領域,較大卷積核效果更佳。
  2. 單獨的1×1極小卷積核只能用作分離卷積而不能對輸入的原始特徵進行有效的組合,極大的卷積核通常會組合過多的無意義特徵從而浪費了大量的計算資源。

5.每層卷積是否只能用一種尺寸的卷積核?

事實上,同一層特徵圖可以分別使用多個不同尺寸的卷積核,以獲得不同尺度的特徵,得到的新特徵可以看作不同感受域提取的特徵組合,相比於單一卷積核會有更強的表達能力。

6.爲什麼要用Batch Normalization(BN)?

批歸一化(BN)算法的優點:

  1. 減少了人爲選擇參數。在某些情況下可以取消 dropout 和 L2 正則項參數,或者採取更小的 L2 正則項約束參數;
  2. 減少了對學習率的要求。現在我們可以使用初始很大的學習率或者選擇了較小的學習率,算法也能夠快速訓練收斂;
  3. 可以不再使用局部響應歸一化。BN 本身就是歸一化網絡(局部響應歸一化在 AlexNet 網絡中存在)
  4. 破壞原來的數據分佈,一定程度上緩解過擬合(防止每批訓練中某一個樣本經常被挑選到,文獻說這個可以提高 1% 的精度)。
  5. 減少梯度消失,加快收斂速度,提高訓練精度。

7.爲什麼需要非線性激活函數?

  1. 激活函數對模型學習、理解非常複雜和非線性的函數具有重要作用。
  2. 激活函數可以引入非線性因素。如果不使用激活函數,則輸出信號僅是一個簡單的線性函數。線性函數一個一級多項式,線性方程的複雜度有限,從數據中學習複雜函數映射的能力很小。沒有激活函數,神經網絡將無法學習和模擬其他複雜類型的數據,例如圖像、視頻、音頻、語音等。
  3. 使用非線性激活函數 ,以便使網絡更加強大,增加它的能力,使它可以學習複雜的事物,複雜的表單數據,以及表示輸入輸出之間非線性的複雜的任意函數映射。使用非線性激活函數,能夠從輸入輸出之間生成非線性映射。

8.如何選擇激活函數?

選擇一個適合的激活函數並不容易,需要考慮很多因素,通常的做法是,如果不確定哪一個激活函數效果更好,可以把它們都試試,然後在驗證集或者測試集上進行評價。然後看哪一種表現的更好,就去使用它。

以下是常見的選擇情況:

  1. 如果輸出是 0、1 值(二分類問題),則輸出層選擇 sigmoid 函數,然後其它的所有單元都選擇 Relu 函數。
  2. 如果在隱藏層上不確定使用哪個激活函數,那麼通常會使用 Relu 激活函數。有時,也會使用 tanh 激活函數,但 Relu
    的一個優點是:當是負值的時候,導數等於 0。
  3. sigmoid 激活函數:除了輸出層是一個二分類問題基本不會用它。
  4. tanh 激活函數:tanh 是非常優秀的,幾乎適合所有場合。
  5. ReLu 激活函數:最常用的默認函數,如果不確定用哪個激活函數,就使用 ReLu 或者 Leaky ReLu(GANs),再去嘗試其他的激活函數。如果遇到了一些死的神經元,我們可以使用 Leaky ReLU 函數。

9.池化層的作用和設置?

池化操作通常也叫做子採樣或降採樣,在構建卷積神經網絡時,往往會用在卷積層之後,通過池化來降低卷積層輸出的特徵維度,有效減少網絡參數的同時還可以防止過擬合現象。

池化操作可以降低圖像維度的原因,本質上是因爲圖像具有一種“靜態性”的屬性,這個意思是說在一個圖像區域有用的特徵極有可能在另一個區域同樣有用。因此,爲了描述一個大的圖像,很直觀的想法就是對不同位置的特徵進行聚合統計。例如,可以計算圖像在固定區域上特徵的平均值 (或最大值)來代表這個區域的特徵。

注意:但是池化層也不是越多越好,根據其原理可以發現,池化層增多在某種意義上會導致原始圖像信息的算是,就像平均和最大並不完全能代表整體。

10.全連接層的作用?

大多數神經網絡中高層網絡通常會採用全連接層(Full Connected Layer),通過多對多的連接方式對特徵進行全局彙總,可以有效地提取全局信息。但是全連接的方式需要大量的參數,是神經網絡中最佔資源的部分之一,因此可能具需要使用局部連接(Local Connected Layer),僅在局部區域範圍內產生神經元連接,能夠有效地減少參數量。

採坑未解決問題

1.爲什麼隨着網絡結構的加深,模型的性能爲什麼會提升過後降低?

2.對於網絡結構的建立,conv2d、BatchNorm2d、ReLU、MaxPooling等應該如何搭配?

3.CNN網絡結構中卷積核的大小,channel的熟練設置或分佈有什麼依據可言?
……
……
……

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章