决策树算法预测森林植被

算法介绍

回归和分类

回归算法和分类算法通常会被联系在一起,因为两者都可以通过一个或者多个值来预测一个或者多个值 he

为了能够做出预测,两者需要从一组输入和输出中学习预测规则,在学习过程中需要告诉它们问题以及问题的答案

因此,回归和分类都属于监督学习类的算法

回归是预测一个数值型的结果,例如温度,成绩等

分类是预测一个标号或者类别,例如邮件是否为辣鸡邮件,一个人是属于哪个人种

这里将使用决策树随机森林算法来完成工作,这两种算法灵活且被广泛应用

既可以用于分类问题也可以用于回归问题

特征识别

假设我们要通过某饭店商家今天的销售额来预测明天的销售额,使用机器学习算法完全没有问题

但是在这之前我们要做一些操作,今天的销售额是一个非常广泛的概念,无法直接应用到算法中

那么我们就需要对今天的销售额进行特征提取和识别,这些特征有助于我们预测明天的销售额

例如:

  • 今天的最低人流量:20
  • 今天的最高人流量:200
  • 今天平均上菜速度:3
  • 忙时是早上、中午还是晚上:中午
  • 隔壁饭店的平均人流量:60

等等,特征有时候也被称为维度或者预测指标,以上的每个特征都能够被量化,例如

今天的最低人流量为20,单位人

今天平均上菜速度为3,单位分钟

因此,今天的销售额就可以简化为一个值列表:

20,200,3,中午,60

这几个特征顺序排列就组成了特征向量,一个特征向量可以用来描述该商家每天的销售额

关于如何提取特征,要根据实际的业务场景来操作,提取出的特征能够贴切的描述具体的业务场景,这个过程甚至需要业务专家的参与

相信你已经注意到了,示例中的特征向量中并不是每个值都是数值型,例如中午

在实际应用中,这种情况很常见,通常把特征分为两种:

  • 数值型特征:可以直接使用数字表示,数字的小大是有意义的
  • 类别型特征:在几个离散值中选取一个,离散值之间的大小是没有意义的

训练样本

为了进行预测,监督学习算法需要在大量的数据集上进行训练,这些数据集不仅要包含数据特征输入,还要包含正确的输入

如上例中的特征向量是不能够被作为训练样本的,因为其没有正确的输出–今天的销售额

如果将今天的销售额2000也作为一个特征加入该数据中,该数据就能够作为一个训练样本,为机器学习算法提供了一个结构化的输入:

20,200,3,中午,60,2000

注意,这里的输出是一个数值型

回归和分类的区别在于:回归的目标为数值型特征,分类的目标为类别型特征

并不是所有的回归、分类算法都能够处理类别型特征或者类别型目标,有些算法只能处理数值型

我们可以通过适当的转换规则将类别型特征转换为数值型特征,例如:

  • 早上:1
  • 中午:2
  • 晚上:3

用数字123分别代表早上、中午和晚上,那么该训练样本就可以表示为:

20,200,3,2,60,2000

注意:有些算法对对数值型特征的大小进行猜测,一旦将类别型特征转换为数值型特征可能会造成一些影响,因为类别型特征本身的大小是没有意义的

决策树

决策树算法家族能够自然的处理署执行和类别型特征

什么是决策树呢?

事实上,我们在生活中无意中就会用到决策树所体现的推理方法,例如:

看到一部满意的新手机,但是旧手机还能用,买还是不买呢?

于是我会经历一下的过程:

1.旧手机是否已经无法忍受?是,就买

2.上一步为否,那么新手机是否能够达到非买不可的地步?是,就买

3.上一步为否,新手机的价格是否达到可以随意购买的地步?是,就买

4.上一步为否,新手机的综合性价比能否和旧手机甩开一个距离?是,就买

5.上一步为否,那么就不买

可以看到,决策树推理的过程就是一系列的是/否,在程序中表达就是一堆if/else

但是决策树有个很严重的缺点过度拟合,如何理解?

即,用训练数据训练出来的模型在训练数据中表现优异,但是对新的数据无法做出合理的预测

决策树训练出来的模型可能会对训练数据有过度拟合的问题

随机森林

随机森林是由多个随机的决策树组成的,何为随机的决策树?

随机森林中的每颗决策树中,使用的训练数据是总训练数据中随机的一部分,每层使用的决策规则都是随机选定的

随机森林的做法是属于集体智慧的,集体的平均预测应该比任何一个个体的预测要准确

正是因为随机森林构建过程中的随机性,才有了这种独立性,这是随机森林的关键

因为每颗决策树所使用的决策都是随机的一部分,所以随机森林得以有足够的时间来构建多颗决策树

