文档章节

Spark 数据挖掘 - 利用决策树预测森林覆盖类型

clebeg
 clebeg
发布于 2015/11/03 10:15
字数 2447
阅读 5015
收藏 108

Spark 数据挖掘—利用决策树预测森林覆盖类型

1 前言

预测问题记住一点:最垃圾的预测就是使用平均值,如果你的预测连比直接给出平均值效果都要差,那就省省吧!
统计学诞生一个多世纪之后,随着现在机器学习和数据科学的产生,我们依旧使用回归的思想来进行预测,尽管回归 就是用平均值向后不断回滚来预测。回归的技术和分类的技术紧密相关。通常情况下,当目标变量是连续数值时指的是回归,例如预测 身高和体重。当预测的目标变量是名义或者说是类别变量时,指的就是分类,例如预测邮件是否是垃圾邮件。
无论是分类还是回归,都需要给定已知信息去预测未知信息,所以它们都需要从输入输出来学习。它们需要包括问题和答案。这类算法因此也称为监督学习的方法。
回归和分类是使用年代最近研究的最充分的预测分析技术。很多算法开源包都包含通用的这些方法。比如:支持向量机,逻辑回归,朴素贝叶斯,神经网络和深度学习。
本文的重点是讨论:决策树和它的扩展随机森林。决策树是通用而且灵活的分类回归算法。

2 一些基本概念

注意:特别小心分类变量(尤其是那些用数字表示的分类变量,不要随便放到算法中去训练)和数值变量
注意:不是所有的算法都能处理分类变量,或者都能处理回归分类问题,但是放心决策树都可以

3 算法简介

决策树

算法名字 决策树,DT,Decision Trees
算法描述 适合任何数据类型的分类和回归算法 关键概念:树、信息增益、停止条件、过拟合
算法原理 根据已有样本训练得到一颗树,树的叶子节点就是预测的值,新的样本将按照样本的值遍历树的相对应节点最后到达叶子节点,叶子节点的值就是新样本的预测值。<br/> 决策树原理非常简单,如下图:<br/> 决策树示例图
使用场景 强大的算法,适合回归和预测的很多场合
算法优缺点 优点: 1. 能够自然处理分类和数值特征 2. 容易并行计算 3. 对异常值具有很好的鲁棒性(意味着小量的异常值或者错误数据不影响分类结果) 4. 可以处理不同类型和不同维度的数据不需要数据预处理或者预先正则化数据 5. 结果容易理解和解释<br /> 缺点: 1. 容易过拟合(不过它的变种随机森林已经改进了这个问题)
数据类型 数值型和标称型数据
参考资料 1. 算法原理 机器学习实战 <br /> 2. MLlib实现 DesisionTree<br /> 3. MLlib实现 RandomForest

4 数据集

本文将使用著名的 Covtype 数据集合,可以在 http://bit.ly/1KiJRfg 这里下载。下载之后是一个压缩的 csv 文件, linux 用户可以用命令:tar -xzvf 解压缩,windows用户可以使用 .7-zip 解压缩,同时下载数据集的描述文件 covtype.info 数据集记录的是美国 Colorado 植被覆盖类型数据,也是唯一一个关心真实森林的数据。每条记录都包含很多指标描述每一块土地。 例如:高度、坡度、到水的距离、树荫下的面积、土壤的类型等等。森林的覆盖类型是需要根据其他54个特征进行预测的特征。 这是一个有趣的数据集,它包含分类和数值特征。总共有581012条记录。每条记录有55列,其中一列是土壤的类型,其他54列是输入特征。 虽然这个数据集还不能算得上真正的大数据,但是也能说明很多问题。很幸运,这个数据集已经是csv文件,所以不需要太多的数据清洗或者其他的准备就可以给 Spark Mllib 使用。 数据集可上传到 HDFS,当然也可以先放到本地进行这个有趣的测试。不管哪种方式,Spark 都只需要改变一两个参数。 这里不得不再次提醒一个问题,分类变量如何编码,下面是编码的方式:

  • 一个合适的编码方式是:one-hot 或者 1 of n 编码 一个分类变量:编码为 n(分类特征个数)个变量
  • 另一种编码方式:就是给每个值一个固定的数字,例如: 1, 2, 3, ..., n

