卷積神經網絡模型解讀及數學原理 ——翻拍圖片識別

目錄

一、需求背景

二、知識儲備

1、深度學習

2、卷積神經網絡

3、PyTorch框架

4、張量

5、梯度下降法

三、模型解讀

1、輸入層

2、隱藏層

1)卷積層

2)激活函數

3)池化層

4)流向圖推演

5)線性層

3、輸出層

四、模型訓練

1、損失函數

2、優化方法

3、訓練過程

五、模型評估


前言:

本篇主要記錄在研究翻拍圖片識別程序源碼過程中的理論學習成果、對模型設計的解讀和其中的數學原理。由於程序代碼實現來自外部,在未經作者和公司允許的情況下,這裏不會貼出程序的源代碼。

         主要表述都是個人的想法和認識,避免摘抄文檔材料,可能會有偏差或錯誤,歡迎感興趣的同學一起討論研究。

一、需求背景

         此需求的提出是基於這樣一個業務場景:

         XX企業在提供售後服務如安裝、檢測、維修等上門服務時,服務人員需要使用終端將產品包含機編碼的部分拍照上傳系統,並且終端會在圖片上增加工單號、拍照時間和拍攝地址信息的水印。

在這個過程中,發現一種情況,存在部分服務人員沒有現場拍攝照片上傳,而是翻拍以前的或別人的照片上傳。

基於此場景,客戶提出希望實現系統自動識別出翻拍圖片。

         簡單分析需求可以得出,需要實現這樣一個算法程序:輸入爲一張圖片,經過算法模型處理,輸出爲一個分類(正常圖片, 翻拍圖片)。

         拿到樣本圖片後,瀏覽正常圖片和翻拍圖片,首先對分類特徵可以有一個直觀的認識,基於經驗,我們知道如果你對着電腦或手機屏幕翻拍圖片後,會發現照片上有水狀波紋(見下圖),這種波紋叫做莫爾條紋,它的產生是因爲屏幕刷新頻率低於手機的快門速度產生的。所以可以得出,識別翻拍圖片是可以有明顯統一特徵的。

圖片1

         這種特徵是人腦可以識別的,那麼機器又該如何識別呢?

         實踐中,深度學習在這一領域有成熟的應用,深度學習的模型有很多種,其中對於圖像識別效果最穩定的就是卷積神經網絡模型(CNN)。

二、知識儲備

這裏對相關知識做簡要說明,不做展開,如果對相關理論有興趣,可以自行查閱資料。

1、深度學習

深度學習是機器學習的一個方向,主要在三個領域廣泛應用:計算機視覺、聲音識別、自然語言處理。而機器學習的“學習”二字,在我看來,體現在其中的模型機制使模型自身具有可學習的特性,即訓練的次數和樣本越多,預測的結果就越準確。

深度學習基本上可以跟人工神經網絡掛鉤,因爲深度學習的概念就來自於對人工神經網絡的研究,其目的是模擬人腦的機制來解釋複雜數據並進行分析學習。

比如人看到一張牛的圖片立刻就能給它分類到牛這個類別中,這個過程中,人接受到的信息是這張圖片假設1024*1024個像素點,以及每個像素點上的顏色,通過這些像素點組合出一些低層次的特徵比如耳朵的形狀、牛角的形狀、頭的形狀、身體的花色、蹄子的形狀等等,在通過低層次的特徵抽象成高層次的屬性類別或特徵,最後歸爲一個認知。

當然人不可能出生就認識這是個牛,而是在長大後他可能看過實物、看過圖片、看過簡筆畫,然後被父母老師指出這就是牛(即監督角色,對訓練樣本打標籤),他甚至不需要被教授牛都有什麼特徵,而是在訓練的過程中就自然而然學習到了牛的各種特徵。

這就是深度學習的機制,通過大量的訓練,在學習的過程中通過不斷監督反饋,總結出各種分佈式低層次表徵,形成記憶和認知模式。當出現新的樣本時,就可以對其通過進行低層次特徵的識別,而形成更加抽象的高層次認知了,即準確預測。

