决策树归纳是从有类标号的训练元组中学习决策树。决策树是一种类似于流程图的树结构,其中,每个内部节点表示在一个属性上的测试,每个分支代表该测试的一个输出,而每个树叶节点存放一个类标号,最顶层节点是跟节点
决策树归纳是从有类标号的训练元组中学习决策树。决策树是一种类似于流程图的树结构,其中,每个内部节点表示在一个属性上的测试,每个分支代表该测试的一个输出,而每个树叶节点存放一个类标号,最顶层节点是跟节点。
一:算法逻辑
D:数据
Attribute_list:元组属性列表
Attribute_selection_method:选择可以按类最好地区分给定元组的属性
树从单个节点N开始,N代表D中的训练元组
如果D中的元组都为同一类,则节点N变为树叶,并用该类标记他。
否则继续调用attribute_selection_method确定如果分裂。目的是使得每个分支上的输出分区都尽可能“纯”。
对分裂准则的每个输出,由节点N生长一个分支,D中的元组据此进行划分。假设A是分裂属性,根据训练数据,由三种可能的情况:
(1) A是离散的:在这种情况下,节点N的测试输出直接对应与A的已知值。对A的每个已知值创建一个分支。
(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; 反映了被正确判定的正例占总的正例的比重
另外,完成的项目存放在项目地址