也正是因为如此,森林中的每棵树更不会产生过度拟合的问题,因为使用的决策是随机的一部分

随机森林的预测是所有决策树的加权平均

程序开发

数据集

示例中将使用Covtype的森林植被数据集,该数据集是公开的,可以在线下载

该数据集的每个样本描述每块土地的若干特征,包括海拔、坡度、到水源的距离、遮阳情况和土壤类型等54个特征,并给出了目标特征–每块土地的森林植被类型

Spark Mllib的决策树

这里将使用Spark中的Mllib机器学习库,Mllib将特征向量抽象为LabeledPoint,关于LabeledPoint的具体介绍请看:

Spark(十一) – Mllib API编程 线性回归、KMeans、协同过滤演示

LabeledPoint中的Vector本质上是对多个Double类型的抽象,所以LabeledPoint只能处理数值型特征,样本数据集中已经将类别型的特征转换为数值型特征了

Mllib中的DecisionTree的输入为LabeledPoint类型,所以读取数据之后,我们需要将数据转换为LabeledPoint

val conf = new SparkConf().setAppName("DecisionTree")
val sc = new SparkContext(conf)
//读取数据
val rawData = sc.textFile("/spark_data/covtype.data")
//转换为为LabeledPoint
val data = rawData.map { line =>
  val values = line.split(",").map(_.toDouble)
  //init返回除了最后一个元素的所有元素,作为特征向量
  val feature = Vectors.dense(values.init)
  //返回最后一个目标特征,由于决策树的目标特征规定从0开始,而数据是从1开始的,所以要-1
  val label = values.last - 1
  LabeledPoint(label, feature)
}

为了能够评估训练出来的模型的准确度,我们可以将数据集划分为三部分:训练集、交叉验证集和测试集,各占80%,10%和10%

val Array(trainData, cvData, testData) = data.randomSplit(Array(0.8, 0.1, 0.1))
trainData.cache()
cvData.cache()
testData.cache()

接下来我们先训练出一个决策树模型来看看猪长什么样

/**
  * 获得评估指标
  *
  * @param model 决策树模型
  * @param data  用于交叉验证的数据集
  **/
def getMetrics(model: DecisionTreeModel, data: RDD[LabeledPoint]): MulticlassMetrics = {
  //将交叉验证数据集的每个样本的特征向量交给模型预测,并和原本正确的目标特征组成一个tuple
  val predictionsAndLables = data.map { d =>
    (model.predict(d.features), d.label)
  }
  //将结果交给MulticlassMetrics,其可以以不同的方式计算分配器预测的质量
  new MulticlassMetrics(predictionsAndLables)
}

val model = DecisionTree.trainClassifier(trainData, 7, Map[Int, Int](), "gini", 4, 100)
val metrics = getMetrics(model, cvData)

DecisionTree有两种训练模型的方法:trainClassifier和trainRegressor分别对应分类和回归问题

trainClassifier的参数:

1.训练数据集

2.目标类别个数,即结果有几种选择

3.Map中的键值分别对应Vector下标和该下标对应类别特征的取值情况,空表示所有特征都是数值型(为了方便,示例中直接取空,实际当中并不能这么使用)

4.不纯性(impurity)度量:gini或者entropy,不纯度用来衡量一个规则的好坏,好的规则可以将数据划分为等值的两部分,坏规则则相反

5.决策树的最大深度,越深的决策树越有可能产生过度拟合的问题

6.决策树的最大桶数,每层使用的决策规则的个数,越多就可能精确,花费的时候也就越多,最小的桶数应该不小于类别特征中最大的选择个数

现在来看看metrics指标中的混淆矩阵:

System.out.println(metrics.confusionMatrix.toString())

结果为:

14411.0  6564.0   17.0    1.0    0.0   0.0  317.0
5444.0   22158.0  449.0   22.0   4.0   0.0  43.0
0.0      415.0    3022.0  95.0   0.0   0.0  0.0
0.0      0.0      159.0   112.0  0.0   0.0  0.0
0.0      895.0    34.0    0.0    14.0  0.0  0.0
0.0      422.0    1228.0  108.0  0.0   0.0  0.0
1112.0   28.0     0.0     0.0    0.0   0.0  903.0

因为目标类别有7个,所以混淆矩阵是一个7*7的矩阵,每一行对应一个正确的目标特征值,每一列对应一个预测的目标特征

第i行第j列表示一个正确类别为i的样本被预测为j的次数,所以对角线上的元素代表预测正确的次数,其他表示预测错误的次数

另外,模型的精准度也可以用一个数字来表示:

System.out.println(metrics.precision)

结果为0.6996041965535718,准确率大概在69%左右

除了准确度,还有召回率等概念,还可以为每个目标特征单独查看其准确度等信息:

(0 until 7).map(target => (metrics.precision(target), metrics.recall(target))).foreach(println)

下面为输出结果:

(0.6845289541918755,0.6708390193402664)
(0.7237410535817912,0.7904577464788732)
(0.6385618166526493,0.8483240223463687)
(0.5800865800865801,0.44966442953020136)
(0.0,0.0)
(0.7283950617283951,0.03460410557184751)
(0.6814580031695721,0.4405737704918033)

可以看到,每个类别的准确度都不同,而且很诡异的是第5个类别的准确度为0,所以这个模型并不是我们想要的

我们想要的是一个符合实际的,准确度尽可能高的模型,那么该如何确定模型训练的参数呢?

可以在训练模型的时候选择不同的组合,并反馈出每个组合训练处的模型准确度结果,那么我们就可以从中选出最好的那个模型来使用:

/**
  * 在训练数据集上得到最好的参数组合
  * @param trainData 训练数据集
  * @param cvData 交叉验证数据集
  * */
def getBestParam(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 metrics = getMetrics(model, cvData)
    ((impurity, depth, bins), metrics.precision)
  }
  evaluations.sortBy(_._2).reverse.foreach(println)
}

执行的结果为:

((entropy,20,300),0.9123611325743918)
((gini,20,300),0.9062140490049623)
((entropy,20,10),0.8948814368378578)
((gini,20,10),0.8902625388485379)
((gini,1,300),0.6352272532151995)
((gini,1,10),0.6349525232232697)
((entropy,1,300),0.4855337488624461)
((entropy,1,10),0.4855337488624461)

可以看到最好的组合为第一个,准确度在91%左右,我们可以再查看一下使用最好参数训练出来的模型,各个类别的准确度为多少:

(0.899412455934195,0.9029350698376746)
(0.9193229901269393,0.9203289914928166)
(0.9222857142857143,0.9238694905552376)
(0.8263888888888888,0.8623188405797102)
(0.8294663573085846,0.7663451232583065)
(0.8596802841918295,0.8491228070175438)
(0.9454369869628199,0.9275225011842728)

现在看来比之前的要好上很多了吧

直到这里,我们一直没有使用到10%的测试数据集,如果说10%的交叉验证数据集的作用是确定在训练数据集上训练出来的模型的最好参数

那么测试数据集的作用就是评估CV数据集的最好参数,可以将训练集和CV集结合起来,然后对测试集进行以上的步骤验证来得到一个合适的参数组合

随机森林

在Spark Mllib中使用随机森林的方式和决策树差不多:

val forest = RandomForest.trainClassifier(trainData, 7, Map(10 -> 4, 11 -> 40), 20, "auto", "entropy", 30, 300)

和构架决策树的时候不同,这里不再使用空的Map

Map(10 -> 4, 11 -> 40)表示特征向量中下标为10的是类别型特征,类别取值有4个;下标为11的类别特征向量取值有40个

此时,随机森林不会再对10和11这两个特征向量做出“大小推测”等数值型特征才会有的操作

这样明显更加贴近实际,所得到的模型质量也会更好

此外随机森林还多了两个参数:

1.森林中有多少颗决策树,示例中取值为20

2.每层决策规则的选择方法,示例中为”auto”

按照决策树的评估流程对随机森林模型进行测试,可以得到关于准确度的一些指标进而衡量模型质量

至此,关于决策树和随机森林算法的模型已经构建完毕,可以使用这个模型对数据进行预测

Github源码地址

作者:@小黑

时间: 2024-10-14 19:13:22

决策树算法预测森林植被的相关文章

4-Spark高级数据分析-第四章 用决策树算法预测森林植被

预测是非常困难的,更别提预测未来. 4.1 回归简介 随着现代机器学习和数据科学的出现,我们依旧把从“某些值”预测“另外某个值”的思想称为回归.回归是预测一个数值型数量,比如大小.收入和温度,而分类则指预测标号或类别,比如判断邮件是否为“垃圾邮件”,拼图游戏的图案是否为“猫”. 将回归和分类联系在一起是因为两者都可以通过一个(或更多)值预测另一个(或多个)值.为了能够做出预测,两者都需要从一组输入和输出中学习预测规则.在学习的过程中,需要告诉它们问题及问题的答案.因此,它们都属于所谓的监督学习.

决策树预测森林植被