在機器學習中,不論是分類問題還是迴歸問題,對最終結果的表述都稱爲預測,因爲在沒有人工確認之前,機器識別的結果都是一個概率的猜測,是有機率失真的,所以對分類問題的識別動作也稱爲預測。

深度學習的模型使用非循環的有序流向圖來表示,流向圖中的每一個節點表示一個基本計算併產生一個計算結果,計算的結果又被他的子節點所使用。因流向圖有一個重要的屬性,深度:從輸入到輸出的最長路徑的長度。所以被稱爲深度學習。

 

深度學習區別於傳統的淺層學習的特點:

  1. 強化了模型結構的深度,通常有幾層甚至幾十層的隱藏節點。
  2. 淺層學習是人工來構造特徵規則,即算法,雖然其參數可反饋優化,但學習程度受限於固定的特徵規則;而深度學習利用大數據來自我學習特徵(只提供訓練樣本的標籤),並且通過多層的特徵轉換,將樣本原空間的特徵變換到一個又一個新的特徵空間,形成一個多層又有聯繫的大特徵空間,在適應性和準確性方面都更優秀。

2、卷積神經網絡

         卷積神經網絡(CNN),也被稱作平移不變人工神經網絡,是深度學習的代表算法之一。如果說深度學習是模仿人腦的學習機制,那麼卷積神經網絡就是更具體的模仿大腦的視知覺機制來構建的。其特點是包含卷積計算,可以對多維數據進行平移不變的特徵提取,然後一層一層的對較小的特徵提取更大的特徵,最終總結爲模式識別或分類的認知。

建議學習一片博文,有精彩的說明:https://www.cnblogs.com/wj-1314/p/9754072.html

3、PyTorch框架

PyTorch是Facebook在深度學習框架Torch的基礎上使用Python重寫的一個全新的深度學習框架。PyTorch支持GPU計算,所以可以利用GPU並行加速計算;支持動態神經網絡,利用梯度下降法的反向求導技術,可以自動改變網絡的行爲;源碼簡潔直觀,提供很多高級功能,可以快速搭建神經網絡和進行訓練。

程序作者是使用Python編寫,使用PyTorch框架實現。本篇不涉及代碼實現,所以不需要了解框架,想在深度學習方向發展的同學可以自行學習,類似的框架還有Tensorflow、Keras、Theano、Caffe等等。

4、張量

張量是PyTorch和TensorFlow框架處理的核心數據類型,原始數據經過變形轉化爲張量類型的數據集合輸入模型中,張量可以是任意維度。其數學形式可以理解爲N維數組,框架中的張量作爲數據類型包含很多的對象函數和類方法方便使用。

單個數值稱爲標量。

向量的概念大多數人清楚,其表示一個既有長度又有方向的量,在座標系中用數組[a, b]作爲數學表示,這是二維空間向量,三個座標則是三維空間向量,更多的則是多維空間向量。這裏的維度是指代表的空間維度,其實不管什麼向量其實都是一維數組,也就是一維張量。

所以標量=零維張量,向量=一維張量,矩陣=二維張量。

張量的概念不過是對事物描述的高層次架構。

這裏插一句,我之前做過對驗證碼的識別,應用的是谷歌的Tesseract模型,基本原理是使用多維向量表示一個識別對象的特徵,如一個數字0的特徵使用50維向量表示,多維向量超越三維向量的空間想象,所以稱爲超立方體模型。其原理與卷積神經網絡相印證,就貫通了,超立方體模型不過是通過像素位置直接提取特徵映射到分類中,即只有一個神經網絡的線性層。

