分享

Spark 高级分析:第四章第9,10节

feilong 2018-2-2 10:25:01 发表于 连载型 [显示全部楼层] 回帖奖励 阅读模式 关闭右栏 2 6047
问题导读

1.如何调优决策树?
2.怎样修正分类特征?
3.参数最大深度对决策树结果有何影响?





上一篇:Spark 高级分析:第四章第8节
http://www.aboutyun.com/forum.php?mod=viewthread&tid=23874&extra=

第9节 调优决策树

从数据上看,不太明显的是,不纯净的测量会带来更好的准确性,或者是最大深度或是容器的数量足够的,而未过度。幸运的是,就像前一章一样,让Spark尝试一系列这些值的组合并报告结果很简单:
[mw_shl_code=scala,true]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)
...
((entropy,20,300),0.9125545571245186)
((gini,20,300),0.9042533162173727)
((gini,20,10),0.8854428754813863)
((entropy,20,10),0.8848951647411211)
((gini,1,300),0.6358065896448438)
((gini,1,10),0.6355669661959777)
((entropy,1,300),0.4861446298673513)
((entropy,1,10),0.4861446298673513)[/mw_shl_code]
显然,最大深度1太小,产生的结果较差。更多的容器会有一点帮助。这两种杂质措施似乎是可比的(对于最大深度的合理设置)。这个过程可以继续探索这些超参数。更多的容器不应该受到损害,但是会减慢构建过程并增加内存使用。在所有情况下都应采取不洁净措施。
更多的深度在某种程度上会有所帮助。

到目前为止,这里的示例代码忽略了10%的数据作为测试集。如果CV集的目的是为了评估参数是否适合训练集,然后测试集的目的是评估超参数“适合”CV集。也就是说,测试集确保了对最终选择的模型及其超参数的准确性的无偏估计。

上面的测试表明,基于熵的杂质,最大深度20和300容器是目前已知的最好的超参数设置,达到了大约91.2%的精度。然而,在这些模型的构建过程中总是存在随机性的因素。碰巧这种模型和评估结果可能非常好。最好的模型和评估结果更有可能受益于一点这种运气,因此,如果它过于适合,准确度估计很可能是乐观的。

为了真正评估这一最佳模型在未来的例子中可能表现得如何,我们需要在不被用来训练它的例子中进行评估。但是我们也需要避免CV集中用来评估的例子。这就是为什么第三个子集,测试集,被留存了。最后一步,可以使用超参数在训练和CV集合上建立一个模型,并像之前一样进行评估:
[mw_shl_code=scala,true]val model = DecisionTree.trainClassifier(trainData.union(cvData), 7, Map[Int,Int](), "entropy", 20, 300)[/mw_shl_code]
结果是大约91.6%的准确性,大致相同,所以最初的估计是可靠的。

这是一个很有趣的点来重新讨论过度拟合的问题。正如前面所讨论的,可以很好地构建一个决策树,它是如此的深入和详细,它与给定的训练示例非常匹配,但是不能推广到其他示例,因为它与训练数据的特性和噪声太接近了。这实际上是大多数机器学习算法的共同问题,而不仅仅是决策树。

当决策树过度拟合时,在与模型匹配的相同训练数据上运行时,它会显示出较高的精度,但在其他示例中精度较低。上述分析表明,最终模型的准确性大约为91.6%。精确度可以很容易地根据模型所训练的相同数据进行评估。这使其精确度达到了95.3%。

差异并不大,但表明决策树在一定程度上超出了训练数据。更低的最大深度可能是更好的选择。

第10节 修正分类特征

到目前为止,代码示例已经包含了参数Map[Int,Int](),没有解释。与7一样,该参数指定输入中每个类别特性的不同值的数量。该映射中的键是输入向量中特征的索引,值是不同的值计数。此时,实现需要提前了解这些信息。

空Map()实际上表示所有的特性都应该被视为数字。所有的特征都是数字,但有些是概念上的范畴特征。正如前面提到的,将简单地映射到不同数字的分类特性作为数字值是错误的,因为该算法将尝试从没有意义的排序中学习。

值得庆幸的是,这里的分类特性是一个热编码为几个二进制0/1值。将这些单独的特性作为数字处理是没问题的,因为“数字”特性的任何决策规则都会选择0到1之间的阈值,所有的值都是相等的,因为所有的值都是0或1。

当然,这种编码迫使决策树算法单独考虑底层分类特性的值。在学习“适当”的范畴特征时,它不受限制。也就是说,有一个40个值的分类特性,决策树可以根据一个决策的类别来创建决策,这可能更直接和最优。另一方面,拥有40个数字特征代表一个40个值的分类特性也会增加内存使用,并使事情变慢。

那么取消一个热编码又如何呢?对输入的下列替代解析将两种分类特性从一热编码转换为一系列不同的数值:
[mw_shl_code=scala,true]val data = rawData.map { line =>
val values = line.split(',').map(_.toDouble)
val wilderness = values.slice(10, 14).indexOf(1.0).toDouble
val soil = values.slice(14, 54).indexOf(1.0).toDouble
val featureVector =
Vectors.dense(values.slice(0, 10) :+ wilderness :+ soil)
val label = values.last - 1
LabeledPoint(label, featureVector)
}[/mw_shl_code]
我们可以重复同样的过程,训练/CV/测试的分割和评估。这一次,给出了两个新的分类特性的不同值的计数,这使得这些特性被视为分类的,而不是数字的。决策树要求容器的数量必须增加到至少40个,因为土壤特性有40个不同的值。考虑到之前的结果,我们建造了更深的树,DecisionTree目前所支持的最大的深度30。最后,展示了训练和CV的准确性:
[mw_shl_code=scala,true]val evaluations =
for (impurity <- Array("gini", "entropy");
depth <- Array(10, 20, 30);
bins <- Array(40, 300))
yield {
val model = DecisionTree.trainClassifier(
trainData, 7, Map(10 -> 4, 11 -> 40),
impurity, depth, bins)
val trainAccuracy = getMetrics(model, trainData).precision
val cvAccuracy = getMetrics(model, cvData).precision
((impurity, depth, bins), (trainAccuracy, cvAccuracy))
}
...
((entropy,30,300),(0.9996922984231909,0.9438383977425239))
((entropy,30,40),(0.9994469978654548,0.938934581368939))
((gini,30,300),(0.9998622874061833,0.937127912178671))
((gini,30,40),(0.9995180059216415,0.9329467634811934))
((entropy,20,40),(0.9725865867933623,0.9280773598540899))
((gini,20,300),(0.9702347139020864,0.9249630062975326))
((entropy,20,300),(0.9643948392205467,0.9231391307340239))
((gini,20,40),(0.9679344832334917,0.9223820503114354))
((gini,10,300),(0.7953203539213661,0.7946763481193434))
((gini,10,40),(0.7880624698753701,0.7860215423792973))
((entropy,10,40),(0.78206336500723,0.7814790598437661))
((entropy,10,300),(0.7821903188046547,0.7802746137169208))[/mw_shl_code]
如果你在集群上运行此操作,可能会注意到,树构建过程的完成速度比以前快了好几倍。

深度为30时,训练集近乎完美;它在某种程度上是过度拟合的,但仍然在交叉验证集上提供了最佳的准确性。测试集的准确率为94.5%。分类器将分类特征作为分类特征,提高了近3%的准确率。

已有(2)人评论

跳转到指定楼层
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条