1. 决策树和决策森林 决策树算法家族能自然地处理类别型和数值型特征 决策树算法容易并行化 它们对数据中的离群点(outlier)具有鲁棒性(robust),这意味着一些极端或可能错误的数据点根本不会对预测产生影响 2. Covtype数据集 https://archive.ics.uci.edu/ml/machine-learning-databases/covtype/ wget https://archive.ics.uci.edu/ml/machine-learning-database

决策树算法

利用ID3算法来判断某天是否适合打网球. (1)类别属性信息熵的计算由于未分区前,训练数据集中共有14个实例, 其中有9个实例属于yes类(适合打网球的),5个实例属于no类(不适合打网球), 因此分区前类别属性的熵为: (2)非类别属性信息熵的计算,若先选择Outlook属性. (3)Outlook属性的信息增益为: (4)同理计算出其他3个非类别属性的信息增益,取最大的那个属性作为分裂节点,此例中最大的是Outlook,进而得到如下图所示: (5)上图中,针对sunny中的子训练数据集分支,

决策树算法原理

转载于:http://www.cnblogs.com/pinard/p/6050306.html (楼主总结的很好,就拿来主义了,不顾以后还是多像楼主学习) 决策树算法在机器学习中算是很经典的一个算法系列了.它既可以作为分类算法,也可以作为回归算法,同时也特别适合集成学习比如随机森林.本文就对决策树算法原理做一个总结,上篇对ID3, C4.5的算法思想做了总结,下篇重点对CART算法做一个详细的介绍.选择CART做重点介绍的原因是scikit-learn使用了优化版的CART算法作为其决策树算法

机器学习——决策树算法原理及案例

机器学习在各个领域都有广泛的应用,特别在数据分析领域有着深远的影响.决策树是机器学习中最基础且应用最广泛的算法模型.本文介绍了机器学习的相关概念.常见的算法分类和决策树模型及应用.通过一个决策树案例,着重从特征选择.剪枝等方面描述决策树的构建,讨论并研究决策树模型评估准则.最后基于 R 语言和 SPSS Modeler这两个工具,分别设计与实现了决策树模型的应用实例. 1.机器学习概念 机器学习 (Machine Learning) 是近 20 多年兴起的一门多领域交叉学科,涉及概率论.统计学.

机器学习之决策树算法

机器学习在各个领域都有广泛的应用,特别在数据分析领域有着深远的影响.决策树是机器学习中最基础且应用最广泛的算法模型.本文介绍了机器学习的相关概念.常见的算法分类和决策树模型及应用.通过一个决策树案例,着重从特征选择.剪枝等方面描述决策树的构建,讨论并研究决策树模型评估准则.最后基于 R 语言和 SPSS 这两个工具,分别设计与实现了决策树模型的应用实例. 机器学习概念  机器学习 (Machine Learning) 是近 20 多年兴起的一门多领域交叉学科,涉及概率论.统计学.逼近论.凸分析.

决策树算法(二)

在决策树算法原理(上)这篇里,我们讲到了决策树里ID3算法,和ID3算法的改进版C4.5算法.对于C4.5算法,我们也提到了它的不足,比如模型是用较为复杂的熵来度量,使用了相对较为复杂的多叉树,只能处理分类不能处理回归等.对于这些问题, CART算法大部分做了改进.CART算法也就是我们下面的重点了.由于CART算法可以做回归,也可以做分类,我们分别加以介绍,先从CART分类树算法开始,重点比较和C4.5算法的不同点.接着介绍CART回归树算法,重点介绍和CART分类树的不同点.然后我们讨论CA

决策树算法原理(下)

1. CART分类树算法的最优特征选择方法 2. CART分类树算法对于连续特征和离散特征处理的改进 3. CART分类树建立算法的具体流程 4. CART回归树建立算法 5. CART树算法的剪枝 6. CART算法小结 7. 决策树算法小结 在决策树算法原理(上)这篇里,我们讲到了决策树里ID3算法,和ID3算法的改进版C4.5算法.对于C4.5算法,我们也提到了它的不足,比如模型是用较为复杂的熵来度量,使用了相对较为复杂的多叉树,只能处理分类不能处理回归等.对于这些问题, CART算法大部

scikit-learn决策树算法类库使用小结

参考:http://www.cnblogs.com/pinard/p/6056319.html 之前对决策树的算法原理做了总结,包括决策树算法原理(上)和决策树算法原理(下).今天就从实践的角度来介绍决策树算法,主要是讲解使用scikit-learn来跑决策树算法,结果的可视化以及一些参数调参的关键点. 1. scikit-learn决策树算法类库介绍 scikit-learn决策树算法类库内部实现是使用了调优过的CART树算法,既可以做分类,又可以做回归.分类决策树的类对应的是Decision