深度學習中的動手實踐:在CIFAR-10上進行圖像分類

你想開始進行深度學習嗎? 這有一篇關於Keras的深度學習的文章(地址見下方鏈接),對圖像分類的神經網路做了一個總體概述。然而,它缺少一個關鍵的因素——實際的動手練習。本文將試圖填補這一空白。

  • 文章:p.migdal.pl/2017/04/30/

實用性的深度學習

深度學習有一個骯髒的秘密——不管你知道多少,總會有很多反覆的嘗試和錯誤。你需要測試各種網路體系架構、數據預處理方法、參數和優化器等等。即使是頂尖的深度學習專家,也不能只寫一個神經網路程序,運行它,並在一天內調用它。

每次你看到一個最先進的神經網路,然後問自己「為什麼這裡會有6個卷積層?」或者「為什麼他們會把dropout率提高到0.3?」答案是,他們嘗試了各種各樣的參數,並選擇了他們在經驗基礎上所做的那個。然而,對其他解決方案的了解確實給我們提供了一個很好的起點。理論知識建立了一種直觀的看法,即哪些想法是值得嘗試的,哪些想法是不可能改善神經網路的。

解決任何深度學習問題的一個相當普遍的方法是:

  • 對於給定的一類問題,使用一些最先進的體系架構。
  • 修改它以優化你的特定問題的性能。

修改既包括更改其架構(例如,層數、添加或刪除輔助層,如Dropout或Batch Normalization)和調優其參數。唯一重要的性能指標是驗證分數(validation score),也就是說,如果在一個數據集上訓練的一個網路能夠對它從未遇到過的新數據做出良好的預測,其他的一切都歸結為實驗和調整。

一個良好的數據集——用於圖像分類的CIFAR-10

許多關於深度學習的圖像分類的介紹都是從MNIST開始的,MNIST是一個手寫數字的標準數據集。它不僅不會產生令人感嘆的效果或展示深度學習的優點,而且它也可以用淺層機器學習技術解決。在這種情況下,普通的K近鄰(KNN)演算法會產生超過97%的精度(甚至在數據預處理的情況下達到99.5%)。此外,MNIST並不是一個典型的圖像數據集——控制它不太可能教給你可遷移的技能,而這些技能對於其他分類問題是有用的。

如果你真的需要使用28×28灰度圖像數據集,那麼可以看看notMNIST數據集和一個MNIST-like fashion product數據集(一個非常有趣的數據集,也是10分類問題,不過是時尚相關的)。

  • notMNIST數據集:yaroslavvb.blogspot.com
  • MNIST-like fashion product數據集:github.com/zalandoresea

然而,我認為沒有任何理由可以避免使用真實的照片。

我們將在CIFAR-10上工作,這是一個經典的小彩色圖像集。60000個32×32彩色圖像,10個類,每個類有6000個圖像。有50000個訓練圖像(也就是我們用來訓練神經網路的那個)和10000個測試圖像。

  • CIFAR-10:cs.toronto.edu/~kriz/ci

看一下這些樣本圖片:

帶有示例圖像的CIFAR-10類

動手實踐

在開始之前:

  • 創建一個Neptune賬戶,創建地址? neptune.ml/
  • 克隆或複製github.com/neptune-ml/h;我們使用的所有腳本都需要從cifar_image_classification目錄中運行。
  • 在Neptune上,點擊項目,創建一個新的CIFAR-10(使用代碼:CIF)。

代碼在Keras中,地址? keras.io/

我們將使用Python 3和TensorFlow後端。該代碼中唯一的特定於Neptune的部分是logging。如果你想在另一個基礎設施上運行它,只需更改幾行。

架構和塊(在Keras中)

將深度學習與經典機器學習區別開來的是它的組合架構。我們不再使用one-class分類器(即邏輯回歸、隨機森林或XGBoost),而是創建一個由塊(稱為層)構成的網路。

深度學習隱喻:將ConvNet層比作Jenga塊

邏輯回歸

讓我們從一個簡單的「多類邏輯回歸」開始。它是一種「淺層」的機器學習技術,但可以用神經網路語言表達。它的體系架構只包含一個有意義的層。在Keras,我們寫如下:

1model= Sequential()

2

3model.add(Flatten(input_shape=(32,32,3)))

4model.add(Dense(10))

5model.add(Activation(softmax))

6

7model.compile(optimizer=』adam』,

8 loss=categorical_crossentropy,

9 metrics=[accuracy])

如果我們想一步一步地看到數據流的變化,關於維度和要優化的權重的數量,我們可以使用一個keras-sequential-ascii腳本:

  • 腳本地址:github.com/stared/keras