5、梯度下降法

         我們的主旨是應用,大家也不會想看梯度下降的公式是什麼。主要是理解梯度下降的概念、原理和作用。

         在模型訓練過程中,如何確定訓練的參數符合要求了呢?會通過使用一個損失(誤差/代價)函數,損失函數的目標是讓結果趨近於0。怎麼調整參數才能讓損失函數接近於0呢?其實就是讓計算機自己猜,但是不能隨便猜,不然哪裏知道什麼時候會猜對。這就要根據梯度去猜,梯度指的是這個點在函數的導數。

         導數我們回憶一下,高中教過,某個點導數大於0說明它周圍是單調遞增,導數小於0說明是單調遞減。如果是單調遞增,就把猜的數減小;如果單調遞減,就把猜的數增大。也就是說按導數相反的方向走,這是梯度下降法的原理。

舉個例子:假設損失函數是x平方。見下圖:

https://pic1.zhimg.com/80/v2-dd2f69abbfbc07b4bcf05d31a04fb76d_720w.jpg

圖片2

x平方的導數還記得吧:2x。x大於0時導數大於0,x小於0時導數小於0。所以計算機猜測x的值,初始值如果在第一象限,計算機就按梯度下降的原則一步一步向下走,最終接近損失函數的目標。

         對於多元函數就是求偏導數。到此看到二元偏導數時,我就放棄了。

不過對原理的直觀理解還是可以有的:想像一個山谷,你在山腰但是周圍都是大霧,只能看到有限的範圍,需要走到谷底,怎麼走?

         應用時,求導自然是計算機去做,甚至對於PyTorch深度學習框架,可以自動實現鏈式求導,從而使模型無延遲的通過反饋學習參數。

三、模型解讀

         完整的卷積神經網絡模型包含了輸入層、隱藏層和輸出層。

1、輸入層

         卷積神經網絡可以處理多維數據,得益於其模型的數據基本單元Tensor(張量)。所以輸入層的任務就是對原始數據(圖片、聲音、文字)進行預處理,轉換成多維度的張量,並進行標準化和歸一化處理,以便於模型計算。

 

         本篇模型的輸入層處理過程:

  1. 客戶端將圖片base64加密,在網絡傳輸中使圖片不直接可讀。
  2. 服務端接收數據後,對其進行base64解密,得到圖片數據。
  3. 將圖片數據利用OpenCV視覺庫轉換爲三維數組,即圖片的數學表示:二維像素點陣+RGB三原色通道(所以圖片天然就是一個三維張量,其數學表示不會丟失任何數據)。
  4. 對三維數組進行標準化,其實際意義爲對圖片大小進行標準化。如果圖片像素點不是512*512,就利用視覺庫對它進行縮放,這樣數組大小就標準化爲512*512*3。
  5. 每一個像素點的數學表示是三原色的值(範圍在0~255)的數組,如[ 17, 51, 127],但讀出來的顏色通道是反的,即BGR,所以需要轉換爲標準的RGB格式:如[127 , 51, 17]。
  6. 這時我們發現數組的結構並不是我們所想要的,因爲最內層是RGB的數值,上一層是圖片的寬度,相當於每次看到的是一條橫線的像素點+顏色,這對於圖像識別沒有意義。我們想要的是將一張圖片轉換R、G、B三個通道的的像素點陣,這樣才能對圖像的輪廓正確描述,就像一張宣紙揭成三張宣紙一樣,見下圖:

圖片3

  1. 所以,對數據進行矩陣轉置,變換成3*512*512的數組。
  2. 對於PyTorch框架來說,輸入數據的張量從外到內要設置四個維度,對於圖片就是(批量樣本數,通道數、高度、寬度),所以在最外層增加一個維度,我們每次輸入一個樣本,就轉換成1*3*512*512的數組。
  3. 然後對數組的數據進行歸一化處理,歸一化的目的是提高模型學習效率和表現。剛纔說到其中數值在0~255之間,我們需要歸一化到-1~1之間。方法是:首先對數組除以極差255,得到0~1的數值範圍,再-0.5,得到-0.5~0.5,最後除以0.5,得到    -1~1的數值範圍。
  4. 最後將四維數組轉化成四維張量(1,3,512,512),交給CNN隱藏層來處理就可以了。輸入層處理完成。