当算法中把编码当作数字的时候只能使用第一种编码,第二种编码会得出滑稽的结果。具体原因是没有大小的东西被强制成有大小之分。
Covtype 数据集中有很多类型的特征,不过很幸运,它已经帮我们转换成 one-hot 形势,具体来说:

  • 11到14列,其实表示的是 Wilderness_Area,Wilderness_Area 本身有 4 个类别
  • 15到54列,其实表示的是 Soil_Type,Soil_Type 本身有 40个属性值
  • 55列是表示目标值,当然它不需要表示成为 one-hot形式。

这个数据集每一列的变量单位都不一定相同,有的表示距离,有的表示度数等等

5 Spark 决策树模型

下面给出一个初步的利用Spark MLlib 实验的决策树模型,具体的意图,代码都有详细的注释:

  //本地测试
  val rootDir = "your sample data directory"
  def main(args: Array[String]) {
    val conf = new SparkConf().setAppName("SparkInAction").setMaster("local[4]")
    val sc = new SparkContext(conf)
    val covTypeData = sc.textFile(rootDir + "/covtype.data")
    val data = dataPrepare(covTypeData)
    //选择测试集合和训练集合
    val Array(train, cvData, test) =
      data.randomSplit(Array(0.8, 0.1, 0.1))
    train.cache()
    cvData.cache()
    test.cache()

    val model = buildDecisionTree(train, cvData)
  }


  /**
   * Spark MLlib 表示特征向量的对象是 LabeledPoint
   * 这个对象由表示特征的向量和目标变量组成
   */
  def dataPrepare(data: RDD[String]) = {
    val sample = data.map{
      line =>
        //全部数据转化为 double
        val array = line.split(",").map(_.toDouble)
        //前面54列是特征向量,后面一列是目标变量 label
        val featureVector = Vectors.dense(array.init)
        //决策树目标变量必须从0开始,按照1递增
        LabeledPoint(array.last - 1, featureVector)
    }
    sample
  }

  /**
   * 决策树模型建立,这里很容易改进为十择交叉验证。
   * 对每一份数据建立模型时,都需要随机选出部分数据来调整模型参数到最优。
   * 通过交叉验证的方式调整参数。
   * @param train
   * @param cvData
   */
  def buildDecisionTree(train: RDD[LabeledPoint], cvData: RDD[LabeledPoint]) = {
    def getMetrics(model: DecisionTreeModel, data: RDD[LabeledPoint]) = {
      val predictionsAndLabels = data.map {
        example =>
          (model.predict(example.features), example.label)
      }
      new MulticlassMetrics(predictionsAndLabels)
    }
    val model = DecisionTree.trainClassifier(
      train, 7, Map[Int, Int](), "gini", 4, 100
    )
    val matrics = getMetrics(model, cvData)
    println(matrics.confusionMatrix)
    (0 until 7).map(
      cat => (matrics.precision(cat), matrics.recall(cat))
    ).foreach(println)
  }

这个是初步的运行结果:

#整体的准确率和召回率
(0.7012384971978136,0.7012384971978136)
#每一个类别的准确率和召回率
(0.685108051158916,0.6668097486526446)
(0.7255299659774928,0.7930627570177007)
(0.6194455768446799,0.8685338668190912)
(0.3771043771043771,0.39436619718309857)
(0.55,0.011727078891257996)
(0.0,0.0)
(0.7174657534246576,0.4134188455846078)

