Spark隨機森林實現學習

前言 html

最近閱讀了spark mllib(版本:spark 1.3)中Random Forest的實現,發如今分佈式的數據結構上實現迭代算法時,有些地方與單機環境不同。單機上一些直觀的操做(遞歸),在分佈式數據上,必須進行優化,不然I/O(網絡,磁盤)會消耗大量時間。本文整理spark隨機森林實現中的相關技巧,方便後面回顧。 git

 

隨機森林算法概要 github

隨機森林算法的詳細實現和細節,能夠參考論文Breiman 2001。這裏簡單說說大致思路,方便理解代碼。 算法

隨機森林是一個組裝(ensemble model)模型,內部的模型使用決策樹。基本思想是生成不少不少決策樹(構成森林),最後由這些決策數一塊兒投票決定最終結果。生成樹的過程當中,從行和列兩個方向添加隨機過程。行方向,在構建每棵樹前,使用有放回抽樣(稱爲Bootstrapping),獲得訓練數據。列方向,每次選擇切分點時,對feature進行無放回隨機抽樣,獲得一個feature子集,在當前節點上,只使用這些子集對應的數據計算最優切分點。這也是爲何此算法稱爲隨機森林,是否是很直觀。相比於單一決策樹,隨機森林有如下一些優勢: apache

  1. 結果比較穩定,不容易出現過擬合;
  2. Out-Of-Bag error評估模型效果,無需交叉檢驗;
  3. 可獲得feature重要性。

固然,爲了獲得上面的優勢,必須付出計算開銷做爲代價。在單機時代,使用隨機森林(R或scikit-learn)每每成本很高,可是如今有了spark,使得大規模,分佈式迭代計算成爲了可能,因此在spark上運用隨機森林是技術發展的必然結果! 服務器

 

Spark實現優化 網絡

spark在實現隨機森林時,採用了下面幾個優化策略: 數據結構

  1. 切分點抽樣
  2. feature裝箱(bin)
  3. 分區統計
  4. 逐層計算(level-wise)

使用這些策略,緣由在於RDD的數據時分佈在不一樣服務器上,爲了不過多的I/O,必須在原始算法上作出一些優化,不然執行時間可能難以接受。下面分別詳細討論這三個優化策略。 app

 

切分點抽樣 dom

此優化主要針對連續變量。先回憶一下通常的決策樹是如何對連續變量進行切分點選擇的。通常是先對feature進行排序,而後選取相鄰兩個數據之間的點做爲切分點。若是在RDD上執行這個操做,不可避免會使用shuffle過程,此過程會帶來大量的網絡通信。並且,通常RDD上的數據都很大,少則幾百萬,多則幾億到幾十億,甚至更多。在這樣的數量級上進行排序操做,想一想也是醉了。因此,爲了不排序操做,mllib經過抽樣的方法,在樣本上進行排序,而且根據樣本,獲取切分點。據spark團隊反饋,使用此策略雖然犧牲了部分精度,可是在實際運用過程當中,並無帶來過多的影響,模型效果能夠接受。

 

feature裝箱

根據抽樣,獲得切分點後,接下來是對feature進行裝箱操做,箱子就是由相鄰的樣本切分點構成。箱子的個數是很是小的,通常實際中採用30個左右。計算每一個箱子中不一樣種類的佔比,能夠很快計算出最優切分點。

舉個例子,參考上面的示例數據,第一行是每一個切分點的比例統計。基於上面的數據,可能生成3中切分狀況,分別有棕,紅和綠色三行表示。若是須要計算棕色的切分狀況,只須要按照第一行的組合方式,就能夠很快的計算所出來。

 

分區統計

RDD分區中裝箱數據單獨統計後,能夠經過reduce將每一個分區的數據合併,獲得整體的裝箱數據(經過mapPartition實現分區統計)。正是因爲裝箱統計數據能夠合併,因此能夠很好的適應分佈式數據環境,最後須要合併的數據也只是一些統計數據,不會帶來很大的網絡通信開銷。

 

逐層計算

單機版本的決策數生成過程是經過遞歸調用(本質上是深度優先)的方式構造樹,在構造樹的同事,須要移動數據,將同一個子節點的數據移動到一塊兒。此方法在分佈式數據結構上沒法有效的執行,並且也沒法執行,由於數據太大,沒法放在一塊兒,因此在分佈式存儲。mlib採用的策略是逐層構建樹節點(本質上是廣度優先),這樣遍歷全部數據的次數等於全部樹的最大層數。每次遍歷時,只須要計算每一個節點全部feature的裝箱統計參數,遍歷完後,根據節點裝箱統計量,決定是否切分,以及如何切分。

 

以上就是spark mllib實現的隨機森林的關鍵技巧。固然還有不少實現細節這裏沒有描述,不過若是理解了這些技巧,對閱讀spark mllib隨機森林源代碼會有很大幫助,但願對讀者有用。

 

Spark Random Forest實現的不足

截止到spark 1.3,mllib的隨機森林仍然不支持OOB error和variable importance的支持,也有一些網友在spark社區諮詢此問題,可是目前沒有獲得官方的迴應。但願後面,spark能夠支持此特性。

 

應用案例

目前,在網絡遊戲流失預測的場景下,使用spark隨機森林模型(1000棵樹)和單機c50模型作了對比試驗。試驗中覆蓋5款不一樣類型的遊戲,共執行608輪,試驗週期跨度爲4個月。採用了相同的數據,因爲單機數據量計算限制,C50使用了10%的採樣建模,而spark使用了全量數據(計算能力秒殺)。試驗結果是隨機森林的模型效果明顯優於C50。F1值有37%的提高,而F2(召回率優先)提高度高達72%

提高可能的緣由有兩個:

1 隨機森林模型效果確實優於C50

2 隨機森林建模數據量有質的飛躍,致使性能提高

 

參考資料

  1. Spark源代碼
  2. Spark峯會關於分佈式決策樹實現的分享
相關文章
相關標籤/搜索