2、隱藏層

卷積神經網絡的隱藏層包含卷積層、激勵層、池化層和線性層(全連接層),其中激勵層和池化層的作用是對卷積層提取的特徵進行非線性映射和稀疏處理,所以不認爲是獨立的神經元層次。從下面的結構定義可以看出,本篇的CNN隱藏層共有7個神經元層次。

 

從源碼中打印此CNN隱藏層的結構定義:

ClassNet(

  (Block): Sequential(

    (0): Conv2d(3, 4, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))

    (1): ReLU()

(2): MaxPool2d(kernel_size=4, stride=4, padding=0, dilation=1, ceil_mode=False)

    (3): Conv2d(4, 8, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))

    (4): ReLU()

(5): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)

    (6): Conv2d(8, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))

    (7): ReLU()

(8): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)

    (9): Conv2d(16, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))

    (10): ReLU()

(11): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)

    (12): Conv2d(16, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))

    (13): ReLU()

(14): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)

    (15): Conv2d(16, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))

    (16): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)

    (17): ReLU()

    (18): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)

  )

  (classer): Sequential(

    (0): Dropout(p=0.5, inplace=False)

    (1): Linear(in_features=512, out_features=2, bias=True)

  )

)

隱藏層結構翻譯:

神經網絡

         特徵提取網絡

                   0:卷積層:輸入通道數3,輸出通道數4,卷積核大小3*3,邊界填充1*1

                   1:激活函數:修正線性單元函數

                   2:池化層:池化窗口大小4,移動步長4

                   3:卷積層:輸入通道數4,輸出通道數8,卷積核大小3*3,邊界填充1*1

                   4:激活函數:修正線性單元函數

                   5:池化層:池化窗口大小2,移動步長2

                   6:卷積層:輸入通道數8,輸出通道數16,卷積核大小3*3,邊界填充1*1

                   7:激活函數:修正線性單元函數

                   8:池化層:池化窗口大小2,移動步長2

                   9:卷積層:輸入通道數16,輸出通道數16,卷積核大小3*3,邊界填充1*1

                   10:激活函數:修正線性單元函數

                   11:池化層:池化窗口大小2,移動步長2

                   12:卷積層:輸入通道數16,輸出通道數16,卷積核大小3*3,邊界填充1*1

                   13:激活函數:修正線性單元函數

                   14:池化層:池化窗口大小2,移動步長2

                   15:卷積層:輸入通道數16,輸出通道數32,卷積核大小3*3,邊界填充1*1

                   16:批量標準化:輸入特徵數32,權重和偏置將被使用

                   17:激活函數:修正線性單元函數

                   18:池化層:池化窗口大小2,移動步長2

         特徵映射網絡

                   0:神經連接丟棄:隨機丟棄神經連接概率0.5,非特定位置丟棄

                   1:線性層:輸入特徵數512,輸出特徵數2,使用偏置

 

超參數的確定:

         在設計神經網絡模型時,首先需要確定網絡的層數和每層的節點數。

         關於網絡的層數,實際沒有什麼理論化的方法,基本就是根據經驗隨便拍一個,或者多嘗試幾個層數,哪個效果好就用哪個。我們知道的只是網絡層數越多模型效果越好,但反過來需要學習的參數就更多,模型訓練的難度就越大。因爲需要更多的訓練樣本和訓練次數,每次的計算量也需要更多才能達到理想的訓練效果。

         所以有人說深度學習是個手藝活,有些手藝很有技術含量,有些手藝真的讓人無語。

         輸入層的節點數是可以確定的,卷積神經網絡中就是通道數。

隱藏層的節點數基本還是靠經驗的,幾個到幾十萬個都有可能。不過卷積神經網絡遵循頭輕腳重的原則,下一層節點數一般是上一層的2倍或者相等。後面經過流向圖推演可以對這種原則有一定理解。

輸出層的節點數就是最終分類數。

 

下面對每一層逐個詳細解釋:

