如何使基於梯度下降的機器學習並行化

本文,討論batch-gradient和stochastic gradient descent的並行化。

首先來看batch-gradient。batch-gradient的每次更新都要在整個訓練集上計算獲得。比如,logistic regression的更新公式爲:

(1)
圖片來自coursera上的《Machine Learning》截屏

因此若訓練集很大(m很大),這種做法是十分耗時的。那何做到並行化呢?Andrew ng 在《Machine Learning》中便提到了機器學習的並行化:如果機器學習算法能表示成training set上函數的sum的形式(即上面公式),那麼一個好的並行化選擇是使用Map-reduce。一個Map-reduce job分兩個階段進行:map階段和reduce階段。因此可以將原本的sum公式(1)分解成幾個小的sum公式,each由不同map task分別計算,最後由reduce task把map得到的結果進一步加和。


好,看來batch-gradient的並行化不是個很大的問題。但batch-gradient本身有缺陷:若機器學習算法(比如矩陣分解問題)面臨的是一個非convex的算法,那麼使用batch-gradient會使算法收斂很慢[2],並且很可能陷入局部最優解(local optimum)。因此,實際中使用的是SGD(Stochastic Gradient Descent)——隨機梯度下降。SGD的主要思想是:不同於以往利用整個training set更新一次參數,SGD隨機從training set 中挑選出一個樣本進行更新,直到算法收斂。 [1]指出KDD Cup 2011(track 1)的前三名都使用了SGD。SGD有算法converge 快,不容易陷入局部最優解的優點。


但是SGD內在本身是序列化的,因而不容易並行化。但不是不能,基本思想是:若爲選定的一個評分r_ij,算法對應要更新的用戶feature向量p_i和物品feature向量q_j,也就確定了。因此,評分矩陣中,所有即不同行又不同列的評分都可以同時更新。臺灣國立大學的團隊提出了一種快速的基於內存共享的並行SGD算——FPSGD。根據評測,它超出了現有被認爲最好的shared-memory SGD並行算法CCD++。[13]指出,以往的SGD並行化算法面臨兩個問題:①緩存命中率低和②等待問題。首先,緩存命中率低是由算法內在的隨機選取引起的。而等待問題是由數據的imbalance引起的。比如評分預測問題中,有的用戶評分多,有的用戶評分少,因此整個評分矩陣是imbalanced的。若使用DSGD(詳見[1]),則所有節點要等待最慢的那個節點處理完(“最慢”可能是因爲它被分配的block是最密集的)。


針對問題②,可以在執行DSGD之前random shuffle整個評分矩陣。但作者不滿意這樣方法,它指出不同線程的執行時間還會有差異。於是作者提出給空閒線程分配任務的方法:將整個矩陣分成(s+1)×(s+1)塊,讓s個線程同時執行。這樣一個線程處理完一個block之後,必定有其他的block是free的(free是指不與其他線程處理的block共享用戶或物品feature向量)。算法則爲其分配更新次數最少的free block——爲了使所有block的更新次數都差不多。論文顯示,這樣的方法使DoI在a few iteration之接近zero。(見論文)。


針對問題①,作者提出了partial random method:即更新塊的選擇是隨機,而塊內的更新是有序的。同時爲了增加隨機性,算法將評分矩陣分成了比(s+1)×(s+1)更多的塊。


最後值得指出的是,作者將改算法實現並開源了,enjoy


參考文獻:

[1] A Fast Parallel SGD for Matrix Factorization in Shared Memory Systems

[2] Efficient Top-N Recommendation for Very Large Scale Binary Rated Datasets

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章