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;  反映了被正确断定的正例占总的正例的比重 


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

相关文章
相关标签/搜索