1)卷積層

         從結構定義中,卷積層和池化層都是2d可以看出本篇CNN模型是二維卷積模型。此外還有一維卷積和三維卷積,可以通過二維卷積的理解展開。

 

         下面重點解釋CNN的核心概念,卷積:

         假設神經網絡第一層有3個節點,如果一個樣本輸入的是4個值,那麼經典神經網絡每個節點就要設置4個權重參數;如果輸入的是512*512的矩陣,那這一層就要有512*512*3個參數。而我們說訓練神經網絡模型,讓它學習到數據的特徵,方式就是通過損失函數反饋使神經元優化調整這些參數,那麼當一個樣本數據量過大,計算量就會非常巨大。所以經典神經網絡對於圖像聲音等的處理是無能爲力的。

         而卷積神經網絡的模型更符合人類對事物的認知,即先對微小的局部有感知,然後對更大的範圍有感知,而逐步形成整體的認知。這種方式在模型中稱爲局部感受野,還是上面的例子,每個神經元我只開一個3*3大小的窗口,用這個窗口掃過整個圖片,得到的就是所有3*3大小局部的認知,因爲整幅圖片使用同一個窗口,也就是共享這些參數,所以這一層總共計算3*3*3個權重參數就可以了。

         這個窗口稱爲卷積核,由3*3個權重參數矩陣組成,卷積核相當於一個特徵過濾器,其內部的權重參數就是當前要匹配的特徵,用參數矩陣乘以圖片同等大小的矩陣得到的是這個局部的特徵匹配程度,當卷積核掃過整個圖片完成匹配的過程稱爲卷積計算。

 

 

         以第0卷積層爲例:

         輸入層輸入的是張量(1,3,512,512),即1個樣本有3個通道的512*512像素矩陣。通道可以理解爲神經網絡的節點,即輸入層有3個節點,每個節點掌握一個原色的像素矩陣並向下傳遞。

輸入通道數3,要與輸入層通道數相等。

輸出通道數4,代表這一層有4個節點,本層輸出的就是一個4通道張量,每個節點掌握其中一個通道。

卷積核3*3,即二維卷積核的大小。每個節點接收3個通道的矩陣,則需要3個卷積核作爲特徵來匹配,見下圖,就是其中一個節點的初始卷積核。

圖片4

對於一個節點的單通道計算來說,接收到512*512的矩陣數據,卷積核的9個參數在模型建立初始是隨機生成的,如何通過訓練反饋優化調整這些參數,後面在模型訓練的部分會講到。這些參數的值也會在-1~1之間,卷積計算時,卷積核與局部感受野做矩陣相乘,結果求和得到該區域匹配此特徵的程度。

此時細心的會發現,如果3*3的卷積核按步長1掃過512*512的數據時,得到是511*511的結果,有部分特徵丟失了。爲什麼會出現這種情況呢?因爲卷積核掃過的時候,所有的像素點都作爲卷積核中心點計算過了,除了邊界的那些,所以丟失的就是這部分數據的特徵。模型通過在邊界外填充數據的方法解決這個問題,即填充成513*513的矩陣,填充的值爲0,這裏的0注意不是表示沒有數,其實0是數據範圍的平均值,同時0作爲乘數又不影響計算,這樣既保留了邊界局部特徵,又不會對特徵計算造成影響。

         計算可得,本層需要學習的參數有(3*3卷積核*3輸入通道*4個節點)=108個,同時模型對於輸出通道也有權重參數,4個,共計112個參數。

         經過卷積計算,並且輸出通道爲4,所以生成張量(1,4,512,512),向下傳遞。

