Spark中的CrossValidation

  • Spark中采用是k折交叉验证 (k-fold cross validation)。举个例子,例如10折交叉验证(10-fold cross validation),将数据集分成10份,轮流将其中9份做训练1份做验证,10次的结果的均值作为对算法精度的估计。
  • 10折交叉检验最常见,是因为通过利用大量数据集、使用不同学习技术进行的大量试验,表明10折是获得最好误差估计的恰当选择,而且也有一些理论根据可以证明这一点。但这并非最终结论,争议仍然存在。而且似乎5折或者20折与10折所得出的结果也相差无几。
  • 交叉检验常用于分析模型的泛化能力,提高模型的稳定。相对于手工探索式的参数调试,交叉验证更具备统计学上的意义。
  • 在Spark中,Cross Validation和ParamMap(“参数组合”的Map)结合使用。具体做法是,针对特定的Param组合,CrossValidator计算K (K 折交叉验证)个评估分数的平均值。然后和其它“参数组合”CrossValidator计算结果比较,完成所有的比较后,将最优的“参数组合”挑选出来,这“最优的一组参数”将用在整个训练数据集上重新训练(re-fit),得到最终的Model。
  • 也就是说,通过交叉验证,找到了最佳的”参数组合“,利用这组参数,在整个训练集上可以训练(fit)出一个泛化能力强,误差相对最小的的最佳模型。
  • 很显然,交叉验证计算代价很高,假设有三个参数:参数alpha有3中选择,参数beta有4种选择,参数gamma有4中选择,进行10折计算,那么将进行(3×4×4)×10=480次模型训练。

Spark documnets 原文: 
(1)CrossValidator begins by splitting the dataset into a set of folds which are used as separate training and test datasets. E.g., with k=3folds, CrossValidator will generate 3 (training, test) dataset pairs, each of which uses 2/3 of the data for training and 1/3 for testing. To evaluate a particular ParamMap, CrossValidator computes the average evaluation metric for the 3 Models produced by fitting the Estimator on the 3 different (training, test) dataset pairs. 
(2)After identifying the best ParamMap, CrossValidator finally re-fits the Estimator using the best ParamMap and the entire dataset. 
(3)Using CrossValidator to select from a grid of parameters.Note that cross-validation over a grid of parameters is expensive. E.g., in the example below, the parameter grid has 3 values for hashingTF.numFeatures and 2 values for lr.regParam, and CrossValidator uses 2 folds. This multiplies out to (3×2)×2=12different models being trained. In realistic settings, it can be common to try many more parameters and use more folds (k=3 and k=10 are common). In other words, using CrossValidator can be very expensive. However, it is also a well-established method for choosing parameters which is more statistically sound than heuristic hand-tuning.

计算流程

