[NIPS2012] 針對深度學習的大型分散式訓練
正文在這裡https://static.googleusercontent.com/media/research.google.com/en//archive/large_deep_networks_nips2012.pdf ,這個可是神人Jeff Dean在2012年時候的作品,今天我們來強勢圍觀一下。
在這個paper之前,沒有什麼大型深度學習分散式訓練的實例,而且大型CPU分散式學習主要還是大的廣告公司需要,Google作為這個行業的領頭人肯定是率先推出自己的解決方案來教大家做人的。
Google 沒有選擇走GPU這條路的原因是模型可能大到一個GPU的內存不夠用(2012年的時候GPU內存還沒有現在的這麼大),而且GPU到CPU的數據傳輸會有瓶頸(那個時候應該也還沒有nvm)
Google這個解決方案叫DistBelief,這個解決方案是包括單機多線程和message passing,而且在這個系統上面專門寫了兩個方案是適合大規模訓練的,叫做Downpour SGD和Sandblaster L-BFGS,這兩個方案後面會講到。
前人在這個領域的貢獻
每次寫一個新的系統前都要問問自己,這個新的系統有沒有必要寫。對於CPU分散式訓練來說,沒有人比Google走的更前面,所以paper里寫了學術界是沒有什麼可以借鑒的。這裡特別提到了兩個之前嘗試過的方法
- 訓練一堆小的模型然後取它們的平均:https://arxiv.org/pdf/1202.2745.pdf
- 把已有的神經網路的設計改成可以並行訓練的模式:http://www.mirlab.org/conference_papers/International_Conference/ICASSP%202012/pdfs/0002133.pdf
這兩個方案都不算是最佳,因為對NN的設計都是有限制的。Paper也考慮了Google先有的系統能不能做這個分散式訓練的
- MapReduce主要設計的時候是為了更好的可以分散式處理數據,跟機器學習訓練的時候需要迭代的設計是不一樣的
- GraphLab主要適用於一般的網路處理,不能很好的針對神經網路來優化。
模型層面的並行
在模型超過一個機器的時候,模型的parameter會被分配到不同的機器上去,需要跨機器的參數在訓練的時候是通過網路來傳輸的。那麼這個時候神經網路的設計就要注意了,如果想要能夠訓練的時候快的話,那麼模型的複雜度就很是關鍵了,如果跨機器的連接太多的話那麼網路層面可能會成為瓶頸。
在Google內部測試的時候,有成功的做到過把參數分配到144台機器上面,後面會具體提到各種不同的設置跟訓練速度的比較。
分散式訓練的演算法
這裡要回到我們之前講的兩個演算法,Downpour SGD和Sandblaster L-BFGS
Downpour SGD
SGD算是最受歡迎的訓練神經網路的演算法,但是SGD本身是有時序的,不適合分散式訓練,所以需要做以下改動:
- 把訓練數據分成好幾份分到不同的機器上面
- 模型更新是通過parameter server來做的,parameter server也是sharded
這樣的話,每個機器訓練的時候是分開的,而且parameter server收發參數變化的時候也是分開的。這個是downpour SGD 的psudocode
具體流程是這樣的
- 每次開始一個新的迭代的時候,向parameter server要最新的paramter
- 開始訓練,算出這些parameter需要怎樣更新。注意這裡算出的是參數要怎麼變,而不是變成什麼值。有可能兩個伺服器在分開訓練的時候都覺得某一個參數要-2,那麼伺服器端是要-4而不是-2.
- 把這些變化發給parameter server。如果不是每一步都需要給parameter server跟新的話,那麼本地先把這些變化存起來,直到提交給伺服器的時候再清空。不是每次都提交的話,參數可能會比較老,但是可以節省網路上的代價。
- 有一個很重要的優化是在訓練的時候需要實時更新learning rate,這個paper裡面提到了Adagrad http://www.jmlr.org/papers/volume12/duchi11a/duchi11a.pdf,也就是說learning rate應該是根據gradiant 來算的,每個parameter 的learning rate是一個常數處以這個parameter到現在為止的gradient的L2,像這樣
這個gamma,常數,一般選擇會比較大,這樣整體的learning rate是比較大的,大過一個比較合理的既定的learning rate。
- 每次訓練的時候會先訓練一個model replica,然後才會把所有其他model replica的打開,這樣等於是給模型一個warm start。
後面會具體提到這些招數的差別,我們先繼續看第二個演算法是怎麼實現的
Sandblaster L-BFGS
BFGS的全名是Broyden–Fletcher–Goldfarb–Shanno (BFGS) algorithm (https://en.wikipedia.org/wiki/Broyden%E2%80%93Fletcher%E2%80%93Goldfarb%E2%80%93Shanno_algorithm),是一個通過迭代可以解非線性優化問題。L-BFGS是一個具體演算法實現,L這裡是limited memory,具體實現可以看這裡:Limited-memory BFGS
Sandblaster是這個paper給支持L-BFGS一個分散式演算法的系統。在這個系統里,L-BFGS具體的運算是發生在coordinator裡面的。這個coordinator是直接跟parameter server溝通的,但是不從parameter server裡面直接拿參數,而是通過跟parameter server交流讓parameter server來做一個簡單的運算,比如點積,加減乘除這些運算。L-BFGS之前運算的結果也是存在各個parameter server上面的。這裡是在加入L-BFGS之後整個訓練過程
這裡有一個重要的優化,就是L-BFGS是需要等最慢的訓練機器響應了之後才能開始下一個迭代,在分散式系統裡面這個是大忌。為了降低這個問題,在分配工作的時候,工作數量是大於機器數量的,這樣就確保的快的replica在等慢的replica的時候可以干跟多的活。
比起Downpour SGD,這個演算法需要跟parameter server溝通的次數大大增加了,那麼我們可以通過增加本地迭代的次數來減少跟parameter server的溝通成本。
實驗
Google把各種不同的模型都拿DistBelief來訓練了一遍,來看看具體提速效果如何
我們可以看到圖像模型的提速非常的明顯,而語言模型在超過8個機器之後基本沒有提速。這裡主要是因為這個語言模型等餓參數較少,所以網路溝通成本會變高。
這裡是不同的演算法跟它們的模型準確度的提升,我們可以看到分散式訓練是對準確度有提升的。
想要把模型訓練到一個準度就停止的話,那麼SGD加上adagrad是速度最快的。
從各個實驗結果我們可以看出來這個系統真的算是效果拔群。原文連接再貼一遍 https://static.googleusercontent.com/media/research.google.com/en//archive/large_deep_networks_nips2012.pdf ,各位看官走好啊~
推薦閱讀:
※[DNN] 嘗試理解深度神經網路的Large-batch魔咒
※鋼鐵俠3裡面的賈維斯系統是個什麼構造的?
※分散式系統理論基礎 - 一致性、2PC和3PC
※Zeppelin:一個分散式KV存儲平台之概述