70%的准确率和召回率似乎效果还不错,但是我们现在不能盲目的认为我们的效果就真的不错了,有时候瞎猜效果也会不错。 例如:70%的数据属于类别1,每次都猜测类别是1,那么效果也能达到70%的准确率,下面我们确定一下瞎猜的准确率: 回答瞎猜猜对的概率,这个问题也不是简单的,回到概率论课堂上,在训练样本每类概率已知的情况下,测试样本瞎猜对的概率有多大呢? 随机给出一个样本:猜测类A的概率是由训练样本决定的,同时猜对的概率是由测试样本决定的,所以瞎猜猜对的概率是训练样本每类的概率分别 乘以测试样本对应类的概率之和

 /**
   * 获取模型瞎猜的概率
   * @param train 测试数据集
   * @param cvData 验证数据集
   */
  def guessProb(train: RDD[LabeledPoint], cvData: RDD[LabeledPoint]) {
    /**
     * 返回数据集合中,每一个类别的概率
     * @param data 训练数据集
     */
    def labelProb(data: RDD[LabeledPoint]): Array[Double] = {
      val labelCnt = data.map(_.label).countByValue()
      val labelProb = labelCnt.toArray.sortBy(_._1).map(_._2)
      labelProb.map(_.toDouble/labelProb.sum)
    }

    val trainProb = labelProb(train)
    val cvProb = labelProb(cvData)
    val prob = trainProb.zip(cvProb).map {
      case (a, b) => a * b
    }.sum
    println(prob)
  }

可以看到瞎猜的结果只有:0.3771281350885772 的准确率。说明70%的准确率效果确实不错,但是请注意,我们还没有优化参数, 说明我们的模型还有优化的空间。

6 决策树参数选择

主要的参数有下面几个:

  • Maximum Depth: 决策树树的最大深度,控制深度防止过拟合
  • 决策树训练算法迭代最大次数
  • 纯度测量算法 Gini Entropy (Gini纯度和熵) 通过反复查看不同参数模型评估效果,下面给出测试代码:
 /**
  * 模型评估
  * @param trainData 训练数据
  * @param cvData 交叉验证数据
  */
 def evaluate(trainData: RDD[LabeledPoint], cvData: RDD[LabeledPoint]): Unit = {
   val evaluations =
     for (impurity <- Array("gini", "entropy");
          depth <- Array(1, 20);
          bins <- Array(10, 300))
       yield {
         val model = DecisionTree.trainClassifier(
           trainData, 7, Map[Int,Int](), impurity, depth, bins)
         val predictionsAndLabels = cvData.map(example =>
           (model.predict(example.features), example.label)
         )
         val accuracy =
           new MulticlassMetrics(predictionsAndLabels).precision
         ((impurity, depth, bins), accuracy)
       }
   evaluations.sortBy(_._2).reverse.foreach(println)
 }

个人微信公众号

欢迎关注本人微信公众号,会定时发送关于大数据、机器学习、Java、Linux 等技术的学习文章,而且是一个系列一个系列的发布,无任何广告,纯属个人兴趣。
Clebeg能量集结号

© 著作权归作者所有

clebeg
粉丝 45
博文 40
码字总数 40057
作品 0
广州
程序员
私信 提问
加载中

评论(8)

开源小绵羊
开源小绵羊

引用来自“隔壁家老王”的评论

大专学历的代码狗,想学数据挖掘,学不学得了,又会不会有公司要呢?
自信一点,大专的主要原因还是年少轻狂,日子长着呢,贵在坚持。
吕秀才
吕秀才

引用来自“隔壁家老王”的评论

大专学历的代码狗,想学数据挖掘,学不学得了,又会不会有公司要呢?

引用来自“王建奎Jerrick”的评论

重要的不是学历,个人能力很重要,数据挖掘要求很深的数学功底,不然公式都看不懂

引用来自“clebeg”的评论

相信只要坚持下去,一定会有奇迹发生的一天
我一直坚信,读书百遍,其意自见。 看不明白的东西,换个时间再看,慢慢的,循环几次,就会有新的想法与思路,慢慢就懂了
clebeg
clebeg 博主

引用来自“隔壁家老王”的评论

大专学历的代码狗,想学数据挖掘,学不学得了,又会不会有公司要呢?

引用来自“王建奎Jerrick”的评论

