一、新建scala项目

二、构造程序



代码如下

package xyz.pl8

import java.io.File

import org.apache.log4j.{Level, Logger}
import org.apache.spark.{SparkContext, SparkConf}
import org.apache.spark.mllib.evaluation.RegressionMetrics
import org.apache.spark.mllib.recommendation.{MatrixFactorizationModel, Rating, ALS}
import org.apache.spark.rdd.RDD import scala.util.Random object MovieLensALS { //1. Define a rating elicitation function
// Seq[Rating]
def elicitateRating(movies: Seq[(Int, String)])={
val prompt="Please rate the following movie(1-5(best) or 0 if not seen: )"
println(prompt)
val ratings= movies.flatMap{x=>
var rating: Option[Rating] = None // Rating(user: Int, product: Int, rating: Double)
var valid = false
while(!valid){
println(x._2+" :")
try{
val r = Console.readInt()
if (r>5 || r<0){
println(prompt)
} else {
valid = true
if (r>0){
rating = Some(Rating(0, x._1, r))
}
}
} catch{
case e:Exception => println(prompt)
}
}
rating match {
case Some(r) => Iterator(r) // FlatMap将结构解散成元素, 这里是Rating
case None => Iterator.empty
}
}
if (ratings.isEmpty){
error("No ratings provided!")
} else {
ratings
}
} //2. Define a RMSE computation function
def computeRmse(model: MatrixFactorizationModel, data: RDD[Rating]) = {
val prediction = model.predict(data.map(x=>(x.user, x.product)))
val predDataJoined = prediction.map(x=> ((x.user,x.product),x.rating)).join(data.map(x=> ((x.user,x.product),x.rating))).values
new RegressionMetrics(predDataJoined).rootMeanSquaredError
} //3. Main
def main(args: Array[String]) {
//3.1 Setup env
Logger.getLogger("org.apache.spark").setLevel(Level.WARN) if (args.length !=1){
print("Usage: movieLensHomeDir")
sys.exit(1)
} val conf = new SparkConf().setAppName("MovieLensALS")
.set("spark.executor.memory","500m")
val sc = new SparkContext(conf) //3.2 Load ratings data and know your data
// ratings.dat 的格式 UserID::MovieID::Rating::Timestamp
val movieLensHomeDir=args(0)
// RDD[long, Rating]
val ratings = sc.textFile(new File(movieLensHomeDir, "ratings.dat").toString).map {line =>
val fields = line.split("::")
//timestamp, user, product, rating
// 取模成分成10组
(fields(3).toLong%10, Rating(fields(0).toInt, fields(1).toInt, fields(2).toDouble))
}
// movies.dat格式 MovieID::Title::Genres
// Map[Int,String]
val movies = sc.textFile(new File(movieLensHomeDir, "movies.dat").toString).map {line =>
val fields = line.split("::")
//movieId, movieName
(fields(0).toInt, fields(1))
}.collectAsMap() val numRatings = ratings.count()
val numUser = ratings.map(x=>x._2.user).distinct().count()
val numMovie = ratings.map(_._2.product).distinct().count() println("Got "+numRatings+" ratings from "+numUser+" users on "+numMovie+" movies.") //3.3 Elicitate personal rating
// = RDD[(long,Rating) -> Array[int] -> Map[Int, long] -> Seq[(Int, long)] -> Seq[(Int,long)] -> Seq[Int]
val topMovies = ratings.map(_._2.product).countByValue().toSeq.sortBy(-_._2).take(50).map(_._1)
val random = new Random(0)
// Seq[(Int, String)]
val selectMovies = topMovies.filter(x=>random.nextDouble() < 0.2).map(x=>(x, movies(x))) val myRatings = elicitateRating(selectMovies)
val myRatingsRDD = sc.parallelize(myRatings, 1) //3.4 Split data into train(60%), validation(20%) and test(20%)
val numPartitions = 10
// 6组(即60%),并上手工输入评价
val trainSet = ratings.filter(x=>x._1<6).map(_._2).union(myRatingsRDD).repartition(numPartitions).persist()
val validationSet = ratings.filter(x=>x._1>=6 && x._1<8).map(_._2).persist()
val testSet = ratings.filter(x=>x._1>=8).map(_._2).persist() val numTrain = trainSet.count()
val numValidation = validationSet.count()
val numTest = testSet.count() println("Training data: "+numTrain+" Validation data: "+numValidation+" Test data: "+numTest) //3.5 Train model and optimize model with validation set
val numRanks = List(8, 12)
val numIters = List(10, 20)
val numLambdas = List(0.1, 10.0)
var bestRmse = Double.MaxValue
var bestModel: Option[MatrixFactorizationModel] = None
var bestRanks = -1
var bestIters = 0
var bestLambdas = -1.0
// 寻找优化参数的模型
for(rank <- numRanks; iter <- numIters; lambda <- numLambdas){
val model = ALS.train(trainSet, rank, iter, lambda)
val validationRmse = computeRmse(model, validationSet)
println("RMSE(validation) = "+validationRmse+" with ranks="+rank+", iter="+iter+", Lambda="+lambda) if (validationRmse < bestRmse) {
bestModel = Some(model)
bestRmse = validationRmse
bestIters = iter
bestLambdas = lambda
bestRanks = rank
}
} //3.6 Evaluate model on test set
// 用测试集来评估模型
// 测试集均方根差
val testRmse = computeRmse(bestModel.get, testSet)
println("The best model was trained with rank="+bestRanks+", Iter="+bestIters+", Lambda="+bestLambdas+
" and compute RMSE on test is "+testRmse) //3.7 Create a baseline and compare it with best model
// 创建基线 并与模型进行比较
val meanRating = trainSet.union(validationSet).map(_.rating).mean() // 训练集与验证集和的均数
// 最佳根均方错误线(基线)
val bestlineRmse = new RegressionMetrics(testSet.map(x=>(x.rating, meanRating))).rootMeanSquaredError // 测试集与均数的均方根差
// testRmse(这个数应该更优,值更小)
val improvement = (bestlineRmse - testRmse)/bestlineRmse*100
println("The best model improves the baseline by "+"%1.2f".format(improvement)+"%.") //3.8 Make a personal recommendation
// 进行个人推荐, 排除自己已经评分内容
val moviesId = myRatings.map(_.product)
val candidates = sc.parallelize(movies.keys.filter(!moviesId.contains(_)).toSeq)
val recommendations = bestModel.get
.predict(candidates.map(x=>(0, x)))
.sortBy(-_.rating)
.take(50) var i = 0
println("Movies recommended for you:")
recommendations.foreach{ line=>
println("%2d".format(i)+" :"+movies(line.product))
i += 1
}
sc.stop()
}
}

