SparkMllib之集成算法:梯度提升树和随机森林
:数据挖掘与分析学习
集成算法是将其他基础模型进⾏组合的⼀中算法。spark.mllib⽀持两种主要的集成算法:GradientBoostedTrees和RandomForest。 两者都使⽤决策树作为基础模型。
1.梯度提升树和随机森林
Gradient-Boosted Trees(GBTs)和Random Forest都是⽤于学习树集成的算法,但训练过程是不同的。 有⼏个实际的权衡点:GBT⼀次训练⼀棵树,因此它们⽐随机森林需要更长时间的训练。 随机森林可以并⾏训练多棵树。
另⼀⽅⾯,使⽤具有GBT训练较⼩(较浅)树⽐使⽤随机森林更有优势,并且训练较⼩树需要的时间更短。
随机森林可能不太容易过度拟合。在随机森林中训练更多树可以降低过拟合的可能性,但是使⽤GBT训练更多树会增加过拟合的可能性。(在统计语⾔中,随机森林通过使⽤更多树来减少⽅差,⽽GBT通过使⽤更多树来减少偏差。)
随机森林更容易调整,因为性能随树数量增加⽽改善(对于GBT来说,如果树⽊数量增长太⼤,性能可能会开始降低)。
简⽽⾔之,两种算法都很有效,并且应基于特定数据集来选择合适的算法。
2 随机森林
随机森林是以决策树作为基础模型的集成算法。随机森林是机器学习模型中⽤于分类和回归的最成功的模型之⼀。通过组合⼤量的决策树来降低过拟合的风险。与决策树⼀样,随机森林处理分类特征,扩展到多类分类设置,不需要特征缩放,并且能够捕获⾮线性和特征交互。
spark.mllib⽀持使⽤连续和分类特征的⼆分类和多类分类以及回归的随机森林。spark.mllib使⽤现有的决策树实现随机森林。
2.1 基本算法
随机森林分别训练⼀组决策树,因此训练可以并⾏完成。该算法将随机性注⼊训练过程,以使每个决策树略有不同。结合每棵树的预测可以减少预测的⽅差,提⾼测试数据的性能。
1)训练
注⼊训练过程的随机性包括:
1. 在每次迭代时对原始数据集进⾏⼆次采样,以获得不同的训练集(例如,bootstrapping)。
java中split的用法2. 考虑在每个树节点处分割的不同随机特征⼦集。
除了这些随机化之外,决策树训练的⽅式与单个决策树的⽅式相同。
2)预测
要对新实例进⾏预测,随机森林必须整合各个决策树的预测。对于分类和回归,这种整合的⽅式不同。
分类:多数票原则。 每棵树的预测都算作⼀个类的投票。预计该标签是获得最多选票的类别。
回归:平均。 每棵树预测⼀个真实的值。 预测标签是各个树预测的平均值。
2.2 ⽤法提⽰
我们通过讨论各种参数总结⼀些使⽤随机森林的指南。
我们提到的前两个参数是最重要的,调整它们通常可以提⾼性能:
1. numTrees:森林中的树数量。
1)增加树的数量将减少预测的⽅差,从⽽提⾼模型的测试准确性。
2)训练时间⼤致呈线性增加。
1. maxDepth:森林中每棵树的最⼤深度。
1)增加深度使模型更具表现⼒和更强⼤。 然⽽,深树需要更长的时间进⾏训练,⽽且更容易过度拟合。
2)通常,在使⽤更深的树来训练随机森林⽐使⽤单个决策树时更深的树更好。⼀棵树⽐随机森林更容易过度拟合(因为森林中多棵树的平均值减少了差异)。
接下来的两个参数通常不需要调整。 但是,他们可以调整以加快训练。
1. subsamplingRate:此参数指定⽤于训练随机森林中每棵树的数据集的⼤⼩,作为原始数据集⼤⼩的⼀部分。建议使⽤默认值
(1.0),但减少此分数可以加快训练速度。
2. featureSubsetStrategy:⽤作每个树节点处的分割候选的特征数。该数字被指定为特征总数的占⽐或函数。减少这个数字会加快训
练速度,但如果太低,有时会影响性能。
2.3 代码⽰例
1)分类
下⾯的⽰例演⽰如何加载LIBSVM数据⽂件,将其解析为LabeledPoint的RDD,然后使⽤随机森林执⾏分类。 计算测试误差以测量算法精度。
JavaRDD<LabeledPoint> data = MLUtils.loadLibSVMFile(jsc.sc(), path).toJavaRDD();
// 将数据集划分为训练数据和测试数据
JavaRDD<LabeledPoint>[] splits = data.randomSplit(new double[] { 0.7, 0.3 });
JavaRDD<LabeledPoint> training = splits[0];
JavaRDD<LabeledPoint> testData = splits[1];
// 随机森林模型训练
Integer numClasses = 2;
Map<Integer, Integer> categoricalFeaturesInfo = new HashMap<>();
Integer numTrees = 3; // 树的数量
String featureSubsetStrategy = "auto"; // 算法⾃动选择
String impurity = "gini";
Integer maxDepth = 5;
Integer maxBins = 32;
Integer seed = 12345;
RandomForestModel model = ainClassifier(training, numClasses,
categoricalFeaturesInfo, numTrees,
featureSubsetStrategy, impurity, maxDepth, maxBins, seed);
JavaPairRDD<Double, Double> predictionAndLabel = testData
.mapToPair(p -> new Tuple2<>(model.predict(p.features()), p.label()));
double testErr = predictionAndLabel.filter(pl -> !pl._1.equals(pl._2())).count() / (double) unt();
System.out.println("Test err:" + testErr);
System.out.DebugString());
}
}
2)回归
下⾯的⽰例演⽰了如何加载LIBSVM数据⽂件,将其解析为LabeledPoint的RDD,然后使⽤随机森林执⾏回归。 最后计算均⽅误差(MSE)以评估拟合优度。
package com.cb.spark.mllib;
import java.util.HashMap;
import java.util.Map;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.ssion.LabeledPoint;
import org.apache.RandomForest;
import org.apache.odel.RandomForestModel;
import org.apache.spark.mllib.util.MLUtils;
import scala.Tuple2;
public class JavaRandomForestRegressionExample {
public static void main(String[] args) {
3.梯度提升树
梯度提升树(GBT)是决策树的集成算法。GBT迭代地训练决策树以最⼩化损失函数。与决策树⼀样,GBT处理分类特征,扩展到多类分类设置,不需要特征缩放,并且能够捕获⾮线性和特征交互。
spark.mllib⽀持使⽤连续和分类特征进⾏⼆分类和回归的GBT。spark.mllib使⽤现有的决策树实现来实现GBT。注意:GBT尚不⽀持多类分类。 对于多类问题,请使⽤决策树或随机森林。
3.1 基本算法
梯度提升迭代地训练⼀系列决策树。在每次迭代时,算法使⽤当前集合来预测每个训练实例的标签,然后将预测与真实标签进⾏⽐较。重新标记数据集以更加重视预测较差的训练实例。因此,在下⼀次迭代中,决策树将帮助纠正先前的错误。
重新标记实例的具体机制由损失函数定义(下⾯讨论)。 每次迭代,GBT进⼀步减少训练数据的这种损失函数。
1. 损失
下表列出了spark.mllib中GBT当前⽀持的损失。 请注意,每种损失都适⽤于分类或回归。
注意:N=实例数。 yi =实例i的标签。 xi=实例i的特征。 F(xi)=模型的预测标签。
3.2 ⽤法提⽰
我们通过讨论各种参数总结了⼀些使⽤GBT的指南。
loss:根据数据集的不同,不同的损失会产⽣明显不同的结果。
numIterations:设置集成中树的数量。每次迭代都会⽣成⼀棵树。 增加此数字可使模型更具表现⼒,从⽽提⾼训练数据的准确性。
但是,如果测试时间过长,则测试时精度可能会受到影响。
learningRate:不需要调整此参数。 如果算法⾏为看起来不稳定,则降低此值可以提⾼稳定性。
algo:使⽤树[策略]参数设置算法或任务(分类与回归)。
3.3 训练时验证
当训练更多的树时,梯度提升会过拟合。 为了防⽌过拟合,在训练时进⾏验证很有⽤。提供了runWithValidation⽅法以使⽤此选项。它需要⼀对RDD作为参数,第⼀个是训练数据集,第⼆个是验证数据集。
当验证误差的改进不超过某个容差(由BoostingStrategy中的validationTol参数提供)时,将停⽌训练。实际上,验证误差最初会降低,之后会增加。可能存在验证误差不会单调变化的情况,建议⽤户设置⾜够⼤的负容差并使⽤evaluateEachIteration(每次迭代给出误差或损失)检查验证曲线以调整迭代次数。
1)分类
下⾯的⽰例演⽰了如何加载LIBSVM数据⽂件,将其解析为LabeledPoint的RDD,然后使⽤具有⽇志丢失的Gradient-Boosted树执⾏分类。 计算测试误差以测量算法精度。
package com.cb.spark.mllib;
import java.util.HashMap;
import java.util.Map;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.ssion.LabeledPoint;
import org.apache.GradientBoostedTrees;
import org.apache.onfiguration.BoostingStrategy;
import org.apache.odel.GradientBoostedTreesModel;
import org.apache.spark.mllib.util.MLUtils;
import scala.Tuple2;
public class JavaGradientBoostingClassificationExample {
public static void main(String[] args) {
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论