决策树概括是从有类标号的训练元组中学习决策树。决策树是一种相似于流程图的树结构,其中,每一个内部节点表示在一个属性上的测试,每一个分支表明该测试的一个输出,而每一个树叶节点存放一个类标号,最顶层节点是跟节点。
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; 反映了被正确断定的正例占总的正例的比重
另外,完成的项目存放在项目地址