大家期盼已久的 Detectron 終於開源啦,state-of-the-art 的模型就在一個命令行之間。但是面對龐大的 caffe2 和 detectron 函數庫,多少會感覺有些迷茫。Detectron 精讀系列會從細小的調參開始,到一些重要的函數分析,最後掌握 Detectron 函數庫的全貌。在這個過程中,我們也會幫大家提前踩坑,希望大家可以從 Detectron 函數庫學到更多通用的計算機視覺技能。
Detectron 函數庫有一點複雜,在這次的解讀中我們主要介紹 multi-gpu 訓練的時候,學習率如何調節的問題。看似簡單的問題,最近 Facebook,Google 和 Berkeley 多個組都發表了論文對這一問題進行了理論和實驗的討論,首先我們對這些論文的結果做一個簡要的總結。三篇論文研究類似,但是每一篇相對於前一篇都有改進。
Facebook : Training Imagenet in 1 hour
貢獻:
提出了 Linear Scaling Rule,當 Batch size 變為 K 倍時,Learning rate 需要乘以 K 就能夠達到同樣的訓練結果。看似簡單的定律,Facebook 的論文給出了不完整的理論解釋和堅實的實驗證明。除此之外,論文還討論了如何處理 Batch Normalization 如何實現分布式 SGD。通過 Linear Scaling Rule,Facebook 成功的在一小時內訓練了 Batch size 為 8192 的 Resnet 50。
缺陷:
當 Batch Size 超過 8000 時觀測到了模型訓練結果會嚴重變差。如下圖:
Berkeley : Large Batch Training of Convolution Networks
Berkeley 的組發現 Facebook 提出的 Linear Scaling Rule 當 Batch Size 過大時訓練不穩定,容易發散。並且當模型 Batch Size 超過 8000 時,結果會嚴重退化。作者提出了 Layer Wise Adaptive Rate Scaling(LARS)定律,從而能夠在 Batch Size 為 32000 的情況下高效的訓練 ResNet 50 網絡。SGD 的權值更新等於梯度乘以 Learning rate,論文中作者提出了 global learning rate 和 local learning rate 決定,global learning rate 所有層共享,local learning rate 由梯度的變化速率決定,這一想法是受 ADAM 等 adaptive learning rate SGD 的方法的影響。下表格為 LARS 的訓練結果:
Google : Don’t decrease the learning rate, increase the batch size
LSR 和 LARS 大大的提高了模型的並行性,但是不能夠提高模型的結果。Google 組的研究發現,通過增大 Batch Size 保持 Learning rate 不變的辦法可以得到與 decreasing learning rate 類似的學習曲線,並且將 batch size 進一步擴大到了 65536,整個模型的訓練過程只需要 2500 次參數更新。
收穫與總結:
三篇論文通過理論和實驗證明了 large batch size 能夠加快模型的訓練速度。面對動則幾百塊的 GPU,很多人對這三篇論文望而卻步。其實本文提出的 idea 可以在 Faster RCNN,Mask RCNN 中得到很好的應用,我們只需要使用 multi-GPU,並且根據 Linear Scaling Rule 來調節學習旅就可以大大的提高 Detection 網絡的訓練速度,並且還有可能得到更好的結果。
Detectron Linear Scaling Rule Example
Detectron 庫的 toy example 已經給大家展示如何使用 Linear Scaling Rule
python2 tools/train_net.py \
--cfg configs/getting_started/tutorial_1gpu_e2e_faster_rcnn_R-50-FPN.yaml \
OUTPUT_DIR /tmp/detectron-output
python2 tools/train_net.py \
--cfg configs/getting_started/tutorial_2gpu_e2e_faster_rcnn_R-50-FPN.yaml \
OUTPUT_DIR /tmp/detectron-output
python2 tools/train_net.py \
--cfg configs/getting_started/tutorial_4gpu_e2e_faster_rcnn_R-50-FPN.yaml \
OUTPUT_DIR /tmp/detectron-output
python2 tools/train_net.py \
--cfg configs/getting_started/tutorial_8gpu_e2e_faster_rcnn_R-50-FPN.yaml \
OUTPUT_DIR /tmp/detectron-output
對應的 config 文件如下:
1 GPUs:
BASE_LR: 0.0025
MAX_ITER: 60000
STEPS: [0, 30000, 40000]
2 GPUs:
BASE_LR: 0.005
MAX_ITER: 30000
STEPS: [0, 15000, 20000]
4 GPUs:
BASE_LR: 0.01
MAX_ITER: 15000
STEPS: [0, 7500, 10000]
8 GPUs:
BASE_LR: 0.02
MAX_ITER: 7500
STEPS: [0, 3750, 5000]
Large Batch Size 的初始訓練不穩定,需要使用 warm up schedule 進行學習旅調整,具體論文在 lib/utils/lr_policy.py 中實現。
Mxnet Faster RCNN Linear Scaling Rule Testing
Linear Scaling Law 簡單的讓人難以相信,為了真實的測定這一定律是適用於 faster rcnn,我們在 mxnet faster rcnn github 上面測試了該定律。我們分別測定了不使用 Linear Scaling Law 的 faster rcnn 跟使用 Linear Scaling Law 的結果。從結果分析使用 Linear Scaling Law 能夠加速訓練,並且還有可能得到更高的準確率。訓練集和測試集分別為:VOC 07 和 VOC 07 test 實驗結果如下:
nohup bash script/resnet_voc07.sh 0,1 0.001 &> resnet_voc07.log &
nohup bash script/resnet_voc07.sh 0,1,2,3 0.002 &> resnet_voc07.log &
nohup bash script/resnet_voc07.sh 0,1,2,3,4,5,6,7 0.004 &> resnet_voc07.log &
Learning rate / GPUs / MAP / training sample per second
0.001 / 2 / 70.23 / 4
0.002 / 4 / 71.43 / 6
0.004 / 8 / 70.98 / 9
0.001 / 4 / 66.50 / 6
0.001 / 8 / 65.00 / 9
Detectron 函數庫訓練踩坑錄 (o^^o)
Detectron 條理清楚,但是免不了有一些小的 bug,下面我們就給大家分享一下我們遇到的小坑。
踩坑 1
Config 中大多數參數是為 8 路 GPU 準備的,直接把 GPU 數目改為 1 會讓結果變為 NAN。
Solution
根據 Linear Scaling Law 請自行降低學習率,減少 batch size 會增大梯度的不準確性,這時候大的學習率會讓神經網絡 diverge。
踩坑 2
Multi GPU 訓練的時候會 out of memory。錯誤如下:
terminate called after throwing an instance of 'caffe2::EnforceNotMet'
what(): [enforce fail at context_gpu.h:230] error == cudaSuccess. 4 vs 0. Error at: /home/huichan/caffe2/caffe2/caffe2/core/context_gpu.h:230: unspecified launch failure Error from operator:
input: "gpu_0/res5_0_branch2c_w_grad" output: "gpu_2/res5_0_branch2c_w_grad" name: "" type: "Copy" device_option { device_type: 1 cuda_gpu_id: 2 }
terminate called recursively
*** Aborted at 1516782983 (unix time) try "date -d @1516782983" if you are using GNU date ***
terminate called recursively
terminate called recursively
terminate called recursively
terminate called recursively
terminate called recursively
terminate called recursively
terminate called recursively
terminate called recursively
Solution
Facebook 已經發現了這一錯誤,對 lib/utils/subprocess.py 進行了及時的修改。
踩坑 3
我們使用 multi GPU 訓練的時候會出現伺服器重啟,初步懷疑 memory leakage,我們已經將該問題反饋回了 Facebook,如果遇到相同問題的同學,請稍加等候。
祝大家學習順利……(o^^o)
本文為機器之心專欄,轉載請聯繫本公眾號獲得授權。
✄---
加入機器之心(全職記者/實習生):hr@jiqizhixin.com
投稿或尋求報導:editor@jiqizhixin.com
廣告&商務合作:bd@jiqizhixin.com