Detectron精讀系列之一:學習率的調節和踩坑
作者: huichan chen
大家期盼已久的Detectron終於開源啦,先進的模型就在一個命令行之間。但是面對龐大的caffe2和detectron函數庫,多少會感覺有些迷.Detectron精讀系列會從細小的調參開始,到一些重要的函數分析,最後掌握Detectron函數庫的全貌。在這個過程中,我們也會幫大家提前踩坑,希望大家可以從Detectron函數庫學到更多通用的計算機視覺技能。
Detectron函數庫有一點複雜,在這次的解讀中我們主要介紹multi-gpu訓練的時候,學習率如何調節的問題。看似簡單的問題,最近Facebook,Google和Berkeley多個組都發表了論文對這一問題進行了理論和實驗的討論,首先我們對這些論文的結果做一個簡要的總結。三篇論文研究類似,但是每一篇相對於前一篇都有改進。
Facebook:1小時內培訓Imagenet
貢獻:
提出了線性縮放規則,當批量變為K倍時,學習速度需要乘以K就能夠達到同樣的訓練結果。看似簡單的定律,Facebook的論文給出了不完整的理論解釋和堅實的實驗證明。除此之外,論文還討論了如何處理批量標準化如何實現分散式SGD。通過線性縮放規則,Facebook成功的在一小時內訓練了批量大小為8192的Resnet 50。
缺陷:
當批量超過8000時觀測到了模型訓練結果會嚴重變差。如下圖:
伯克利:卷積網路的大批量訓練
Berkeley的組發現Facebook提出的線性縮放規則當批量過度大時訓練不穩定,容易發散。並且噹噹Batch Size超過8000時,結果會嚴重退化。作者提出Layer Layer Wise Adaptive Rate Scaling(LARS)定律,從而能夠在批量為32000的情況下高效的訓練ResNet 50網路.SGD的權值更新等於梯度乘以學習率,論文中作者提出了全球學習率和本地學習率決定,全球學習率所有層共享,本地學習率由梯度的變化速率決定,這一想法是受ADAM等自適應學習率SGD的方法的影響。下表格為LARS的訓練結果:
谷歌:不要降低學習率,增加批量
LSR和LARS大大提高了模型的並行性,但是不能夠提高模型的結果.Google組的研究發現,通過增大Batch Size保持學習速率不變的辦法可以得到與學習速度降低類似的學習曲線,並且將批量進一步擴大到了65536,整個模型的訓練過程只需要2500次參數更新。
收穫與總結:
三篇論文通過理論和實驗證明了大批量能夠加快模型的訓練速度。面對動則幾百塊的GPU,很多人對這三篇論文望而卻步。其實本文提出的想法可以在更快的RCNN,Mask RCNN中得到很好的應用,我們只需要使用多GPU,並且根據線性縮放規則來調節學習旅就可以大大的提高檢測網路的訓練速度,並且還有可能得到更好的結果。
Detectron線性縮放規則示例
Detectron庫的玩具示例已經給大家展示如何使用線性縮放規則
python2 tools/train_net.py --cfg configs/getting_started/tutorial_1gpu_e2e_faster_rcnn_R-50-FPN.yaml OUTPUT_DIR /tmp/detectron-outputpython2 tools/train_net.py --cfg configs/getting_started/tutorial_2gpu_e2e_faster_rcnn_R-50-FPN.yaml OUTPUT_DIR /tmp/detectron-outputpython2 tools/train_net.py --cfg configs/getting_started/tutorial_4gpu_e2e_faster_rcnn_R-50-FPN.yaml OUTPUT_DIR /tmp/detectron-outputpython2 tools/train_net.py --cfg configs/getting_started/tutorial_8gpu_e2e_faster_rcnn_R-50-FPN.yaml OUTPUT_DIR /tmp/detectron-output
對應的配置文件如下:
1個GPU:
BASE_LR:0.0025
MAX_ITER:60000
步驟:[0,30000,40000]
2個GPU:
BASE_LR:0.005
MAX_ITER:30000
步驟:[0,15000,20000]
4個GPU:
BASE_LR:0.01
MAX_ITER:15000
步驟:[0,7500,10000]
8個GPU:
BASE_LR:0.02
MAX_ITER:7500
步驟:[0,3750,5000]
Large Batch Size的初始訓練不穩定,需要使用預熱時間表進行學習調調整,具體論文在lib / utils / lr_policy.py中實現。
Mxnet更快的RCNN線性縮放規則測試
Linear Scaling Law簡單的讓人難以相信,為了真實的測定這一定律是適用於更快rcnn,我們在mxnet更快rcnn github上面測試了該定律。我們分別測定了不使用Linear Scaling Law的更快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 &
學習速度/ GPU / MAP /訓練樣本每秒
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
配置中大多數參數是為8 GPU準備的,直接把GPU數目改為1會讓結果變為NAN。
解
根據Linear Scaling Law請自行降低學習率,減少批量會增大梯度的不準確性,這時候大的學習率會讓神經網路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 Errorfrom 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
解
Facebook已經發現了這一錯誤,對lib / utils / subprocess.py進行了及時的修改。
踩坑3
我們已經將該問題反饋回了Facebook,如果遇到相同問題的同學,請稍加等候。
祝大家學習順利......(鄰^^ O)
※Petuum研究提出形義感知型Grad-GAN:可基於遊戲生成真實城市場景
TAG:機器之心 |