Spark Decision Tree

    決策樹概括是從有類標號的訓練元組中學習決策樹。決策樹是一種相似於流程圖的樹結構,其中,每一個內部節點表示在一個屬性上的測試,每一個分支表明該測試的一個輸出,而每一個樹葉節點存放一個類標號,最頂層節點是跟節點。
git


一:算法邏輯github

D:數據算法

Attribute_list:元組屬性列表apache

Attribute_selection_method:選擇能夠按類最好地區分給定元組的屬性dom

  • 樹從單個節點N開始,N表明D中的訓練元組學習

  • 若是D中的元組都爲同一類,則節點N變爲樹葉,並用該類標記他。測試

  • 不然繼續調用attribute_selection_method肯定若是分裂。目的是使得每一個分支上的輸出分區都儘量「純」。lua

  • 對分裂準則的每一個輸出,由節點N生長一個分支,D中的元組據此進行劃分。假設A是分裂屬性,根據訓練數據,由三種可能的狀況:spa

    (1) A是離散的:在這種狀況下,節點N的測試輸出直接對應與A的已知值。對A的每一個已知值建立一個分支。scala

    (2)A是連續的:有兩個可能的輸出,分別對應與條件A<=split,A>split

    (3) A是離散的且必須產生二叉樹:子集做爲分裂條件

  • 對於D的每一個結果分區上的元組,算法使用一樣的遞歸造成決策樹。

  • 終止條件

    (1)分區D的全部元組都屬於同一個類

    (2)沒有剩餘屬性能夠用來進一步劃分元組,使用多數表決。

  • 返回決策樹

二: 屬性選擇度量

    屬性選擇度量是一種選擇分裂準則,通常咱們使用兩種方式,信息增益(熵),以及基尼係數。基尼指數通常考慮屬性的二元劃分。二者的目的都是使得每一個分支上的輸出分區都儘量「純」。


三:使用Spark MLlib

  Spark MLlib提供了決策樹算法,使咱們可以從基本的算法中脫離出來。

 加載數據:

    // line -> user,featureCategoricalOne,fTwo,featureCategoricalThree,label
    val rawData = sc.textFile(rawdataPath)
                    .map(line =>{
                      val values = line.split("\t")
                      val featureVector = Vectors.dense(values.slice(1,values.length-1).map(_ .toDouble))
                      val label = values(values.length-1).toDouble
                      LabeledPoint(label, featureVector)
                    })

第一步是加載數據,假設你已經有要處理的數據存放在hdfs中。

label:結果,也就是最後的分類

featureVector:特徵向量

    //train data for training set, test data for valuating the model
    val Array(trainData, testData) = rawData.randomSplit(Array(0.8, 0.2))
    trainData.cache()
    testData.cache()

第二部是劃分數據,一部分數據用來訓練構造決策樹,另外一部分用來作測試(其實還應該有第三部分,能夠防止構造的決策樹過度耦合overfitting)

    //tell DecisionTree the number of values of categorical feature
    val featureMap = Map(0 -> 2,2 ->2)
    
    val model = org.apache.spark.mllib.tree.DecisionTree.trainClassifier(trainData, 2, featureMap, "gini", 10, 100)

第三部分就是訓練決策樹。

最後是評估模型。

  def getMetrics(model: DecisionTreeModel, data: RDD[LabeledPoint]): MulticlassMetrics = {
    val predictionsAndLabels = data.map(example => (model.predict(example.features), example.label)
    )
    new MulticlassMetrics(predictionsAndLabels)
  }
  
      val metrics = getMetrics(model, testData)
          //our label is binary
    println("precision:0:::::::::::::::"+metrics.precision(0))
    println("recall pre:0::::::::::"+metrics.recall(0))

    println("precision:1:::::::::::::::"+metrics.precision(1))
    println("recall pre:1:::::::::::::::"+metrics.recall(1))

    //confusion matrix
    println("confusionMatrix:::::::::::::::"+metrics.confusionMatrix)

如何評估呢?有如下一些指標:精確度,召回率等。理解以下:

    假設原始樣本中有兩類,其中:

1:總共有 P個類別爲1的樣本,假設類別1爲正例。 

2:總共有N個類別爲0 的樣本,假設類別0爲負例。 

    通過分類後:

3:有 TP個類別爲1 的樣本被系統正確斷定爲類別1,FN 個類別爲1 的樣本被系統誤斷定爲類別 0,

顯然有P=TP+FN; 

4:有 FP 個類別爲0 的樣本被系統誤判判定爲類別1,TN 個類別爲0 的樣本被系統正確判爲類別 0,

顯然有N=FP+TN; 

那麼:

精確度(Precision):

P = TP/(TP+FP) ;  反映了被分類器斷定的正例中真正的正例樣本的比重( 

 準確率(Accuracy)

A = (TP + TN)/(P+N) = (TP + TN)/(TP + FN + FP + TN);    

反映了分類器統對整個樣本的斷定能力——能將正的斷定爲正,負的斷定爲負 

 召回率(Recall),也稱爲 True Positive Rate:

R = TP/(TP+FN) = 1 - FN/T;  反映了被正確斷定的正例佔總的正例的比重 


另外,完成的項目存放在項目地址  

相關文章
相關標籤/搜索