全面解析Apache Spark中的決策樹
Apache Spark中的決策樹
決策樹是在順序決策問題進行分類,預測和促進決策的有效方法。決策樹由兩部分組成:
決策(Desion)
結果(Outcome)
決策樹包含三種類型的節點:
根節點(Root node):包含所有資料的樹的頂層節點。
分割節點(Splitting node):將資料分配給子組(subgroup)的節點。
終端節點(Terminal node):最終決定(即結果)。
分割節點(Splitting node),僅就離散數學中的樹的概念而言,就是指分支節點。
為了抵達終端結點或者說獲得結果,該過程從根節點開始。根據在根節點上做出的決定,選擇分支節點。基於在分支節點上做出的決定,選擇下一個子分支節點。這個過程繼續下去,直到我們到達終端節點,終端節點的值是我們的結果。
Apache Spark中的決策樹
Apache Spark中沒有決策樹的實現可能聽起來很奇怪。然而從技術上來說是有的。在Apache Spark中,您可以找到一個隨機森林演算法的實現,該演算法實現可以由使用者指定樹的數量。因此,Apache Spark使用一棵樹來呼叫隨機森林。
在Apache Spark中,決策樹是在特徵空間上執行遞迴二進位制分割的貪婪演算法。樹給每個最底部(即葉子結點)分割槽預測了相同的標籤。為了最大化樹的節點處的資訊增益,通過在一組可能的分支中選擇其中的最佳分割來貪婪地選擇每個分支結點。
節點不純度(impurity)是節點上標籤一致性的度量。目前的實施提供了兩種不純的分類方法(Gini雜質和熵(Gini impurity and entropy))。
停止規則
在滿足以下列條件之一的情況下,在節點處停止遞迴樹構建(即只要滿足一個就停止,譯者注):
節點深度等於訓練用的 maxDepth 引數。
沒有候選的分割結點導致資訊收益大於 minInfoGain 。
沒有候選的分割結點去產生(至少擁有訓練minInstancesPerNode例項)的子節點 。
有用的引數
algo:它可以是分類或迴歸。
numClasses:分類類的數量。
maxDepth:根據節點定義樹的深度。
minInstancesPerNode:對於要進一步拆分的節點,其每個子節點必須至少接收到這樣的訓練例項數(即例項數必須等於這個引數)。
minInfoGain:對於一個節點進一步拆分,必須滿足拆分後至少提高這麼多資訊量。
maxBins:離散連續特徵時使用的bin數。
準備決策樹的訓練資料
您不能直接向決策樹提供任何資料。它需要一種特殊的格式來提供。您可以使用 HashingTF 技術將訓練資料轉換為標記資料,以便決策樹可以理解。這個過程也被稱為資料的標準化。
(資料)供給和獲得結果
一旦資料被標準化,您就可以提供相同的決策樹演算法進來行分類。但在此之前,您需要分割資料以用於訓練和測試目的; 為了測試的準確性,你需要保留一部分資料進行測試。你可以像這樣提供資料:
al splits = data.randomSplit(Array(0.7, 0.3))
val (trainingData, testData) = (splits(0), splits(1))
// Train a DecisionTree model.
// Empty categoricalFeaturesInfo indicates all features are continuous.
val numClasses = 2
val categoricalFeaturesInfo = Map[Int, Int]()
val impurity = "gini"
val maxDepth = 5
val maxBins = 32
val model = DecisionTree.trainClassifier(trainingData, numClasses, categoricalFeaturesInfo,
impurity, maxDepth, maxBins)
在這裡,資料是我的標準化輸入資料,為了訓練和測試目的,我將其分成7:3的比例。我們正在使用最大深度的為5的"gini" 雜質("gini" impurity)。
一旦模型生成,您也可以嘗試預測其他資料的分類。但在此之前,我們需要驗證最近生成的模型的分類準確性。您可以通過計算"test error"來驗證其準確性。
/ Evaluate model on test instances and compute test error
val labelAndPreds = testData.map { point =>
val prediction = model.predict(point.features)
(point.label, prediction)
}
val testErr = labelAndPreds.filter(r => r._1 != r._2).count().toDouble / testData.count()
println("Test Error = " + testErr)
就是這樣!你可以在這裡檢視一個正在執行的例子。
結語
為了幫助大家讓學習變得輕鬆、高效,給大家免費分享一大批資料,幫助大家在成為大資料工程師,乃至架構師的路上披荊斬棘。在這裡給大家推薦一個大資料學習交流圈:
658558542
歡迎大家進群交流討論,學習交流,共同進步。
當真正開始學習的時候難免不知道從哪入手,導致效率低下影響繼續學習的信心。
但最重要的是不知道哪些技術需要重點掌握,學習時頻繁踩坑,最終浪費大量時間,所以有有效資源還是很有必要的。
最後祝福所有遇到瓶疾且不知道怎麼辦的大資料程式設計師們,祝福大家在往後的工作與面試中一切順利。