火炬中 92.45% CIFAR-10
完整程式碼可在 https://github.com/szagoruyko/cifar.torch 取得,只要複製到你的機器就可以開始玩了。
CIFAR-10 包含 60,000 個標註為 10 個類別的 32x32 尺寸影像,訓練集有 50,000 個,測試集有 10,000 個。Kaggle 上有相關競賽:https://www.kaggle.com/c/cifar-10這裡有有點過時的技術水準結果表格:http://rodrigob.github.io/are_we_there_yet/build/classification_datasets_results.html
依據今日的標準,該資料集相當小,但對於機器學習演算法來說,仍然是很好的訓練場域。技術水準當然屬於深度卷積神經網路,然而,很難定義哪一種深度技術最好。如果你沒有做任何裁剪、仿射變形或整體,僅做水平翻轉,我會說 92.45% 是最好的結果。有趣的是,人類表現約為 94%,若要超越此水準,必須使用大量的資料擴充。查看 @nagadomi 在 24x24 裁剪上的訓練程式碼:https://github.com/nagadomi/kaggle-cifar10-torch7
我的程式碼約有 400 行,包含模型定義與資料前處理,且大部分來自於 2_supervised 教學。有幾點我不喜歡的
- 所有內容都在單一檔案中:這對示範來說很好,但如果你想進行實驗,在每次執行時都不會想等資料預處理完成;
- 批次按範例處理。新手不確定如何正確執行,於是複製貼上程式碼,但速度非常慢;
- 當中的模型相當舊。
因此,我將其現代化,並加入一些實用的小訣竅,例如儲存會在每個時期更新的 HTML 報告。可以複製到 Dropbox 等,對於追蹤模型表現非常有用,還能儲存報告。
需要記憶體至少 2 GB 的 GPU,並搭配 cudnn
,如果使用標準的 nn
後端,會稍微多一點。 cudnn
是 NVIDIA 的深度學習函式庫,目前尚未公開,但絕對值得註冊並申請,很棒:https://developer.nvidia.com/cudnn
建議使用 NVIDIA GPU,BatchNormalization 會需要,但 AMD 顯示卡搭配 OpenCL 也可以,這要歸功於 Hugh Perkins 的這項絕佳創作:https://github.com/hughperkins/cltorch.git查看 opencl 分支。
文章與程式碼包含 3 個部分/檔案
- 模型定義
- 資料前處理
- 訓練
模型 models/vgg_bn_drop.lua
在 Batch Normalization 論文 [1] 提出並提供一種加快訓練速度的方法,並使用批次統計數據後提升了效能,而且 nn.BatchNormalization
已實作在 Torch(感謝 Facebook!)中,因此我想檢查它與 Dropout 併用時的情形,而CIFAR-10 就是個不錯的起手練習。
這個概念很簡單,BatchNormalization 的作者指出它可以取代 Dropout,但我心想何不將兩者同時使用在網路中,以大幅度規範訓練呢?
以下是模型定義
它是一個類似 VGG 的網路 [2],具有許多個 3x3 的濾波器以及 1,1 的填充,因此它們後面特徵圖的大小不會改變。只有在最大池化後才會改變。卷積層的權重使用 MSR 方式初始化 [3]。
前處理 provider.lua
我喜歡使用 BatchProvider -> Network 結構來訓練模型。事實上,您甚至可以建立一個模型,就像
model = nn.Sequential()
model:add(BatchProvider) -- different in train and test mode
model:add(DataAugmentation) -- disabled in test mode
model:add(NeuralNetwork)
接著,您的訓練程式碼會很簡單。不過在實際程式碼中,我只保留資料擴增功能在模型中,不過 BatchProvider 是個類別。現在讓我們開始前處理,從 https://github.com/szagoruyko/cifar.torch 複製程式碼,然後去資料夾 cifar.torch
並啟動解釋器
th -i provider.lua
它將執行檔案然後進入互動模式。前處理將花費大約 40 分鐘
provider = Provider()
provider:normalize()
torch.save('provider.t7',provider)
最後,您將會有所有資料儲存在 provider.t7
檔案中,大小為 1400 Mb。影像轉換為 YUV 並經過平均標準化處理。
訓練 train.lua
這樣就好了,就可以開始訓練了
CUDA_VISIBLE_DEVICES=0 th train.lua
在程式碼中,模型達到最佳效能時所使用的參數是預設值。我使用 SGD 搭配交叉熵損失,學習率為 1、動量為 0.9 以及權重衰減為 0.0005,每 25 epochs 降低一次學習率。幾個小時後,您就能取得模型。準確度可以使用像是自動更新的 Firefox 或 Chrome 外掛程式更新 logs/report.html
來追蹤。
準確度提昇的方式
混淆矩陣
ConfusionMatrix:
[[ 929 4 15 7 4 0 1 2 29 9] 92.900%
[ 2 977 2 0 1 0 0 0 6 12] 97.700%
[ 16 1 923 16 25 8 7 1 3 0] 92.300%
[ 14 2 30 836 19 68 18 5 6 2] 83.600%
[ 6 1 18 16 932 7 6 10 4 0] 93.200%
[ 3 1 25 78 17 867 4 5 0 0] 86.700%
[ 4 1 19 17 6 7 942 0 2 2] 94.200%
[ 6 0 12 15 10 14 0 942 1 0] 94.200%
[ 22 6 4 1 0 1 1 0 961 4] 96.100%
[ 9 38 1 4 0 1 1 1 10 935]] 93.500%
+ average row correct: 92.439999580383%
+ average rowUcol correct (VOC measure): 86.168013215065%
+ global correct: 92.44%
移除 BN 或 Dropout 後,準確度為 91.4%。
我建立一個小型表格來評定 VGG+BN+Dropout 架構搭配不同後端在 GeForce GTX 980 上的效能。批次大小設定為 128,數字都是以秒為單位
| cunn | cudnn R2 | clnn (no BN) — | :—: | :—: | :—: 向前 | 0.292 | 0.163 | 1.249 向後 | 0.407 | 0.333 | 0.831 向前 + 向後 | 0.699 | 0.500 | 2.079
cunn
是 Torch 的一種標準 CUDA 神經網路後端, clnn
是 OpenCL 後端。 cudnn
預期是最快的。還有一個 cuda-convnet2
後端,它的速度可能快一點,但是我並沒有在這個架構上測試過它,主要是因為 BN 是在 BDHW 格式中實現的,而 cuda-convnet2
則使用 DHWB。
這段程式碼是深層卷積神經網路的良好操場,例如,很容易實作在論文中宣稱 92% 準確率(比他們高出約 2%)的 Network-In-Network 架構,而且不需要 BN,就有 88% 的準確率,NIN 的訓練速度比 VGG 快 4 倍。我已將範例放在 nin.lua
感謝 Soumith 和 IMAGINE 實驗室協助我準備這篇文章!
參考
- Sergey Ioffe、Christian Szegedy。批次正規化:降低內部共變異變異,加速深度網路訓練 [arxiv]
- K. Simonyan、A. Zisserman。使用於大規模影像辨識的深度卷積網路 [arxiv]
- Kaiming He、Xiangyu Zhang、Shaoqing Ren、Jian Sun。深入整流器:在 ImageNet 分類上超越人類級別的效能 [arxiv]
- Min Lin、Qiang Chen、Shuicheng Yan。網路中的網路 [arxiv]