Spark Mllib之集成算法:梯度提升树和随机森林

2024-09-01 08:32

本文主要是介绍Spark Mllib之集成算法:梯度提升树和随机森林,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

微信公众号:数据挖掘与分析学习

集成算法是将其他基础模型进行组合的一中算法。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)。
  2. 考虑在每个树节点处分割的不同随机特征子集。

除了这些随机化之外,决策树训练的方式与单个决策树的方式相同。

2)预测

要对新实例进行预测,随机森林必须整合各个决策树的预测。对于分类和回归,这种整合的方式不同。

分类:多数票原则。 每棵树的预测都算作一个类的投票。预计该标签是获得最多选票的类别。

回归:平均。 每棵树预测一个真实的值。 预测标签是各个树预测的平均值。

 

2.2 用法提示

我们通过讨论各种参数总结一些使用随机森林的指南。

我们提到的前两个参数是最重要的,调整它们通常可以提高性能:

  1. numTrees:森林中的树数量。

1)增加树的数量将减少预测的方差,从而提高模型的测试准确性。

2)训练时间大致呈线性增加。

  1. maxDepth:森林中每棵树的最大深度。

1)增加深度使模型更具表现力和更强大。 然而,深树需要更长的时间进行训练,而且更容易过度拟合。

2)通常,在使用更深的树来训练随机森林比使用单个决策树时更深的树更好。一棵树比随机森林更容易过度拟合(因为森林中多棵树的平均值减少了差异)。

 

接下来的两个参数通常不需要调整。 但是,他们可以调整以加快训练。

  1. subsamplingRate:此参数指定用于训练随机森林中每棵树的数据集的大小,作为原始数据集大小的一部分。建议使用默认值(1.0),但减少此分数可以加快训练速度。
  2. featureSubsetStrategy:用作每个树节点处的分割候选的特征数。该数字被指定为特征总数的占比或函数。减少这个数字会加快训练速度,但如果太低,有时会影响性能。

 

2.3 代码示例

1)分类

下面的示例演示如何加载LIBSVM数据文件,将其解析为LabeledPoint的RDD,然后使用随机森林执行分类。 计算测试误差以测量算法精度。

package com.cb.spark.mllib;

 

import java.util.HashMap;

import java.util.Map;

 

import javax.swing.plaf.basic.BasicInternalFrameTitlePane.SystemMenuBar;

 

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.spark.mllib.regression.LabeledPoint;

import org.apache.spark.mllib.tree.RandomForest;

import org.apache.spark.mllib.tree.model.RandomForestModel;

import org.apache.spark.mllib.util.MLUtils;

 

import scala.Tuple2;

 

public class JavaRandomForestClassificationExample {

    public static void main(String[] args) {

       SparkConf sparkConf = new SparkConf().setAppName("JavaRandomForestClassificationExample").setMaster("local");

       JavaSparkContext jsc = new JavaSparkContext(sparkConf);

 

       // 加载数据

       String path = "F:\\Learning\\java\\project\\LearningSpark\\src\\main\\resources\\sample_libsvm_data.txt";

       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 = RandomForest.trainClassifier(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) testData.count();

       System.out.println("Test err:" + testErr);

       System.out.println(model.toDebugString());

    }

}

 

 

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.spark.mllib.regression.LabeledPoint;

import org.apache.spark.mllib.tree.RandomForest;

import org.apache.spark.mllib.tree.model.RandomForestModel;

import org.apache.spark.mllib.util.MLUtils;

 

import scala.Tuple2;

 

public class JavaRandomForestRegressionExample {

    public static void main(String[] args) {

       SparkConf sparkConf = new SparkConf().setAppName("JavaRandomForestClassificationExample").setMaster("local");

       JavaSparkContext jsc = new JavaSparkContext(sparkConf);

 

       // 加载数据

       String path = "F:\\Learning\\java\\project\\LearningSpark\\src\\main\\resources\\sample_libsvm_data.txt";

       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 = "variance";

       Integer maxDepth = 4;

       Integer maxBins = 32;

       Integer seed = 12345;

 

       RandomForestModel model = RandomForest.trainRegressor(training, categoricalFeaturesInfo, numTrees,

              featureSubsetStrategy, impurity, maxDepth, maxBins, seed);

       JavaPairRDD<Double, Double> predictionAndLabel = testData

              .mapToPair(p -> new Tuple2<>(model.predict(p.features()), p.label()));

       double testMSE = predictionAndLabel.mapToDouble(pl -> {

           double diff = pl._1() - pl._2();

           return diff * diff;

       }).mean();

       System.out.println("均方误差:"+testMSE);

    }

}

 

 

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.spark.mllib.regression.LabeledPoint;

import org.apache.spark.mllib.tree.GradientBoostedTrees;

import org.apache.spark.mllib.tree.configuration.BoostingStrategy;

