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. Webpack实例教程及模块化规范

    Webpack 是当下最热门的前端资源模块化管理和打包工具.它能够将很多松散的模块依照依赖和规则打包成符合生产环境部署的前端资源. 通过 loader 的转换,不论什么形式的资源都能够视作模块,比方 ...

  2. grafana里prometheus查询语法

    名称 描述 label_values(label) 返回label每个指标中的标签值列表. label_values(metric, label) 返回label指定度量标准中的标签值列表. metr ...

  3. OS X删除自带的safari和facetime等程序

    打开终端 cd /Applications/ //在应用程序文件目录删除苹果自带的程序 sudo rm -rf Safari.app/ //删除safari浏览器 sudo rm -rf Mail.a ...

  4. Yarn概述

    转自:http://liujiacai.net/blog/2014/09/07/yarn-intro/ Yarn是随着hadoop发展而催生的新框架,全称是Yet Another Resource N ...

  5. HBase学习系列

    转自:http://www.aboutyun.com/thread-8391-1-1.html 问题导读: 1.hbase是什么? 2.hbase原理是什么? 3.hbase使用中会遇到什么问题? 4 ...

  6. Unity3D项目之 Survival Shooter 记录

    1.导入资源 2.把预设文件的环境拖到场景中, 3.位置归0 4.保存场景 5.删除默认灯光,把预设灯光拖到场景中,位置归0 6.新建一个 Quad 7.旋转90度,设置缩放100,100,1 重命名 ...

  7. 测试RESTful API利器-Postman

    对于前端开发者而言,最需要的往往不是技术本身,其实技术都没什么难的,而最缺少的则是各种各样好的兵器,比如调试,开发工具等等. 我们这里就推荐一款前端开发的利器-Postman,它是Google Chr ...

  8. Qualcomm Vuforia SDK背景

    参考视频:http://edu.csdn.net/course/detail/1467/23125?auto_start=1 一:概述 官网:www.vuforia.com 应用方向:产品交互.虚拟购 ...

  9. Angular 组件与模板 - 属性指令

    指令概览 在 Angular 中有三种类型的指令: 组件 — 拥有模板的指令 结构型指令 — 通过添加和移除 DOM 元素改变 DOM 布局的指令 属性型指令 — 改变元素.组件或其它指令的外观和行为 ...

  10. SQL SERVER 服务启动失败

    好久没用SQL SERVER了.今天启动SQL,发现服务启动失败.报错例如以下:--错误发生 1069-(因为登录失败而无法启动服务.) .百度一下,解决方式例如以下: 请按下列步骤操作: 1.右键单 ...