//Spark Version 2.0
package my.spark.ml.practice; import java.io.IOException; import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.ml.Pipeline;
import org.apache.spark.ml.PipelineStage;
import org.apache.spark.ml.evaluation.RegressionEvaluator;
import org.apache.spark.ml.param.ParamMap;
import org.apache.spark.ml.recommendation.ALS;
import org.apache.spark.ml.tuning.CrossValidator;
import org.apache.spark.ml.tuning.CrossValidatorModel;
import org.apache.spark.ml.tuning.ParamGridBuilder;
import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.SparkSession; /**ALS算法协同过滤推荐算法
* 使用Spark 2.0 基于Pipeline,ParamMap,CrossValidation
* 对超参数进行调优,并进行模型选择
*/ public class MyCrossValidation {
public static void main(String[] args) throws IOException{
SparkSession spark=SparkSession
.builder()
.appName("myCrossValidation")
.master("local[4]")
.getOrCreate();
//屏蔽日志
Logger.getLogger("org.apache.spark").setLevel(Level.WARN);
Logger.getLogger("org.eclipse.jetty.server").setLevel(Level.OFF);
//加载数据
JavaRDD<Rating> ratingsRDD = spark
.read().textFile("/home/hadoop/spark/spark-2.0.0-bin-hadoop2.6" +
"/data/mllib/als/sample_movielens_ratings.txt").javaRDD()
.map(new Function<String, Rating>() {
public Rating call(String str) {
return Rating.parseRating(str);
}
});
//将整个数据集划分为训练集和测试集
//注意training集将用于Cross Validation,而test集将用于最终模型的评估
//在traning集中,在Croos Validation时将进一步划分为K份,每次留一份作为
//Validation,注意区分:ratings.randomSplit()分出的Test集和K 折留
//下验证的那一份完全不是一个概念,也起着完全不同的作用,一定不要相混淆
Dataset<Row> ratings = spark.createDataFrame(ratingsRDD, Rating.class);
Dataset<Row>[] splits = ratings.randomSplit(new double[]{0.8, 0.2});
Dataset<Row> training = splits[0];
Dataset<Row> test = splits[1]; // Build the recommendation model using ALS on the training data
ALS als=new ALS()
.setMaxIter(8)
.setRank(20).setRegParam(0.8)
.setUserCol("userId")
.setItemCol("movieId")
.setRatingCol("rating")
.setPredictionCol("predict_rating");
/*
* (1)秩Rank:模型中隐含因子的个数:低阶近似矩阵中隐含特在个数,因子一般多一点比较好,
* 但是会增大内存的开销。因此常在训练效果和系统开销之间进行权衡,通常取值在10-200之间。
* (2)最大迭代次数:运行时的迭代次数,ALS可以做到每次迭代都可以降低评级矩阵的重建误差,
* 一般少数次迭代便能收敛到一个比较合理的好模型。
* 大部分情况下没有必要进行太对多次迭代(10次左右一般就挺好了)
* (3)正则化参数regParam:和其他机器学习算法一样,控制模型的过拟合情况。
* 该值与数据大小,特征,系数程度有关。此参数正是交叉验证需要验证的参数之一。
*/
// Configure an ML pipeline, which consists of one stage
//一般会包含多个stages
Pipeline pipeline=new Pipeline().
setStages(new PipelineStage[] {als});
// We use a ParamGridBuilder to construct a grid of parameters to search over.
ParamMap[] paramGrid=new ParamGridBuilder()
.addGrid(als.rank(),new int[]{5,10,20})
.addGrid(als.regParam(),new double[]{0.05,0.10,0.15,0.20,0.40,0.80})
.build(); // CrossValidator 需要一个Estimator,一组Estimator ParamMaps, 和一个Evaluator.
// (1)Pipeline作为Estimator;
// (2)定义一个RegressionEvaluator作为Evaluator,并将评估标准设置为“rmse”均方根误差
// (3)设置ParamMap
// (4)设置numFolds CrossValidator cv=new CrossValidator()
.setEstimator(pipeline)
.setEvaluator(new RegressionEvaluator()
.setLabelCol("rating")
.setPredictionCol("predict_rating")
.setMetricName("rmse"))
.setEstimatorParamMaps(paramGrid)
.setNumFolds(5); // 运行交叉检验,自动选择最佳的参数组合
CrossValidatorModel cvModel=cv.fit(training);
//保存模型
cvModel.save("/home/hadoop/spark/cvModel_als.modle"); //System.out.println("numFolds: "+cvModel.getNumFolds());
//Test数据集上结果评估
Dataset<Row> predictions=cvModel.transform(test);
RegressionEvaluator evaluator = new RegressionEvaluator()
.setMetricName("rmse")//RMS Error
.setLabelCol("rating")
.setPredictionCol("predict_rating");
Double rmse = evaluator.evaluate(predictions);
System.out.println("RMSE @ test dataset " + rmse);
//Output: RMSE @ test dataset 0.943644792277118
}
}

备注:程序运行需要定义Rating Class 在下面链接里可以找到: http://spark.apache.org/docs/latest/ml-collaborative-filtering.html

