数据文件:

u.data(userid  itemid  rating  timestamp)

u.item(主要使用 movieid movietitle)

数据操作

把u.data导入RDD, take()  x.split(‘\t’)(1)

查看userid字段的统计信息

查看udata数据矩阵的 userid列上所有值的统计信息

使用ALS.train进行训练

import org.apache.spark.mllib.recommendation.ALS

import org.apache.spark.mllib.recommendation.Rating

//读取userData前3个字段 用户,产品,评分来创建rawRatings

val userData=sc.textFile(”file:/home/hadoop/ALS/u.data”)

val rawRatings=userData.map(_.split(‘\t’).take(3))

//1.准备ALS训练数据

// import org.apache.spark.mllib.recommendation.Rating

//把3个split列case到3个名称变量中(user,movie,rating)后面便于操作

val ratingRDD= rawRatings.map{

case Array(user,movie,rating)=>Rating(user.toInt,movie.toInt,rating.toDouble)

}

//2.使用ALS.train进行训练

//使用显示Explicit rating评分训练.

// ALS.train(ratings:RDD[Rating],rank:Int,iterations:Int,lambda:Double):MatrixFactorizationModel

//隐式Implicit评分训练

// ALS.trainImplicit(ratings:RDD[Rating],rank:Int,iterations:Int,lambda:Double):MatrixFactorizationModel

//Rating(userID,productID,rating),rank 当矩阵分解matrix factorization时,将原本矩阵A(mXn)分解成X(m X rank) Y(rank X n)矩阵

//Iterator   ALS算法重复计算次数,建议10~20

//lambda   建议0.01  会影响准确度|时间

//MatrixFactorizationMode训练完成后产生的模型,训练时会执行矩阵分解。模型对象成员 rank,

userFeatures:RDD[(Int,Array[Double])]分解后的用户矩阵X(m*rank)

productFeatures:RDD[(Int,Array[Double])]分解后的产品矩阵Y(m*rank)

val model=ALS.train(ratingrdd,10,10,0.01)

使用模型推荐

//1.针对用户 推荐电影

model.recommendProducts(196,5).mkString("\n")

//传入user=196被推荐用户ID,num=5 推荐数, 返回Array[Rating]

//2.针对用户 推荐产品的系统评分

model.predict(196,464)   //系统对用户196推荐产品464的评分

//3.针对电影 推荐给用户

//当要促销某些电影时,可以找出可能对这些电影感兴趣的会员 使用model.recommendUsers(product:Int,num:Int):Array[Rating] 方法推荐

product要被推荐的电影ID,num推荐的记录数,返回系统针对产品推荐给用户的数组

model.recommendUser(464,5).mkString(“,”)

//把464推荐给用户471,系统评分 13.0232...

显示推荐电影名称

//1 创建电影ID-名称的对照表

val itemrdd=sc.textFile("file:/home/hadoop/ALS/u.item")

val moviet=itemrdd.map(_.split("\\|").take(2)).map(x=>(x(0),x(1))).collectAsMap

//map(x=>(x(0),x(1))).collect().toMap

//2显示对照表前5条数据

moviet.take(5).foreach(println)

//查询电影名称

scala> moviet(590)

res114: String = Hellraiser: Bloodline (1996)

//2 显示前5条推荐电影名称

model.recommendProducts(195,5).map(rating=>(rating.product,moviet(rating.product),rating.rating)).foreach(println)

Recommend项目代码

import java.io.File

import scala.io.Source

import org.apache.spark.{SparkContext,SparkConf}

import org.apache.spark.rdd._

import org.apache.spark.mllib.recommendation.{ALS,Rating,MatrixFactorizationModel}

main程序

val (ratingrdd,moviet)=PrepareData()  //产生ratingrdd评分数据 与 moviet(id,title)

val model=ALS.train(ratingrdd,5,20,0.1)  //训练模型

recommend(model,moviet)  //推荐

//针对用户推荐电影

def RecommendMovies(model:MatrixfactorizationModel,movieTitle:Map[Int,String],inputUserID:Int)={

val RecomendMovie=model.recommendProducts(inputUserID,10)

RecomendMovie.foreach{r=>pritnln(i.toString+moviet(r.product)+r.rating); i+=1 }

}

//针对电影推荐用户

def RecommendUsers(model:MatrixfactorizationModel,movieTitle:Map[Int,String],inputMovieID:Int)={

val RecomendUser=model.recommendUsers(inputMovieID,10)

RecomendUser.foreach{r=>pritnln(i.toString+r.user+r.rating); i+=1 }

}