1OPERATION DATA DIMENSIONS WEIGHTS(N) WEIGHTS(%)

2

3 Input ##### 32 32 3

4 Flatten |||||------------------- 0 0.0%

5 ##### 3072

6 Dense XXXXX------------------- 30730 100.0%

7 softmax ##### 10

Flatten層只是將(x, y, channels)轉換為像素值的flat向量。密集層將所有輸入連接到所有的輸出。然後,Softmax將實數轉化為概率。

要運行它,只需輸入終端:

1$ neptune send lr.py--environment keras-2.0-gpu-py3--worker gcp-gpu-medium

這將打開一個瀏覽器選項卡,在這個選項卡中你可以跟蹤訓練過程。你甚至可以查看錯誤分類的圖片。然而,這個線性模型主要是在圖像上尋找顏色和它們的位置。

Neptune通道儀錶盤中顯示的錯誤分類的圖像

整體得分並不令人印象深刻。我在訓練集上的準確率達到了41%,更重要的是,37%的準確率在驗證上。請注意,10%是進行隨機猜測的基線。

多層感知器

老式的神經網路由幾個密集的層組成。在層之間,我們需要使用一個激活函數。該函數分別應用於每個組件,使我們可以使其非線性,使用比邏輯回歸更複雜的模式。之前的方法(由生物神經網路的抽象所激發)使用了一個S函數。

01model= Sequential()

02

03model.add(Flatten(input_shape=(32,32,3)))

04model.add(Dense(128, activation=sigmoid))

05model.add(Dense(128, activation=sigmoid))

06model.add(Dense(10))

07model.add(Activation(softmax))

08

09model.compile(optimizer=adam,

10 loss=categorical_crossentropy,

11 metrics=[accuracy])

這對我們的數據意味著什麼?

01OPERATION DATA DIMENSIONS WEIGHTS(N) WEIGHTS(%)

02

03 Input ##### 32 32 3

04 Flatten |||||------------------- 0 0.0%

05 ##### 3072

06 Dense XXXXX------------------- 393344 95.7%

07 sigmoid ##### 128

08 Dense XXXXX------------------- 16512 4.0%

09 sigmoid ##### 128

10 Dense XXXXX------------------- 1290 0.3%

11 softmax ##### 10

我們使用了兩個額外的(所謂的隱藏的)層,每個層都帶有S函數作為其激活函數。讓我們來運行它!

1$ neptune send mlp.py--environment keras-2.0-gpu-py3--worker gcp-gpu-medium

我建議在一個繪圖上創建一個結合訓練和驗證通道(validation channels)的自定義圖表。

訓練集和驗證集的準確性和log-loss

原則上,即使有一個隱藏的層,也可以近似任何函數 (參見:萬能近似定理,universal approximation theorem)。然而,這並不意味著它在實踐中工作得很好,因為數據量十分有限。如果隱藏層太小,它就無法近似任何函數。當它變得太大時,網路很容易就會變得過度擬合——也就是記憶訓練數據,但不能概括為其他圖像。任何時候,你的訓練分數都會以驗證分數的成本上升,然後你的網路就會變得不過度擬合。

我們可以在驗證集上獲得大約45%的準確率,這是對邏輯回歸的改進。不過,我們可以做得更好。如果你想要使用這種網路——編輯文件,運行它(我建議在命令行中添加——tags my-experiment),看看你是否能做得更好。採取一些方法,看看結果如何。

提示:

  • 使用20個以上的epoch。
  • 在實踐中,神經網路使用2-3個密集層。
  • 做大的改變來看看區別。在這種情況下,將隱藏層的大小更改為2x,甚至是10x。

僅僅因為理論上你應該能夠用畫圖的方式來創建任何圖片(或者甚至是任何照片),這並不意味著它將在實踐中起作用。我們需要利用空間結構,並使用卷積神經網路(CNN)。

卷積神經網路

我們可以用更智能的方式處理圖像,而不是試圖把所有東西都連接起來。卷積是在圖像的每個部分執行相同的局部操作的操作。卷積可以做的一些例子包括模糊,放大邊緣或者檢測顏色梯度。參見:setosa.io/ev/image-kern

每一個卷積層都根據之前的內容產生新的通道。首先,我們從紅色、綠色和藍色(RGB)組件的三個通道開始。接下來,通道變得越來越抽象。

當我們創建表示圖像的各種屬性的通道時,我們需要降低解析度(通常使用max-pooling)。此外,現代網路通常使用ReLU作為激活功能,因為它對更深層的模型效果更好。

01model= Sequential()

02

03model.add(Conv2D(32, (3,3), activation=relu,

04 input_shape=(32,32,3)))