Spark2.0机器学习系列之2:基于Pipeline、交叉验证、ParamMap的模型选择和超参数调优的更多相关文章

  1. Spark2.0机器学习系列之3:决策树

    概述 分类决策树模型是一种描述对实例进行分类的树形结构. 决策树可以看为一个if-then规则集合,具有“互斥完备”性质 .决策树基本上都是 采用的是贪心(即非回溯)的算法,自顶向下递归分治构造. 生 ...

  2. Spark2.0机器学习系列之12: 线性回归及L1、L2正则化区别与稀疏解

    概述 线性回归拟合一个因变量与一个自变量之间的线性关系y=f(x).       Spark中实现了:       (1)普通最小二乘法       (2)岭回归(L2正规化)       (3)La ...

  3. Spark2.0机器学习系列之1: 聚类算法(LDA)

    在Spark2.0版本中(不是基于RDD API的MLlib),共有四种聚类方法:      (1)K-means      (2)Latent Dirichlet allocation (LDA)  ...

  4. Spark2.0机器学习系列之11: 聚类(幂迭代聚类, power iteration clustering, PIC)

    在Spark2.0版本中(不是基于RDD API的MLlib),共有四种聚类方法:             (1)K-means             (2)Latent Dirichlet all ...

  5. Spark2.0机器学习系列之10: 聚类(高斯混合模型 GMM)

    在Spark2.0版本中(不是基于RDD API的MLlib),共有四种聚类方法:      (1)K-means      (2)Latent Dirichlet allocation (LDA)  ...

  6. Spark2.0机器学习系列之9: 聚类(k-means,Bisecting k-means,Streaming k-means)

    在Spark2.0版本中(不是基于RDD API的MLlib),共有四种聚类方法:      (1)K-means      (2)Latent Dirichlet allocation (LDA)  ...

  7. Spark2.0机器学习系列之6:GBDT(梯度提升决策树)、GBDT与随机森林差异、参数调试及Scikit代码分析

    概念梳理 GBDT的别称 GBDT(Gradient Boost Decision Tree),梯度提升决策树.     GBDT这个算法还有一些其他的名字,比如说MART(Multiple Addi ...

  8. Spark2.0机器学习系列之5:随机森林

    概述 随机森林是决策树的组合算法,基础是决策树,关于决策树和Spark2.0中的代码设计可以参考本人另外一篇博客: http://www.cnblogs.com/itboys/p/8312894.ht ...

  9. Spark2.0机器学习系列之7: MLPC(多层神经网络)

    Spark2.0 MLPC(多层神经网络分类器)算法概述 MultilayerPerceptronClassifier(MLPC)这是一个基于前馈神经网络的分类器,它是一种在输入层与输出层之间含有一层 ...

随机推荐

  1. 考试星陈沧:借助Testin云測加速实现”考试电子化”目标

    考试星陈沧:借助Testin云測加速实现"考试电子化"目标 2014/10/11 · Testin · 开发人员訪谈 考试星国内首款在线考试云平台,可用于企业内部考核,经销商考核, ...

  2. Ubuntu之No module named cv2

    最简单的方法是:pip install opencv-python 另外,从源码安装的方法: 1下载opencv源码:http://opencv.org/releases.html  推荐2.4.13 ...

  3. 【BZOJ】1669: [Usaco2006 Oct]Hungry Cows饥饿的奶牛(lis)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1669 水题太严重 #include <cstdio> #include <cstr ...

  4. git 使用手册

    git 作为开源项目首选版本管理软件,必然其优势不容小觑,下面总结一下初次解除用到的一些技能 1. 基本命令介绍 git help branch 查看branch帮助文档 git branch -a ...

  5. Sublime 插件补充

    开启vim模式+autosave+Livereload插件 安装参考:emmmet http://www.cnblogs.com/wuheng1991/p/6144955.html

  6. 怎么隐藏MathType标尺

    因为MathType公式编辑能力非常的好用,所以非常的受大家的欢迎.MathType用现有的模板可以直接输入输出各种公式,而且MathType中有着各式各样的数学符号满足了大家日常公式的需求,为大家的 ...

  7. python3----练习题(图片转字符画)

    import argparse from PIL import Image def parse_param(): parser = argparse.ArgumentParser() # 命令行输入参 ...

  8. 安装PHP扩展-----phpredis

    一.redis介绍 redis是当前比较热门的NOSQL系统之一,它是一个key-value存储系统.和Memcached类似,但很大程度补偿了 memcached的不足,它支持存储的value类型相 ...

  9. 【黑金原创教程】【Modelsim】【第四章】激励文本就是仿真环境

      声明:本文为黑金动力社区(http://www.heijin.org)原创教程,如需转载请注明出处,谢谢! 黑金动力社区2013年原创教程连载计划: http://www.cnblogs.com/ ...

  10. 《从零开始学Swift》学习笔记(Day67)——Cocoa Touch设计模式及应用之MVC模式

    原创文章,欢迎转载.转载请注明:关东升的博客 MVC(Model-View-Controller,模型-视图-控制器)模式是相当古老的设计模式之一,它最早出现在Smalltalk语言中.现在,很多计算 ...