评估模型ALSEvaluation.main

调校model参数

model的rank,iterator,lambda这些参数设置会影响结果的准确度,运行时间。下面调校找出最佳参数组合

import java.io.File

import scala.io.Source

import org.apache.spark.{SparkContext,SparkConf}

import org.apache.spark.rdd._

import org.apache.spark.mllib.recommendation.{ALS,Rating,MatrixFactorizationModel}

import org.apache.spark.mllib.regression.LabeledPoint

def main(arg:Array[String]):Unit={

//1 准备数据阶段

val (trainData,validationData,testData)=prepareData()

trainData.persist();validationData.persist();testData.persist()

//2 trainData训练model,validationData评估模型的RMSE均方根误差

//参数设置会影响误差,需反复执行训练和评估找出最佳组合,最后返回

//bestModel模型进入下一阶段测试

val bestModel=trainValidation(trainData,validationData)

//3 使用testData在测试一次,避免出现overfitting(训练过度).如果rmse在trainData训练//和testData测试差异不大代表无过度

val testRmse=computeRMSE(bestModel,testData)

println(“使用testData测试bestModel,结果rmse=”+testRmse)

trainData.unpersist();validationData.unpersist();testData.unpersist()

}

1.准备数据-prepareData

def prepareData():(RDD[Rating],RDD[Rating],RDD[Rating])={

val Array(trainData,validationData,testData)=ratingrdd.randomSplit(Array(0.8,0.1,0.1))

return (trainData,validationData,testData)

}

2.进行训练评估-trainvalidation