导入引用库

三、打包部署

程序运行时,需要指定输入数据路径,数据包含了ratings.dat和movies.dat,数据都包含在了一个数据包。点击下载, 然后解压。

配置运行参数

  • 点击edit configuration,在左侧点击该项目。在右侧在右侧VM options中输入“-Dspark.master=local”,指示本程序本地单线程运行

  • 在Program argguemnts指定,上面解压的路径。

    然后,在IDEA上选择MovieLensALS右键选择运行,即可运行了。

    按照引导,输入自己的评价后,最后输出形式如下:

    The best model was trained with rank=12, Iter=20, Lambda=0.1 and compute RMSE on test is 0.868464888081759

    The best model improves the baseline by 22.01%.

    Movies recommended for you:

    0 :Julien Donkey-Boy (1999)

    1 :Love Serenade (1996)

    2 :Catwalk (1995)

四、HADOOP集群部署

导出jar包设置



选main类对后,点击OK确定, 这个时候配置已经完成了, 我们就可以进行编译 jar文件了, 选择菜单Build->Build Artifacts..., 生成的文件路径为/out/artifacts/MovieLensALS_jar/MovieLensALS.jar

准备HADOOP环境

假设我们的HADOOP环境已经搭建成功。 接下来我们要把需要计算的数据文件上传到hadoop; 首先,在hadoop上面创建文件夹,命令如下:

hdfs dfs -mkdir -p /recommendation/data

上传数据文件命令如下:

hdfs dfs -put *.dat /recommendation/data

这时时候我们可以通过命令查看,上传是否成功

hdfs dfs -cat /recommendation/data/users.dat

运行



在上面红框中,指定了生成的jar文件名, 所在路径, 以及MainClass。这面就是通过spark执行:

/usr/local/spark/spark-2.3.0-bin-hadoop2.7/bin/spark-submit --master local  --class "xyz.pl8.MovieLensALS" /home/hartifacts/movielensals_jar/movielensals.jar /recommendation/data