2)激活函數

         激活函數,顧名思義,其作用是設定一個閾值,將達到閾值的特徵激活後傳,沒達到閾值的特徵截留。類似於生物神經元傳遞信號的機制,刺激達到觸發條件纔會向後傳遞電信號。其數學意義在於將線性計算結果做非線性映射。我們的輸入數據是二維矩陣,卷積計算過程的函數是線性的,而模型最終的輸出結果卻是非線性的二元分類。所以每個卷積層後面都會添加激活函數這個非線性因素。

         卷積神經網絡常用激活函數是ReLU(修正線性單元函數),公式很簡單max(0,T),意思就是如果輸入是負值就輸出0,大於0則原樣輸出。

         激活函數對於神經網絡的意義,我認爲是過濾了不明顯的特徵,使之不再參與下層特徵值的計算。

         激活函數因爲加入了非線性因素,使模型的收斂速度更快,同時求梯度也非常簡單。

 

         以第1激活函數爲例:

ReLU的作用就是將卷積層計算得到的張量(1,4,512,512),其中的負值全部替換爲0.

激活函數層沒有學習參數。

3)池化層

         池化層的作用同樣是減少計算量,如果說激活函數是過濾了不明顯的特徵,那麼池化的作用就是在過濾後提取相對更重要的特徵。

         池化的處理很簡單,如果池化窗口是2*2,則取窗口中這4個數中最大的值作爲代表輸出,參與後面的計算。

         最大池化法保留每個窗口中的最大值,就相當於保留了這個區域的最佳特徵匹配結果,這符合人類認知過程,我不關心這個區域哪個像素更好的匹配了特徵,而只關心這個區域匹配特徵的程度。

         池化方法除了最大池化法,還有平均值池化法。

        

         以第2池化層爲例:

         最大池化法,池化窗口4*4,步長爲4,對於單個通道,掃過激活函數輸入的512*512個特徵值矩陣,對處於窗口的4*4個值,取最大值,作爲這16個特徵值的代表輸出。這樣經過池化層後得到是張量(1,4,128,128),交給下一層卷積層處理。

池化層沒有學習參數。

看後面的池化層,會發現池化窗口都是2*2,第一個池化層爲什麼是4*4呢?我認爲因爲第一層卷積計算的是3*3個像素,其能表示的特徵十分微小,所以前面的層完全可以擴大特徵提取範圍,減少後面的計算量。

 

卷積節點+激活函數+池化節點,我認爲是這個結構組成了卷積神經網絡中完整功能的神經元結構。個人理解的圖形表示:

圖片5

4)流向圖推演

         張量數據在流向圖中的變化類似於下圖(圖片來源於網上資料,對數字圖片0-9的識別):

https://static.oschina.net/uploads/space/2018/0210/003512_hpv5_876354.png

圖片6

         觀察此圖並推演特徵張量的變化,可以發現:每一個特徵矩陣在變小,但是特徵矩陣的層數(通道數)越來越多,最後在分類器中拉平爲特徵向量,映射到最終分類。

 

明白了上述三層的處理過程,就可以根據模型定義向後推演流向圖:

         第3卷積層:八個節點,輸入張量(1,4,128,128),輸出張量(1,8,128,128)。可學習參數3*3*4*8+8個。第一個卷積層輸出的每個特徵值代表3*3像素點的特徵,雖然這一層卷積核仍然是3*3,但是實際計算的像素點範圍擴大了,也就是局部感受野變大了,提取到的特徵層次更高,這有點間接選舉的意思。

         第4激活函數:張量(1,8,128,128)負值變爲0,後傳。

         第5池化層:池化窗口2*2,提取重要特徵,得到張量(1,8,64,64),後傳。

         第6卷積層:十六個節點,輸入張量(1,8,64,64),輸出張量(1,16,64,64)。可學習參數3*3*8*16+16個。

         第7激活函數:張量(1,16,64,64)負值變爲0,後傳。

         第8池化層:池化窗口2*2,提取重要特徵,變爲張量(1,16,32,32),後傳。

         第9卷積層:十六個節點,輸入張量(1,16,32,32),輸出張量(1,16,32,32)。可學習參數3*3*16*16+16個。

         第10激活函數:張量(1,16,32,32)負值變爲0,後傳。

         第11池化層:池化窗口2*2,提取重要特徵,變爲張量(1,16,16,16),後傳。

         第12卷積層:十六個節點,輸入張量(1,16,16,16),輸出張量(1,16,16,16)。可學習參數3*3*16*16+16個。

         第13激活函數:張量(1,16,16,16)負值變爲0,後傳。

         第14池化層:池化窗口2*2,提取重要特徵,變爲張量(1,16,8,8),後傳。

         第15卷積層:三十二個節點,輸入張量(1,16,8,8),輸出張量(1,32,8,8)。可學習參數3*3*16*32+32個。

         第16批量標準化:作用是避免卷積網絡中的梯度消失或爆炸,梯度影響模型的收斂速度,梯度變小時訓練次數會變多,梯度過大時,會難以得到最優解。經過多層卷積計算,如果大多數特徵值都接近於0,下一步的激活函數梯度就會消失,如果大多數值都接近-1和1,那麼激活函數的梯度會無限大。所以批量標準化通過減均值除以標準差的方法,調整輸入下層的數據爲均值0方差1的正態分佈。其中還有一個分母加極小數1e-05,並使用權重gamma和偏置beta,這兩個值是可學習的參數。

         第17激活函數:張量(1,32,8,8)負值變爲0,後傳。

         第18池化層:池化窗口2*2,提取重要特徵,變爲張量(1,32,4,4),後傳。

5)線性層

         卷積計算經過上面所有層次之後,單個通道的矩陣就只有4*4了,再對它進行卷積計算就是在大面積重複計算特徵,意義不大。這時候就應該進行最後一步,將計算得到的所有特徵映射到兩個最終特徵(正常圖片分類,翻拍圖片分類)。

         線性層,也叫做全連接層,即經典神經網絡的節點構型,一次性讀取輸入的全部數據,並對每一個數據增加權重參數。卷積神經網絡中的線性層,起到了最終分類器的作用,將計算特徵映射到最終分類上。

         解讀本篇的特徵映射網絡

                   0:神經連接丟棄:隨機丟棄神經連接概率0.5,非特定位置丟棄

                   1:線性層:輸入特徵數512,輸出特徵數2,使用偏置

         首先線性層是一次性讀取,不能讀取多維張量的結構,需要將張量(1,32,4,4)拉平,轉成一個32*4*4=512維度的向量。所以線性層設置輸入特徵數512,輸出特徵數就是最終的分類數2.

偏置:其中使用偏置是指不但每個特徵要有權重,還要加一個常數偏置項。增加偏置是爲了提高模型的擬合能力,提高靈活性。比如f(x)=ax這個函數無論參數是多少都必然是一條直線經過座標系原點,函數的位置被限制住了。所以一般都需要設置這樣一個偏置項來提供更多的擬合能力。

神經連接丟棄:Dropout這個配置項與偏置的作用不同,是爲了防止過擬合。此例中512個特徵值都要使用嗎?如果我認爲滿足所有特徵才能認定它的分類,那這個模型適用性就太差了。比如你認識一個人,不會因爲他帶了眼鏡、剪了頭髮、換了衣服就不認識了,甚至這次疫情中,大家都戴口罩,作爲最重要識別特徵的臉擋住了大部分,我們認識的依然認識。隨機丟棄概率0.5,就是對這512個特徵,線性層隨機丟棄其中一半的連接,使用剩下的一半特徵來分類。

3、輸出層

         隱藏層的線性層最終映射計算得出的是一個向量,如[0.9803, 0.0197],其中數值代表的是樣本屬於相應分類的概率或者說置信度。本例中第一個位置定義爲翻拍圖片,第二個位置是正常圖片,所以這個向量意思是CNN認爲這個樣本屬於翻拍圖片的概率是98%,屬於正常圖片的概率是2%。輸出層的工作就是找到所有概率中的最大值落在哪個分類,然後輸出模型的預測結果:預測這張圖片是翻拍圖片的分類及其置信度。

         模型的搭建完成。