def trainvalidation(trainData:RDD[Rating],validationData:RDD[Rating]):MatrixFactorizationModel={

//评估rank

evaluateParameter(trainData,validationData,”rank”,Array(5,10,15,20,50,100),Array(10),Array(0.1)

//评估iter

evaluateParameter(trainData,validationData,”numIterators”,Array(10),Array(5,10,15,20,25),Array(0.1));

//评估lambda

evaluateParameter(trainData,validationData,”lambda”,Array(10),Array(10),Array(0.05,0.1,1,5,10.0));

//所有参数找出最好组合

val bestModel=evaluateAllParameter(trainData,validationData, Array(5,10,15,20,50,100), Array(5,10,15,20,25), Array(0.05,0.1,1,5,10.0));

return (bestModel)

}

//以上3个参数有5*5*5=125个组合,对每一种参数组合评估Rmse 最好找出具有最小误差Rmse的参数组合就是最佳组合。

1.评估单个参数-evaluateParameter

那个参数具有比较低的误差,绘制图形

def evaluateParameter(trainData,validationData,p:String,ranks:Array[Int],its:Array[String],lambdas:Array[Double]):(Double,String)={

for(rank<-ranks;it<-its;lambda<-lambdas){

val rmse=trainModel(trainData,validationData,rank,it,lambda)

val pData=p match{

case “rank”=>”rank:”+rank;  //pData取到for中的值

case “it”=>”it:”+it;

case “lambda”=>”lambda:”+lambda;

}

}

(rmse,pData)

}

-----------包含画图

def evaluateParameter(trainData,validationData,p:String,ranks:Array[Int],its:Array[String],lambdas:Array[Double])={

var databarchart=new DefaultCategoryDataset();

var datalinechart=new DefaultCategoryDataset();

for(rank<-ranks;it<-its;lambda<-lambdas){

val rmse=trainModel(trainData,validationData,rank,it,lambda)

val pData=p match{

case “rank”=>rank;  //pData取到for中的值

case “it”=>it;

case “lambda”=>lambda;

}

databarchart.addValue(rmse,p,pData.toString)

datslinechart.addValue(time,”Time”,pData.toString)

}

Chart.plotBarLineChart(“ALS evaluations ”+p,p,”RMSE”,0.58,5,”Time”,databarchart,datalinechart);

}

def evaluateAllParameter(trainData:RDD[Rating],validationData:RDD[Rating],ranks:Array[Int],its:Array[Int],lambdas:Array[Double]):(Double,String):MatrixFactorizationModel={

val evaluations=for(rank<-ranks;it<-its;lambda<-lambdas)

yield{

val rmse=trainModel(trainData,validationData,rank,it,lambda)

(rank,it,lambda,rmse)

}

val Eval=(evaluations.sortBy(_._4))

val BestEval=Eval(0)

println(“最佳model参数 rank=”+BestEval._1+”,it=”+BestEval._2+” lambda=”+BestEval._3)

val bestModel=ALS.train(trainData,BestEval._1,BestEval._2,BestEval._3)

(bestModel)

}

2.训练模型-trainModel

def trainModel(trainData:RDD[Rating], validationData:RDD[Rating],rank:Int,it:Int,lambda:Double):Double={

val model=ALS.train(trainData,rank,it,lambda)

val rmse=computeRmse(model,validationData)

(rmse)

}

3.计算RMSE- computeRmse

root mean square error用来计算推荐系统对用户喜好的预测与实际喜好的误差平均值

误差越小代表预测值与真实值越接近

公式

def computeRmse(model:MatrixFactorizationModel,validationData:RDD[Rating]):Double={

val num= validationrdd.count

val predictedRDD=model.predict(validationrdd.map(r=>(r.user,r.product)))

//取出user+product传入预测方法,预测将结果存入predictRDD.

val predictedAndRatings=predictedRDD.map(p=>((p.user,p.product),p.rating))

.join(validationrData.map(r=>((r.user,r.product),r.rating))).values

//predictRDD预测集join ratingrdd真实集

math.sqrt(predictedAndRatings.map(x=>(x._1-x._2)*(x._1-x._2)).reduce(_+_)/num)

//针对每条数据进行计算,传入x。x._1预测结果-x._2真实数据,相乘就是平方

//reduct将全部误差求和后,在除以个数num。最后计算sqrt平方根

}

3.运行ALSEvaluation

评估rank参数 看到对RMSE没有太大差别,但是越大运行时间会增加

评估it参数  对RMSE没有太大差别,时间会增加

评估lambda参数 0.1时  RMSE最小,所需时间差异不大

所有参数交叉评估找出最好参数组合

运行evaluationAllParameter后显示

最佳model的参数组合:rank20,it15,lamdba0.1  结果rmse=0.72312434463...

最好使用testData再次验证bestModel结果0.7191119923578929,确认无overfitting问题

相同的validationData,在model中

没优化得到RMSE值0.7745372...

优化后得到RMSE值0.7134127699...

最后 找出最佳参数组合,可以修改Recommend.scala为最佳组合

val model=ALS.train(ratings,20,15,0.1)

附录:Chart

import org.jfree.chart._

import org.jfree.data.xy._

import org.jfree.data.category.DefaultCategoryDataset

import java.awt.Color

import java.awt.BasicStroke

object Chart{

def plotBarLineChart(Title:String,xLabel:String,yBarLabel:String,yBarMin:Double,yBarMax:Double,yLineLabel:String,dataBarChart:DefaultCategoryDataset,dataLineChart:DefaultCategoryDataset):Unit={

//画出Bar chart

val chart=ChartFactory.createBarChart(“”,xLabel,yBarLabel,

dataBarChart,   //bar chart数据

PlotOrientation.VERTICAL,  //画图方向垂直

true,   //包含legend

true,   //显示tooltips

false  //不要url generator

)

val plot=chart.getCategoryPlot();

plot.setBackgroundPaint(new Color(0xFF,0xFF,0xFF))

plot.setDomainAxisLocation(AxisLocation.BOTTOM_OR_RIGHT)

plot.setDataset(1,dataLineChart);

plot.mapDatasetToRangeAxis(1,1)

//画柱状图 Y轴

val vn=plot.getRangeAxis();vn.setRange(yBarMin,yBarMax);vn.setAutoTickUnitSelection(true)

//画折线图y轴

val axis2=new NumberAxis(yLineLabel);plot.setRangeAxis(1,axis2);

val renderer2=new LineAndShapeRender();

renderer2.setToolTipGenerator(new StandardCategoryToolTipGenerator());

//先画柱形图,再画折线图

plot.setRenderer(1,renderer2);plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);

//创建画框

val frame=new ChartFrame(Title,chart); frame.setSize(500,500);

frame.pack();frame.setVisible(true);

}

}