推荐系统-05-Spark电影推荐、评估与部署的更多相关文章

  1. SparkMLlib—协同过滤推荐算法,电影推荐系统,物品喜好推荐

    SparkMLlib-协同过滤推荐算法,电影推荐系统,物品喜好推荐 一.协同过滤 1.1 显示vs隐式反馈 1.2 实例介绍 1.2.1 数据说明 评分数据说明(ratings.data) 用户信息( ...

  2. 数据算法 --hadoop/spark数据处理技巧 --(9.基于内容的电影推荐 10. 使用马尔科夫模型的智能邮件营销)

    九.基于内容的电影推荐 在基于内容的推荐系统中,我们得到的关于内容的信息越多,算法就会越复杂(设计的变量更多),不过推荐也会更准确,更合理. 本次基于评分,提供一个3阶段的MR解决方案来实现电影推荐. ...

  3. 【大数据 Spark】利用电影观看记录数据,进行电影推荐

    利用电影观看记录数据,进行电影推荐. 目录 利用电影观看记录数据,进行电影推荐. 准备 1.任务描述: 2.数据下载 3.部分数据展示 实操 1.设置输入输出路径 2.配置spark 3.读取Rati ...

  4. 利用Surprise包进行电影推荐

    Surprise(Simple Python Recommendation System Engine)是一款推荐系统库,是scikit系列中的一个.简单易用,同时支持多种推荐算法(基础算法.协同过滤 ...

  5. Spark学习笔记——构建基于Spark的推荐引擎

    推荐模型 推荐模型的种类分为: 1.基于内容的过滤:基于内容的过滤利用物品的内容或是属性信息以及某些相似度定义,来求出与该物品类似的物品. 2.协同过滤:协同过滤是一种借助众包智慧的途径.它利用大量已 ...

  6. 利用python实现电影推荐

    "协同过滤"是推荐系统中的常用技术,按照分析维度的不同可实现"基于用户"和"基于产品"的推荐. 以下是利用python实现电影推荐的具体方法 ...

  7. 转利用python实现电影推荐

    “协同过滤”是推荐系统中的常用技术,按照分析维度的不同可实现“基于用户”和“基于产品”的推荐. 以下是利用python实现电影推荐的具体方法,其中数据集源于<集体编程智慧>一书,后续的编程 ...

  8. 数据挖掘-MovieLens数据集_电影推荐_亲和性分析_Aprioro算法

    #!/usr/bin/env python2 # -*- coding: utf-8 -*- """ Created on Tue Feb  7 14:38:33 201 ...

  9. 基于Azure构建PredictionIO和Spark的推荐引擎服务

    基于Azure构建PredictionIO和Spark的推荐引擎服务 1. 在Azure构建Ubuntu 16.04虚拟机 假设前提条件您已有 Azure 帐号,登陆 Azure https://po ...

  10. Azure构建PredictionIO和Spark的推荐引擎服务

    Azure构建PredictionIO和Spark的推荐引擎服务 1. 在Azure构建Ubuntu 16.04虚拟机 假设前提条件您已有 Azure 帐号,登陆 Azure https://port ...

随机推荐

  1. oracle坏块处理记录

    1. 执行sql:select count(distinct id) from bw_fpzxx ,报错如下: ORA-01578: ORACLE 数据块损坏 (文件号 16, 块号 195428)O ...

  2. 根据科目计算父科目ID,并递归累计求父科目的金额

    通常情况下,我们会从外部系统或者其他数据源得到以下树形结构的数据,并需要对其进行处理 其中,需要做的处理包括 1.计算每个科目的父科目ID,即PARENT_ID; 2.计算每个科目的ITEM_LEVE ...

  3. Python----list&元祖常用方法总结

    一.创建列表,把使用逗号分隔的数据用中括号[  ]括起来即为一个列表,列表也叫数组.list.array:列表里面也可以再套列表,一个列表里面套一个列表,叫二维数组:一个里面套一个列表,里面的列表再套 ...

  4. Node.js + Express中间件详解

    使用中间件 Express是一种路由和中间件Web框架,它具有自己的最小功能:Express应用程序本质上是一系列中间件函数调用. 中间件函数是可以访问请求对象 (req),响应对象(res)以及应用 ...

  5. 将16进制unsigned char数组转换成整数

    /** * 将unsigned char数组转换成long long数值 * {0x00 0x00 0x20 0x00}转换之后得到8192 * * @param str 数组 * @param le ...

  6. firstchild.data与childNodes[0].nodeValue意思

    x.firstchild.data:获取元素第一个子节点的数据: x.childNodes[0]::获取元素第一个子节点; x.childNodes[0].nodeValue.:也是获取元素第一个子节 ...

  7. U帮忙U盘装系统工具使用教程

    在用U盘装系统时首先我们需要了解一下U帮忙U盘启动盘的制作以及BIOS设置U盘启动和U盘装系统步骤后才能让操作更顺利的完成,下面就来说说U帮忙U盘装系统工具使用教程,希望对大家有所帮助! 如果您不了解 ...

  8. Java反射《一》获取类

    package com.study.reflect; /** * 反射:java程序运行中,可以获得该类的所有属性和方法,对于任意一个对象可以 调用它的属性和方法,这种动态获得属性和方法,调用对象属性 ...

  9. Date和Timestamp区别

    主要是精度问题,date没有ms,而timestamp是有ms的,所以date的精度要低于timestamp. 而且二者可以互相转换. 除此之外,没有什么不同,

  10. Java Swing 简单介绍

    Swing 是一个为Java设计的GUI工具包. Swing是JAVA基础类的一部分. Swing包括了图形用户界面(GUI)器件如:文本框,按钮,分隔窗格和表. Swing提供许多比AWT更好的屏幕 ...