05model.add(MaxPool2D())

06

07model.add(Conv2D(64, (3,3), activation=relu))

08model.add(MaxPool2D())

09

10model.add(Flatten())

11model.add(Dense(10))

12model.add(Activation(softmax))

13

14model.compile(optimizer=adam,

15 loss=categorical_crossentropy,

16 metrics=[accuracy])

網路架構是這樣的:

01OPERATION DATA DIMENSIONS WEIGHTS(N) WEIGHTS(%)

02

03 Input ##### 32 32 3

04 Conv2D |/ ------------------- 896 2.1%

05 relu ##### 30 30 32

06 MaxPooling2D Ymax ------------------- 0 0.0%

07 ##### 15 15 32

08 Conv2D |/ ------------------- 18496 43.6%

09 relu ##### 13 13 64

10 MaxPooling2D Ymax ------------------- 0 0.0%

11 ##### 6 6 64

12 Flatten |||||------------------- 0 0.0%

13 ##### 2304

14 Dense XXXXX------------------- 23050 54.3%

15 softmax ##### 10

要運行它,我們需要輸入:

1$ neptune send cnn_simple.py--environment keras-2.0-gpu-py3--worker gcp-gpu-medium

即使使用這個簡單的神經網路,我們在驗證上的準確率也達到了70%。這比我們用邏輯回歸或者多層感知器產生的結果要多得多!

現在,你可以自由地進行實驗。

提示:

  • 一般來說,3×3卷積是最好的;堅持使用它們(和只使用混合通道的1×1卷積)。
  • 在進行每個MaxPool操作之前,你要有1-3個卷積層。
  • 添加一個密集層可能會有所幫助。
  • 在密集層之間,你可以使用Dropout,以減少過度擬合(例如,如果你發現訓練的準確性高於驗證的準確性)。

這僅僅是個開始。

要比較結果,請單擊項目名稱(project name)。你將看到整個項目列表。在Manage columns中,記錄所有的accuracy score(以及可能的log-loss)。你可以使用驗證精度(validation accuracy)來整理你的結果。

除了架構(這是一個大問題),優化器還會顯著地改變總體結果的準確性。通常情況下,我們通過添加更多的epoch(即整個訓練數據集的次數)來獲得更好的結果,同時降低學習率(learning rate)。

例如,試試這個網路:

01OPERATION DATA DIMENSIONS WEIGHTS(N) WEIGHTS(%)

02

03 Input ##### 32 32 3

04 Conv2D |/ ------------------- 896 0.1%

05 relu ##### 32 32 32

06 Conv2D |/ ------------------- 1056 0.2%

07 relu ##### 32 32 32

08 MaxPooling2D Ymax ------------------- 0 0.0%

09 ##### 16 16 32

10 BatchNormalization μ|σ ------------------- 128 0.0%

11 ##### 16 16 32

12 Dropout | ||------------------- 0 0.0%

13 ##### 16 16 32

14 Conv2D |/ ------------------- 18496 2.9%

15 relu ##### 16 16 64

16 Conv2D |/ ------------------- 4160 0.6%

17 relu ##### 16 16 64

18 MaxPooling2D Ymax ------------------- 0 0.0%

19 ##### 8 8 64

20 BatchNormalization μ|σ ------------------- 256 0.0%

21 ##### 8 8 64

22 Dropout | ||------------------- 0 0.0%

23 ##### 8 8 64

24 Conv2D |/ ------------------- 73856 11.5%

25 relu ##### 8 8 128

26 Conv2D |/ ------------------- 16512 2.6%

27 relu ##### 8 8 128

28 MaxPooling2D Ymax ------------------- 0 0.0%

29 ##### 4 4 128

30 BatchNormalization μ|σ ------------------- 512 0.1%

31 ##### 4 4 128

32 Dropout | ||------------------- 0 0.0%

33 ##### 4 4 128

34 Flatten |||||------------------- 0 0.0%

35 ##### 2048

36 Dense XXXXX------------------- 524544 81.6%

37 relu ##### 256

38 Dropout | ||------------------- 0 0.0%

39 ##### 256

40 Dense XXXXX------------------- 2570 0.4%

41 softmax ##### 10

1$ neptune send cnn_adv.py--environment keras-2.0-gpu-py3--worker gcp-gpu-medium

這個過程需要大約半個小時,但是結果會更好—驗證的準確性應該在83%左右!

本文為atyun編譯,轉載請註明出處。更多內容關注微信公眾號atyun_com;訪問網站atyun.com;或加資源群:213252181


推薦閱讀:

TAG:深度學習DeepLearning | 分類 | 人工智慧 |