import org.apache.spark.mllib.tree.model.GradientBoostedTreesModel;

import org.apache.spark.mllib.util.MLUtils;

 

import scala.Tuple2;

 

public class JavaGradientBoostingClassificationExample {

    public static void main(String[] args) {

       SparkConf sparkConf = new SparkConf().setAppName("JavaRandomForestClassificationExample").setMaster("local");

       JavaSparkContext jsc = new JavaSparkContext(sparkConf);

 

       // 加载数据

       String path = "F:\\Learning\\java\\project\\LearningSpark\\src\\main\\resources\\sample_libsvm_data.txt";

       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];

 

       BoostingStrategy boostingStrategy = BoostingStrategy.defaultParams("Classification");

       boostingStrategy.setNumIterations(3);

       boostingStrategy.getTreeStrategy().setNumClasses(2);

       boostingStrategy.getTreeStrategy().setMaxDepth(5);

       Map<Integer, Integer> categoricalFeaturesInfo = new HashMap<>();

        boostingStrategy.treeStrategy().setCategoricalFeaturesInfo(categoricalFeaturesInfo);

       GradientBoostedTreesModel model = GradientBoostedTrees.train(training, boostingStrategy);

 

       JavaPairRDD<Double, Double> predictionAndLabel = testData

              .mapToPair(p -> new Tuple2<>(model.predict(p.features()), p.label()));

       double testErr = predictionAndLabel.filter(pl -> !pl.equals(pl._2())).count() / (double) testData.count();

       System.out.println("Test Err:" + testErr);

       System.out.println(model.toDebugString());

    }

}

 

 

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.spark.mllib.regression.LabeledPoint;

import org.apache.spark.mllib.tree.GradientBoostedTrees;

import org.apache.spark.mllib.tree.configuration.BoostingStrategy;

import org.apache.spark.mllib.tree.model.GradientBoostedTreesModel;

import org.apache.spark.mllib.util.MLUtils;

 

import scala.Tuple2;

 

public class JavaGradientBoostingRegressionExample {

    public static void main(String[] args) {

       SparkConf sparkConf = new SparkConf().setAppName("JavaRandomForestClassificationExample").setMaster("local");

       JavaSparkContext jsc = new JavaSparkContext(sparkConf);

 

       // 加载数据

       String path = "F:\\Learning\\java\\project\\LearningSpark\\src\\main\\resources\\sample_libsvm_data.txt";

       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];

 

       BoostingStrategy boostingStrategy = BoostingStrategy.defaultParams("Regression");

       boostingStrategy.setNumIterations(3);

       boostingStrategy.getTreeStrategy().setMaxDepth(5);

       Map<Integer, Integer> categoricalFeaturesInfo = new HashMap<>();

        boostingStrategy.treeStrategy().setCategoricalFeaturesInfo(categoricalFeaturesInfo);

       GradientBoostedTreesModel model = GradientBoostedTrees.train(training, boostingStrategy);

       JavaPairRDD<Double, Double> predictionAndLabel = testData

               .mapToPair(p -> new Tuple2<>(model.predict(p.features()), p.label()));

      

       double testMSE=predictionAndLabel.mapToDouble(pl -> {

           double diff=pl._1()-pl._2();

           return diff*diff;

       }).mean();

       System.out.println("测试均方误差为:"+testMSE);

    }

}

 

 

这篇关于Spark Mllib之集成算法:梯度提升树和随机森林的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1126442

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

秋招最新大模型算法面试,熬夜都要肝完它

💥大家在面试大模型LLM这个板块的时候,不知道面试完会不会复盘、总结,做笔记的习惯,这份大模型算法岗面试八股笔记也帮助不少人拿到过offer ✨对于面试大模型算法工程师会有一定的帮助,都附有完整答案,熬夜也要看完,祝大家一臂之力 这份《大模型算法工程师面试题》已经上传CSDN,还有完整版的大模型 AI 学习资料,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

dp算法练习题【8】

不同二叉搜索树 96. 不同的二叉搜索树 给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。 示例 1: 输入:n = 3输出:5 示例 2: 输入:n = 1输出:1 class Solution {public int numTrees(int n) {int[] dp = new int

【区块链 + 人才服务】区块链集成开发平台 | FISCO BCOS应用案例

随着区块链技术的快速发展,越来越多的企业开始将其应用于实际业务中。然而,区块链技术的专业性使得其集成开发成为一项挑战。针对此,广东中创智慧科技有限公司基于国产开源联盟链 FISCO BCOS 推出了区块链集成开发平台。该平台基于区块链技术,提供一套全面的区块链开发工具和开发环境,支持开发者快速开发和部署区块链应用。此外,该平台还可以提供一套全面的区块链开发教程和文档,帮助开发者快速上手区块链开发。

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯: