1. 程式人生 > >CNN卷積神經網路基礎

CNN卷積神經網路基礎

轉自:http://www.sohu.com/a/138403426_470008

卷積神經網路基礎

神經網路

先借用 CNTK 的一個例子,來看看如何使用神經網路來進行分類。如果想根據一個人的年齡和年收入,對他的政治傾向進行分類(保守派,居中和自由派),怎麼做呢?答案是通過已知值,建立並訓練一個預測模型。該模型是某種函式,由兩個輸入產生一個結果,該結果能夠解釋他屬於哪個政治派別。

訓練和測試資料。輸入值 X1 和 X2 分別代表年齡和收入,三個顏色的點代表政治傾向型別。實心點代表訓練資料,空心點代表預測結果。本圖源自 MSDN 的 Machine Learning - Exploring the Microsoft CNTK Machine Learning Tool 一文。

基本的神經網路,本圖源自 MSDN 的 Machine Learning - Exploring the Microsoft CNTK Machine Learning Tool 一文。

這就可以用一個簡單的神經網路來解決:兩個輸入節點 (input nodes,分別代表年齡和收入) 和三個輸出節點 (output nodes 分別代表三個政治傾向的概率)。輸入(8.0, 3.0) 時, 輸出 (0.3090, 0.0055, 0.6854)。該網路還有 5 個隱藏節點 (hidden nodes)。每個節點用從 0 開始的編號來代表,比如 input[0] 是最靠左上角的節點,output2 是最右下角的。

中間的連線叫做權重(weights),比如,從 input[0] 到 hidden[0] 的權重為 2.41。計算隱藏節點的輸出值時,先將每個輸入的權重乘以所連的節點的值,將所有乘積疊加,並加上偏置量,再輸入隱含節點的啟用函式,即可得到輸出。

常見的隱藏層啟用函式包括 tanh(雙曲正切函式)、Sigmoid 和 ReLU。

常見的啟用函式:Sigmoid,雙曲正切和 ReLU,圖片源於 A Practical Introduction to Deep Learning with Caffe and Python 一文。

比如,圖中隱含層第三個節點 h[2]:

以此類推,可以算出所有隱藏層的輸出。最終輸出和隱藏節點的演算法類似,只是去掉了啟用函式,比如 output[0]:

我們希望得到不同結果的概率,因此將 output 輸入到 softmax 函式,進行轉換。

它會把一個由 N 個值組成的向量,“壓”成另一個 N 個值的向量。每個結果都在(0,1)之間,且總和為 1。同時,該函式能放大最大的值,讓大值影響更大,並削弱較小的值的作用。因此,Softmax 啟用函式常用於神經網路的最後一層,用來得到概率。

以此類推: output[1]=0.0055, output[2]=0.6854。output[2] 代表的概率最高,0.6854,因此對(8.0,3.0)的分類是“綠色”,即“自由派”。這些工作是由最後一層:全互聯層(Fully Connected Layer) 來完成。

用於影象識別的神經網路

影象由畫素組成,彩色影象包括 RGB(紅綠藍)分量,每個分量的輕重由灰度值表示。 因此,神經網路的輸入是 N 維陣列,長寬深,分別由 RGB 三個顏色分量組成。

圖片源於 http://xrds.acm.org/blog/2016/06/convolutional-neural-networks-cnns-illustrated-explanation/

我們希望通過神經網路後,得到一組數字,來描述每種結果的可能性。對肺癌影象而言,我們希望得到“陰性”和“陽性”這兩種情況的各自概率。

影象通過卷積神經網路的卷積層、啟用層、池化層、批量歸一化層和全互聯層(Fully Connected Layer)將產生上述結果。

感謝 *A beginner's guide to understanding convolutional Neural Networks* 一文

實際上,不需要通過卷積,也可以實現影象識別——只需要用樣本影象的二維陣列 + 標籤,訓練神經網路,也可以產生一樣的效果。資料量越大,效果越好。

為什麼要在“神經網路”前加“卷積”?

答案很簡單。如果要識別一個在圖片裡位置居中的手寫的“8”,用神經網路 + 一張 NVIDIA GTX 1080 就可以搞定,無需卷積。然而,同樣的“8”,如果位置不居中,在畫面的左上角、右下角或縮小 50% 等等,神經網路都會認為是完全不同的“8”。如果訓練資料沒有類似的位置和大小,就無法準確識別。

因此,我們在神經網路之前,加了一個重要環節:特徵提取。這就是卷積的重要功能之一:它將一個小過濾器(“神經元”或“卷積核”),比如圖案“8”,一步步地平移掃描整個影象。無論“8”的位置是在左上角,還是右上角,它都能找出來。卷積的結果就是“特徵”, 一個數字組成的陣列。

然後,再將特徵陣列,送到神經網路裡,讓神經網路對這個陣列進行判斷,而不是對影象本身判斷,結果就好得多。

卷積神經網路

卷積是兩個函式和的計算:將翻轉平移,和相乘後,做積分。得到。

兩個方形脈衝 f 和 g 的卷積。g 先對 τ = 0 反轉,接著平移"t",成為 g(t-τ)。重疊部分的面積 (黑色實線),即為"t"處的卷積。橫座標為 τ及 f*g 的自變數"t"。

方形脈衝和指數衰退脈衝的卷積。重疊部分面積 (黑色實線)即為處的卷積。

對於離散的矩陣 A 和 B,卷積也是一樣的:先將矩陣 B 翻轉,再平移, 每個元素和矩陣 A 相應的位置的元素相乘後的總和,即得出該位置的卷積。

5x5 的綠色矩陣 A 和 3x3 的矩陣 B 卷積,得出粉紅色矩陣 C。矩陣 B 每滑動一步,和矩陣 A 的 [點積][14] 就是該位置的卷積值。

如前所述,如果矩陣 A 是輸入的影象。矩陣 B 是過濾器。通過卷積運算,能將各種圖案特徵分析出來,比如弧線、邊緣、色塊等等,得到一個較小的矩陣,叫做啟用地圖(activation map)。 舉一個過濾器為例:

比如,要分析出一段長弧線,(本圖來自 A beginner's guide to understanding convolutional Neural Networks 一文)

用第一個矩陣是原影象,第二個矩陣為過濾器(或卷積核),兩者卷積結果——啟用地圖上在弧線位置的值較大:6600,而在其他沒有這樣大弧線的位置,卷積值較小。(本圖來自 A beginner's guide to understanding convolutional Neural Networks 一文)

實際用於影象分析的卷積是三維的,請見下圖。比如,彩色影象包括 RGB 三種色彩,因此,輸入除了長、寬兩個維度之外,還有厚度(“3”)。因此要檢測某種圖案特徵,卷積核或過濾器實際上是三維的,如圖中的粉紅色方塊。

這僅僅是一種影象特徵的過濾器,而更多的特徵還需要更多的過濾器。最終的啟用地圖是將多個過濾器的卷積結果沿厚度方向“疊”起來,因此用了多少個過濾器,其結果(啟用地圖)的“厚度”就是多少。

由 RGB 三個顏色通道組成的三層影象(第一個淺藍方塊體),與粉紅色的 3 維過濾器(厚度同樣為 3)卷積後,得到一個面。用 96 個不同的過濾器卷積,得到 96 層,即厚度為 96。這 96 個過濾器分別檢測不同特徵。

那麼這些過濾器裡的值怎麼確定,是按經驗值或前人的試驗來設定的嗎? 不是,是機器自己“琢磨”出來的,換句話說,是神經網路訓練出來的,過程如下,圖片源於 Machine Learning is Fun!:

上圖中第二步得到啟用地圖。通過啟用層,比如用 ReLU 作為啟用函式,將啟用地圖上所有負數將變為零,正數將不變。

再通過池化層,將特徵地圖的空間尺寸逐漸縮小,以便減少網路裡的引數和計算量,並控制過擬合。池化層對輸入矩陣沿厚度方向的每個切片進行操作,求最大值或平均值來調整其空間大小。

最常見一種池化層是用 2x2 的 Max-Pooling 過濾器。

池化層在空間上縮減樣本,在厚度方向保持不變。 左圖:通過尺寸為 2、步長為 2 的過濾器,將尺寸 224x224x64 縮減為 112x112x64,而厚度方向尺寸不變。右圖:最常用的縮減運算是“最大值”,即求出 2x2 格子(同樣顏色)裡的最大值,然後右移 2 格(步長為 2)。

第五步:將第四步輸出的“特徵”輸入另一個神經網路,進行分類。該層叫做“全互聯層”。

實際的神經網路會由多個卷積層和池化層組成。每個卷積層實際會用 N 個不同過濾器,得到 N 個結果,疊起來形成厚度 N。比如第一層卷積會用 96 個檢測不同特徵的過濾器,因此厚度為 96. 此例將 224x224x3(RGB 三色)的影象經過兩次卷積 + 池化,再經過 3 次卷積,一次池化,和兩個全互聯層(即 dense layer),得到最終的 1000 種分類。

一個卷積神經網路裡,可以由多個卷積層和池化層組成。每層如何決定權重,完全由訓練產生,沒有人工干預。不過,有人逐層分析已經訓練好的神經網路,發現前面的卷積層尋找的是簡單的特徵,比如邊緣或曲線。而後面的卷積層尋找的是人臉、皺紋等更高階的特徵。

最後,將後面得到的高階特徵,輸入另一個全互聯神經網路層和 SoftMax 函式,即可獲得一組輸出值:比如每種分類標籤的概率。後面的肺癌 CT 識別的案例裡,正是借用了 ImageNet 用來進行影象分類的 ResNet-157 模型,將全互聯層的輸入,轉接到 LightGBM。利用已訓練好的 ResNet-157 計算 CT 影象的特徵值, 並用這些特徵值和標籤訓練 LightGBM 的神經網路,並實現對肺癌 CT 的識別。

訓練神經網路

前面提到,所有過濾器的值都是通過訓練獲得,哪些是肺癌的特徵?是機器自己“琢磨”出來的,那麼,到底是怎麼算出來的呢? 答案是,通過用一組已知的圖片和各自對應的標籤(Label) 來訓練神經網路。 訓練過程將逐漸調整各個過濾器的每個值(或權重),也稱之為反向傳播(Back propogation)。反向傳播包括四個計算步驟:前向傳導(forward pass)、損失函式 (loss function)、後向傳導 (backward pass) 和權重更新(weight update)。

先將所有過濾器和權重設為任意數。前向傳導是將樣本影象輸入神經網路,按上面提到的辦法計算得到輸出。因為在訓練階段知道正確的樣本影象分類結果,所以可以算出計算結果和正確結果之間的差距, 記為“L”,比如用均方差 MSE 作為 L,這就是一種損失函式。可以想象,第一次用任意數初始化,得到的 L 會很大,要逐漸減小 L,需要先找到不同權重"W"對 L 的影響,即求 dL/dW。結果越大,代表影響越大,調整也應該越大;結果為零,則代表該權重對 L 沒影響,無需調整。後向傳導就是求 dL/dW。之後,再將第一輪的權重更新成新的權重:

其中,η是學習速度(learning rate),w 是新的權重,wi 是前一輪的權重。η由使用者自己選擇,值越高,則每次變化越大,有可能更快地得到最優結果,但如果過大,也可能得不到最佳結果。整個反向傳播的過程,包括上述四個部分,稱作一個“迴圈(epoch)"。為了利用平行計算來縮短時間,並能更順利地收斂,先將每 n 個訓練樣本編成一個“小批次”(mini-batch),對每個小批次反覆 epoch 迴圈中的 4 個步驟,並更新權重,直到最後的 m 次迴圈的得分不再提升時結束。下面肺癌的例子中,對 lightGBM 迴歸樹訓練的“early_stop_ping_round=300”,即 m=300。

注意,每次更新權重時,dL/dW = {同一個小批裡 n 個訓練樣本的 dL/dW 的平均值}。有時候用完樣本資料後,得分可能還是不收斂,就要將樣本資料重新排序(shuffle),取另一套測試資料,繼續訓練。

防止過擬合

如何避免過擬合是機器學習裡非常重要的考慮因素。如果權重和偏置量(Bias) 過於“貼近”訓練資料,很可能造成模型對新資料不夠適應,實際運用時產生很糟糕的效果。更確切地說,如果訓練所用的資料少,又追求儘可能擬合絕大多數資料,那麼很可能擬合了訓練資料裡的“噪音”或異常值,弄得模型敏感而複雜,因此,最糟糕的訓練是僅用一套資料訓練所有節點。後面提到的 Early_stop_ping_round,L1 和 L2,交叉驗證,及剔除(Dropout)都是避免過擬合的措施。

剔除(Dropout)

剔除能夠在訓練階段快速檢驗是否過擬合。如果模型沒有問題,那麼將神經網路裡的部分節點去掉,也應該產生正確的結果。

神經網路的剔除 左圖:帶有兩個隱藏層的神經網路; 右圖:經過剔除的一個子網路。叉代表被剔除的隱藏和輸入節點; 圖片源於 Dropout: A Simple Way to Prevent Neural Network from Overfitting。

採用剔除時,每個子網路的每個輸入節點和隱藏節點是否出現,由概率 p 隨機決定連線。被剔除的節點權重也剔除掉,如上圖的右圖 (b) 所示。一般來說,將保留大部分輸入節點和部分隱藏節點(比如 50%)。

舉一篇關於剔除的經典論文 Dropout: A Simple Way to Prevent Neural Network from Overfitting 裡所採用的的剔除為例:未使用剔除時,訓練過程的每個小批次(mini-batch) 裡的 n 個影象樣本所訓練的都是同樣的一個網路,如上圖 (a)。而採用剔除時,每個訓練樣本都對應一個不同的經隨機剔除的子網路,如上圖(b)。因此,每個小批次中的 n 個影象樣本,將分別對應 n 個子網路,而每次 epoch 迴圈更新權重 w 時,用的是 n 個的平均值。

驗證時,不再剔除,而是用完整的網路,每個權重等於訓練結果中的權重與相應概率的乘積,即(p* 訓練權重 w),如下圖。

從訓練到最終的網路 左圖:在訓練階段,每個輸入和隱藏節點存在的概率為 p,和下層網路的連線權重為 w; 右圖:在驗證階段,每個節點都保留,權重是 p 和 w 的乘積,模型的輸出是訓練階段所有輸出的期望值; 圖片源於 Dropout: A Simple Way to Prevent Neural Network from Overfitting。

交叉驗證

如何保證模型在新的資料下,仍有較好表現?一般會將所有樣本資料的一部分預留起來,用剩下的訓練模型。等訓練結束後,再用預留的資料驗證,看真實效果如何。這是避免過擬合的重要措施。

但,這樣做,使得用於訓練模型的資料少了,且選擇哪部分資料用於訓練,哪部分用於驗證,也可能影響效果。交叉驗證是個解決方案。比如以 K 折交叉(K-fold cross validation) 驗證為例:將樣本資料分成 K 份,先選一份(A)作為驗證資料,預留起來。用剩下的 K-1 份訓練網路,再用預留的那份(A)做驗證。

然後,再另選一份作為驗證資料(B),同樣重複上述步驟,用剩下的 K-1 份訓練,並用 B 做驗證。以此類推,K 次之後,所有的資料都做過驗證資料。最終的驗證得分是 K 次驗證得分的平均。

用 scikit-learn 的 train_test_split 函式可以很容易地按某個百分比,將資料拆分成訓練和驗證的兩部分。用 cross_val_score(clf,x_data,y_label,cv=num_K_fold) 可以很容易地用設定好的分類器 clf,進行折數為 num_K_fold 的 K 折交叉驗證。

肺癌 CT 影像識別

微軟的 Miguel Fierro, Ye Xing, Tao Wu 等人在 2017 年 1 月 Kaggle 上的“資料科學肺癌檢測競賽”裡,在60 分鐘,利用已訓練好的卷積神經網路 ResNet-157 提取 CT 影象的特徵,並訓練提升樹(boosted tree),以識別肺癌 CT 影像是癌症陰性或陽性。他們獲得了不錯的成績——1 月 19 日之前排名位前 10%,2 月 7 日之前,居前 20%。

所用到的工具包括:

  1. 特徵提取:已訓練好的卷積神經網路——一個用 CNTK 開發的 152 層 ResNet 模型,用 ImageNet 的影象資料集進行的訓練;

  2. 影象分類:LightGBM 灰度提升框架;

  3. 帶 GPU 加速的 Azure 虛機;

具體程式碼請見 Jupyter notebook 裡的筆記。用 CNTK 和 ResNet-157 計算特徵用了 53 分鐘(如果用更簡單的 18 層 ResNet 模型,需 29 分鐘),訓練 LightGBM 用了 6 分鐘。程式碼請見 Kaggle。

訓練速度對獲獎來說非常重要。CNTK 和 LightGBM,加上 Azure 的高效能 GPU 虛機,為他們按需提供高效能運算環境,效果很好。下面,我們具體看看他們怎麼做的。

用 ResNet 模型、CNTK 和 LightGBM 實施影象識別

深度學習的一種較新的辦法是用已訓練好的卷積神經網路作為基礎,利用已經訓練好的模型、權重來加快速度。這也是該團隊所採用的方法。他們用 ImageNet 已訓練好的卷積神經網路 ResNet-152 作為基礎,來提取影象特徵,然後將特徵輸入 LightGBM 灰度提升樹框架(包括了 GBDT,GBRT,GBM,MART 等),來進行訓練和分類。

該模型的前面幾層會提取基本的特徵,比如色塊、弧線等。後面的層會識別更高層次的特徵,比如結節等,更後面的層再進一步識別更復雜的特徵,比如和惡性結節等肺癌特徵更加貼近的特徵。

讓我們先看看 ImageNet 如何用卷積神經網路進行影象分類,見上圖。輸入是 224x224 的彩色影象,每個影象包括 RGB 三個色彩分量,記為 224x224x3。每個卷積層進行卷積計算,用多個厚度為 3 的過濾器,提取各種影象特徵,因此,每層的輸出的厚度隨著過濾器的數量增加而變厚。

最後,由池化 +SoftMax 函式組成的分類器將輸出一組由 1000 種概率組成的向量(最後的一組黑色小圈),對應於 ImageNet 的 1000 種不同影象分類。該概率向量中,哪個分類的概率最高,就是識別結果。比如上圖中用貓照片輸入 ResNet,經過每層卷積計算後,圖片大小變小,厚度增加,直到最後的判斷結果,即圖中第二個小黑點的概率值最高,即識別結果:“虎斑貓”。

用已訓練好的 ImageNet 的 ResNet-152 模型輸出特徵,輸入到 LightGBM 中進行分類。

為了借用 ImageNet 的特徵提取,來實現肺癌影象分類,先將由池化 +SoftMax 函式組成的分類器去掉,而將圖中的"penultimate layer"的節點的輸出作為 LightGBM 分類器的輸入。 同時,每個患者的 CT 套圖是黑白的,所以要先像 ImageNet 的 RBG 樣本那樣,裁切到 224x224 大小,三張一組。分成 K 批輸入前面提到的已訓練的神經網路,計算到“pentimate layer”為止。該過程用 CNTK 執行。將輸出結果輸入灰度提升樹,用 LightGBM 分類。

LightGBM 是微軟 DMTK 框架的一部分,將灰度提升樹用於分散式叢集上,以達到更快的速度,而且隨著節點數增加,可以成比例地提高計算效能。據好事者測,比 XGBoost 快 10 倍,記憶體使用稍微少些。作為微軟 AI 的兩大利器,DMTK(Distributed Machine Learning Toolkit)主要優勢是分散式,而非深度學習。CNTK 的優勢在於深度學習,所以這兩種常常一起用。

ResNet

為什麼要用 ImageNet 的 ResNet-152 模型? ResNet 是微軟亞洲研究院 Kaiming He 等人提出的。傳統神經網路層數較多時,優化比較困難,因此擬合不夠。而且如果僅僅增加層數,得到的訓練誤差和實驗誤差可能更高。而 ResNet 收斂更快,更容易訓練,層數也可以更多,誤差更低。比如,在 2015 年 ResNet 一戰成名的 ILSVRC 比賽中,它囊括 ImageNet 和 COCO 的影象分類、物體檢測等五項比賽冠軍。2014 年冠軍用的是 GoogleNet 的 22 層網路,而 2015 年的冠軍 ResNet 有 152 層,將影象分類的誤差從 6.7% 縮減到 3.57%,而物體檢測 mAP 指標從 2014 年 16 層 VGG 的 66%,提升到 101 層 ResNet 的 86%。下圖是 2016 年 10 月 25 日為止,由 Eugenio Culurciello 發表的,對 AlexNet, VGG 和 ResNet 的比較。

步驟