決策樹概括是從有類標號的訓練元組中學習決策樹。決策樹是一種相似於流程圖的樹結構,其中,每一個內部節點表示在一個屬性上的測試,每一個分支表明該測試的一個輸出,而每一個樹葉節點存放一個類標號,最頂層節點是跟節點。
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; 反映了被正確斷定的正例佔總的正例的比重
另外,完成的項目存放在項目地址