四、模型訓練

         模型訓練部分的代碼我沒有拿到,只能根據參考資料和研究成果推測。

         模型搭建完成後不可能直接起作用,就像初生的嬰兒,是一張白紙。只有經過訓練,才能達到準確預測的目的。

         首先需要定義損失函數和優化方法。

1、損失函數

         損失函數的作用是計算模型輸出的預測結果與樣本實際標籤的誤差,在訓練時將誤差結果反饋到模型中,達到調優模型內參數的目的。

         Torch框架中有很多定義好的損失函數供使用,包括均方誤差函數、平均絕對誤差函數、交叉熵誤差函數等。

2、優化方法

         優化方法指的是選用什麼樣的算法對模型參數進行優化。前面說到的梯度下降法是所有優化器的基本方法,以損失函數爲初始,對模型參數鏈式求導。

         框架中優化是自動的,只需要選擇優化器就可以了,比如SGD、AdaGrad、RMSProp、Adam等。這些損失函數和優化算法,每一個都夠喝一壺的,就交給數學家吧,我們只要瞭解和應用就可以了。

         其次需要準備訓練集,訓練集包括各個分類的訓練樣本及其標籤。一般要求各個分類的樣本數量要均衡,樣本不均衡是採樣處理中要避免的問題,很好理解,比如樣本提供1000個正常圖片而只提供10個翻拍圖片,那這個模型訓練出來的效果就很值得懷疑了。

         假設準備了1000張正常圖片和1000張翻拍圖片。

3、訓練過程

         假設訓練100次,就設置批次循環100次。

         每批次取出訓練集所有樣本循環執行下列步驟:

  1. 對優化器的模型參數梯度歸零,如果參數梯度不歸零,那麼計算的梯度會一直累加,影響後續的計算。
  2. 讓樣本圖片經過CNN計算。
  3. 使用損失函數計算預測結果和實際標籤的誤差。
  4. 將誤差反饋到模型中,實現自動梯度更新。實現自動梯度的步驟可以理解爲:模型參數在模型按順序向前傳播過程中生成一張計算圖,根據這個計算圖和損失函數計算出每個參數的當前的梯度(框架中會自動完成這個求導過程),最後根據反饋的誤差值逆向傳播完成對梯度的更新。整個過程框架中只需要調用一個backward()函數。
  5. 優化器執行優化,即根據上一步更新的每一個參數的梯度按學習效率(步長)調整相應參數。

         最後將模型及其參數保存成文件就可以了。

 

         訓練樣本3批:

         正常圖片:90+189+467=746,翻拍圖片32+73+1807=1912:。

         模型訓練並不是一蹴而就的,需要根據訓練後模型的預測效果評估,來調整模型設計、訓練樣本、訓練次數和訓練方法等。

五、模型評估

         機器學習的模型評估方法都是通用的,主要包括分類問題和迴歸問題兩大類的方法。

         本例是分類問題,最常用的評估方法自然是準確率:

         準確率=正確預測的樣本數/總的樣本數

        

         測試集樣本提供了355張翻拍圖片和139張正常圖片。

         經模型測試,得到如下結果:

總數494,識別正確371,準確率75.10%

 

寫在最後:

         源碼來自於公司外部資源,拿到手將其測試、部署、改寫外部接口以供項目組使用,都沒有問題。然而我意識到這是真正進入深度學習領域一次難得的機會,將CNN模型算法的原理和應用掌握,纔是最有價值的事情。

         這個程序的python代碼,不過200行,但想要讀懂,首先要學習PyTorch深度學習框架,還有提供web服務的flask框架。在研究PyTorch的過程中,發現並不能理解:模型爲什麼這樣搭建、參數爲什麼這樣設置、如何實現了訓練和預測的能力,這些問題框架只是告訴你如何實現,但沒有爲什麼。於是又開始研究卷積神經網絡的理論和數學原理,甚至連微積分、線性代數都翻出來了。發現:數學,果然是自然科學的基石。

         目前爲止,對於深度學習,依然感覺是管中窺豹,需要繼續研究實踐。

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