重要的不是学历,个人能力很重要,数据挖掘要求很深的数学功底,不然公式都看不懂
相信只要坚持下去,一定会有奇迹发生的一天
clebeg
clebeg 博主

引用来自“小猪_null”的评论

这是啥语言- -
Spark开发语言 Scala
小猪_null
小猪_null
这是啥语言- -
王二铁
王二铁

引用来自“隔壁家老王”的评论

大专学历的代码狗,想学数据挖掘,学不学得了,又会不会有公司要呢?
重要的不是学历,个人能力很重要,数据挖掘要求很深的数学功底,不然公式都看不懂
开源中国首席老王
开源中国首席老王
大专学历的代码狗,想学数据挖掘,学不学得了,又会不会有公司要呢?
loki_lan
loki_lan
cool !
学途无忧网的视频怎么破解下载?学途无忧网淘宝可以买吗?

学途无忧网的视频怎么破解下载?学途无忧网淘宝可以买吗? 我想下载这几集,或者低价购买这几集 课时7:SparkSQL java操作mysql数据 课时8:Spark统计用户的收藏转换率 课时9:Spark梳理用户...

天池番薯
2016/12/19
1K
3
利用 Spark 和 scikit-learn 将你的模型训练加快 100 倍

在 Ibotta,我们训练了许多机器学习模型。这些模型为我们的推荐系统、搜索引擎、定价优化引擎、数据质量等提供动力。它们在与我们的移动应用程序交互时为数百万用户做出预测。 当我们使用 Sp...

skura
09/16
0
0
Spark之获取GBT二分类函数的概率值

  在Spark中,GBT(Gradient Boost Trees,提升树)函数用于实现机器学习中的提升树算法,目前仅支持二分类算法。笔者在实际工作中需要获得其预测的概率值,无奈该函数没有相应的方法。  ...

jclian91
2017/10/09
0
0
利用KNIME建立Spark Machine learning模型 2:泰坦尼克幸存预测

本文利用KNIME基于Spark决策树模型算法,通过对泰坦尼克的包含乘客及船员的特征属性的训练数据集进行训练,得出决策树幸存模型,并利用测试数据集对模型进行测试。 1、从Kaggle网站下载训练...

forestwater
2018/05/09
0
0
【独家】用Redis-ML模块实现实时机器学习!

刚刚结束的RedisConf2017大会,在国外是比较大型的Redis盛会了,而且已经举办多年,每次都会在全球邀请业界知名公司的技术大咖分享他们在企业应用中的典型案例和踩过的坑,以及他们正在积极探...

张冬洪 译
2017/06/23
0
0

没有更多内容

加载失败,请刷新页面

加载更多

关于AsyncTask的onPostExcute方法是否会在Activity重建过程中调用的问题

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/XG1057415595/article/details/86774575 假设下面一种情况...

shzwork
今天
6
0
object 类中有哪些方法?

getClass(): 获取运行时类的对象 equals():判断其他对象是否与此对象相等 hashcode():返回该对象的哈希码值 toString():返回该对象的字符串表示 clone(): 创建并返此对象的一个副本 wait...

happywe
今天
6
0
Docker容器实战(七) - 容器中进程视野下的文件系统

前两文中,讲了Linux容器最基础的两种技术 Namespace 作用是“隔离”,它让应用进程只能看到该Namespace内的“世界” Cgroups 作用是“限制”,它给这个“世界”围上了一圈看不见的墙 这么一...

JavaEdge
今天
8
0
文件访问和共享的方法介绍

在上一篇文章中,你了解到文件有三个不同的权限集。拥有该文件的用户有一个集合,拥有该文件的组的成员有一个集合,然后最终一个集合适用于其他所有人。在长列表(ls -l)中这些权限使用符号...

老孟的Linux私房菜
今天
7
0
面试套路题目

作者:抱紧超越小姐姐 链接:https://www.nowcoder.com/discuss/309292?type=3 来源:牛客网 面试时候的潜台词 抱紧超越小姐姐 编辑于 2019-10-15 16:14:56APP内打开赞 3 | 收藏 4 | 回复24 ...

MtrS
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部