基于Spark的电影推荐系统的更多相关文章

  1. 基于Spark的电影推荐系统(电影网站)

    第一部分-电影网站: 软件架构: SpringBoot+Mybatis+JSP 项目描述:主要实现电影网站的展现 和 用户的所有动作的地方 技术选型: 技术 名称 官网 Spring Boot 容器 ...

  2. 基于Spark的电影推荐系统(实战简介)

    写在前面 一直不知道这个专栏该如何开始写,思来想去,还是暂时把自己对这个项目的一些想法 和大家分享 的形式来展现.有什么问题,欢迎大家一起留言讨论. 这个项目的源代码是在https://github. ...

  3. 基于Spark的电影推荐系统(推荐系统~2)

    第四部分-推荐系统-数据ETL 本模块完成数据清洗,并将清洗后的数据load到Hive数据表里面去 前置准备: spark +hive vim $SPARK_HOME/conf/hive-site.x ...

  4. 基于Spark的电影推荐系统(推荐系统~4)

    第四部分-推荐系统-模型训练 本模块基于第3节 数据加工得到的训练集和测试集数据 做模型训练,最后得到一系列的模型,进而做 预测. 训练多个模型,取其中最好,即取RMSE(均方根误差)值最小的模型 说 ...

  5. 基于Spark的电影推荐系统(推荐系统~7)

    基于Spark的电影推荐系统(推荐系统~7) 22/100 发布文章 liuge36 第四部分-推荐系统-实时推荐 本模块基于第4节得到的模型,开始为用户做实时推荐,推荐用户最有可能喜爱的5部电影. ...

  6. 基于Spark的电影推荐系统(推荐系统~1)

    第四部分-推荐系统-项目介绍 行业背景: 快速:Apache Spark以内存计算为核心 通用 :一站式解决各个问题,ADHOC SQL查询,流计算,数据挖掘,图计算 完整的生态圈 只要掌握Spark ...

  7. 基于Mahout的电影推荐系统

    基于Mahout的电影推荐系统 1.Mahout 简介 Apache Mahout 是 Apache Software Foundation(ASF) 旗下的一个开源项目,提供一些可扩展的机器学习领域 ...

  8. 基于pytorch的电影推荐系统

    本文介绍一个基于pytorch的电影推荐系统. 代码移植自https://github.com/chengstone/movie_recommender. 原作者用了tf1.0实现了这个基于movie ...

  9. 基于Spark Mllib,SparkSQL的电影推荐系统

    本文测试的Spark版本是1.3.1 本文将在Spark集群上搭建一个简单的小型的电影推荐系统,以为之后的完整项目做铺垫和知识积累 整个系统的工作流程描述如下: 1.某电影网站拥有可观的电影资源和用户 ...

随机推荐

  1. 2019春Python程序设计练习4(4.9-4.15)

    1-1 如下代码可以实现当输入6的时候输出x>5,输入4的时候输出 3<x<=5,输入1的时候输出x<=3 x = int(input()) if x>5: print( ...

  2. 百度地图api,点击标注,改变标注marker图标的链接地址

    改变选中的图标样式 // 选中高亮标注图片 let mapIcon = ‘./icon.png’; //标注点 let markerArrs = [{},{},....]; // 点击标注点 mark ...

  3. CSS 的伪元素是什么?

    CSS伪元素是用来添加一些选择器的特殊效果.用于:向某个选择器中的文字的首行. ㈠语法 ①伪元素的语法: selector:pseudo-element {property:value;} ②CSS类 ...

  4. BZOJ 2870: 最长道路tree 树的直径+并查集

    挺好的一道题. 把所有点都离线下来,一个个往里加入就行了. #include <cstdio> #include <algorithm> #define N 100003 #d ...

  5. MessagePack Java 0.6.X 快速开始指南 - 安装

    0.6.x 版本的 MessagePack 已经过期被淘汰了.如果你现在开始使用 MessagePack 话,请不要使用这个版本. 我们再这里保留 0.6.x 版本的内容主要用于参考用途. 最新的 M ...

  6. 手动升级 Confluence 6 - 升级 Confluence

    4. 备份 备份你的数据库,并且确定的你的数据库备份已经被正确的创建了.如果你的数据库不支持在线备份的话,你需要首先停止 Confluence 的运行. 备份你的 Confluence 安装目录(in ...

  7. UVA 10900 So do you want to be a 2^n-aire?

    #include<bits/stdc++.h> #include<stdio.h> #include<iostream> #include<cmath> ...

  8. hdu_1059(多重背包)

    多重背包的讲解: 多重背包问题https://blog.csdn.net/yandaoqiusheng/article/details/84782655 ; i <= n; i++) { int ...

  9. 深入理解二阶段提交协议(DDB对XA悬挂事务的处理分析)(一)

    https://sq.163yun.com/blog/article/165554812476866560

  10. 「CEOI2008」order

    题目链接 戳我 \(Solution\) 首先看看没有租条件的怎么弄.这很显然,就是普通最小割的套路 \(s\)向每个工作连一条流量\(x\)的边,\(x\)为工作收益 每个工作向每个机器连流量为\( ...