如何訓練你的ResNet(三):正則化
作者:David Page
編譯:Bing
“如何用一個GPU實現八個GPU的水平。”
在上一篇文章結尾,我們在256秒內將模型在CIFAR10上訓練到94%的測試精確度。相比之下,基於單個V100 GPU上100%的計算效率,初始基線為341秒,而我們理想中的40秒的目標略微不切實際。今天,我們將定一個適中的目標——超越fast.ai在DAWNBench中的獲勝記錄,其中使用了8個GPU,訓練了174秒。我們會繼續使用單個GPU,因為距離使用所有FLOP,我們還離得很遠。
對於目前的設定,我們能得對所需要的時間進行大致對比,我們選擇性地刪除了計算中的某些部分,並運行了剩下部分。例如,我們可以現在GPU上預裝隨機訓練資料,省去資料下載和遷移的時間。我們還能刪除優化器步驟和ReLU以及批規範層,只留下卷積層。如果這樣做,不同batch size所用時間如下:

這裡有幾點明顯特徵。首先,批標準化佔用了很大一部分時間。其次,卷積的主要部分也佔用了超過一半的計算時間,比我們預計的在100%計算力上用掉一半的時間還要長。第三,優化器和資料下載步驟並不是主要問題。
在GPU專家Graham Hazel的幫助下,我們查看了一些配置檔案,迅速發現了批標準化的一些問題——用PyTorch(0.4版本)將模型轉換為半精度的預設方法會觸發一個慢速程式碼路徑,該路徑不使用優化的CuDNN例程。如果我們將批標準化的權重轉換回單精度,那麼快速程式碼就被激發,所用時間看起來就更正常了:

經過改進,在35個epoch內訓練達到94%的精度只需要186秒,越來越接近我們的目標了!
除此之外,還有很多方法能改進訓練,將時間縮短至174秒。GPU程式碼還可以進一步優化,例如,當前的啟用資料以NCHW格式儲存,但TensorBoard中的快速CuDNN卷積例程希望資料遵循NHWC的順序。所以,在卷積前後執行前向和後向轉置需要佔用很大一部分執行時間。由於PyTorch 0.4不支援原生NHWC計算,並且在其他框架中似乎沒有成熟的支援,這一問題會在之後的文章中重點關注。
將訓練時間減少到30個epoch,時間也會減少到161秒,輕鬆打破目前的記錄。但如果僅僅加速基準學習速率,在5次執行中沒有能達到94%的案例。
在CIFAR10上一中有效的簡單正則化策略就是“Cutout”正則化,它可以清除每張訓練圖片中的隨機子集。我們在訓練影象選取隨機8×8方形子集進行實驗,除此之外還有標準的資料增強,用於填補、裁剪、隨機翻轉。
在基線35個epoch訓練後的結果都達到了94%的精確度,其中還有一次達到了94.3%,這也是在基線上的小進步。對學習率進行手動優化後,執行精度達到了94.5%(將峰值學習速率提前,用簡單的線性衰減替換衰減相位)。
如果我們在30個epoch上提高學習速率,4/5的執行次數會達到94%的精度,中間值為94.13%。我們可以將batch size提高到768,4/5也能達到94%,中值為94.06%。當batch size為512時,30epoch執行時間為161秒,當batch size為768時,時間為154秒,所有都只在一個GPU上,打破了我們的目標!折線圖如下:

現在我們達到了文章開頭設定的目標,想要復現這一過程,可以點選連結檢視程式碼: ofollow,noindex"> http:// github.com/davidcpage/c ifar10-fast/blob/master/experiments.ipynb 。不過我們的新紀錄應該能很容易打破,首先,我們一直將單個GPU的計算能力維持在25%以下,之後還有對其優化的方法。第二,可以用相關技術減少訓練epoch,例如Mixup正則化和AdamW訓練。我們尚未研究如何對引數平均以加速最終收斂,如果我們打算在推理時做更多工作,則可以使用測試時間增強來進一步縮短訓練時間。還有人提出在更大的網路中進行小於20個epoch的實驗訓練,結合fast.ai的技術,進一步研究也許會發現更有趣的結果。
但是,目前我們將不繼續探索這些未開發的途徑,而是重點觀察目前我們一直使用的網路,就會發現意想不到的收穫。