基于Spark ALS的离线推荐系统实践
来源:互联网 发布:freehand 11 for mac 编辑:程序博客网 时间:2024/05/01 02:20
首先,此推荐系统搭建在基于Hadoop(2.7.3)、Spark(2.0.0)、Zookeeper(可选)的集群上,关于Hadoop和Spark集群搭建可参考我前面几篇水水的博文~
其次,此demo用到的数据来自DataCastle的一个正在进行的比赛,数据集在此请大家移步下载~比赛的主题是关于地点的推荐
(训练集数据格式:userID, addressID, count –> 用户id,地点id,访问次数)
Spark机器学习库MLlib中关于推荐的算法至今有且只有一种:ALS(交替最小二乘法),不同于协同过滤求用户间相似度,而是一种基于矩阵分解的算法,关于该算法的来龙去脉各位可自行搜索~
废话不多说,上代码说话
Step 1:在IntelliJ IDEA构建maven工程,则pom.xml文件中依赖库具体如下:
<dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-core_${scala.version}</artifactId> <version>${spark.version}</version> </dependency> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-sql_${scala.version}</artifactId> <version>${spark.version}</version> </dependency> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-streaming_${scala.version}</artifactId> <version>${spark.version}</version> </dependency> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-mllib_${scala.version}</artifactId> <version>${spark.version}</version> </dependency> <dependency> <groupId>com.databricks</groupId> <artifactId>spark-csv_${scala.version}</artifactId> <version>1.5.0</version> </dependency>
我系统安装的Scala版本是2.11.6,各位根据实际情况调整~
Step 2:在工程中构建一个Scala Module,如图:
备注:配置ScalaSDK步骤:File –> Project Structure –> Project Settings –> Libraries –>
Step 3:下载数据集,上传数据集到HDFS
hdfs dfs -put /保存文件的HDFS路径 /本地文件路径
Step 4:新建.scala文件,写代码:
1)创建SparkSession,从HDFS导入数据Dataset:
val conf = new SparkConf() .setAppName("Place Recommendation APP") .setMaster("spark://master:7077") .set("spark.rpc.netty.dispatcher.numThreads","2") //预防RpcTimeoutException val spark = SparkSession.builder() .config(conf).getOrCreate() //导入数据 val base = "/user/datacastle/data/" val rawUserAddressData = spark.read.textFile(base + "train.txt") val rawAddressData = spark.read.textFile(base + "mappedpoiinfo.txt")
2)数据预处理,提取有效信息(相对简单,具体看代码),并将Dataset[String]转为DataFrame:
2.1>train.txt的训练集数据转成DataFrame(一个DataFrame可看成是关系型数据库中的一张表):
/** * user,address,count原始文本数据转为DataFrame * * @param rawUserAddressData * @return */ def buildCounts(rawUserAddressData: Dataset[String]): DataFrame = { rawUserAddressData.map{ line => val Array(userID, addressID, count) = line.split(',').map(_.toInt) (userID, addressID, count) }.toDF("user", "address", "count") }
2.2>获取所有有效用户id:
/** * 获取所有用户id,升序排序 * @param rawUserAddressData */ def buildUserByID( rawUserAddressData: DataFrame ): Array[Any] = { rawUserAddressData.groupBy("user").max("user").orderBy("user").rdd.map{line => line(0)}.collect() }
3)重头戏:调用Spark MLlib中ALS模型并设置参数进行推荐:
3.1>ALS模型参数设置以及导入训练集训练模型:
val model = new ALS() .setSeed(Random.nextLong()) .setImplicitPrefs(true) .setRank(10) .setRegParam(1.0) .setAlpha(40.0) .setMaxIter(20) .setUserCol("user") .setItemCol("address") .setRatingCol("count") .setPredictionCol("prediction") .fit(trainData) //fit内部已经将trainData转成Rating,并且调用了train
3.2>给指定用户推荐Top N个地点:
/** * 推荐top howmany个地点 * * @param model * @param userID * @param howMany * @return */ def makeRecommendations(model: ALSModel, userID: Int, howMany: Int): DataFrame = { val toRecommend = model.itemFactors .select($"id".as("address")) .withColumn("user", lit(userID)) model.transform(toRecommend) .select("user", "address") .orderBy($"prediction".desc) .limit(howMany) }
3.3>给所有用户各自推荐不同的50个地点:
val Recommendations = makeRecommendations(model, userIDs(0).toString.toInt, 50) var result: DataFrame = Recommendations for (i <- 1 until userIDs.length) { val userID = userIDs(i).toString.toInt val topRecommendations = makeRecommendations(model, userID, 50) result = result.union(topRecommendations) println("<------------------------>" + "have finished the index of : " + i + "<------------------------>") }
3.4>保存结果,转成.csv文件保存到HDFS:
val csvData = result.select("user", "address") csvData.coalesce(1) .write .format("com.databricks.spark.csv") .option("header", "true") .save("/user/datacastle/data/cand1.csv")
注意:此处使用了databricks社区的开源库spark-csv,重点在于:由于csvData是由多个DataFrame组合union而来,所以分布在n个partition中,如果需要把所有结果都保存在同一个csv中,需要repartition一下,所以调用了coalesce(1),将n个partition归一
3.5>最后释放内存:
trainData.unpersist()model.userFactors.unpersist()model.itemFactors.unpersist()
Step 5:编译工程(Make Project),打成jar包(Build Artifacts),需要注意的是:
在Project Structure中设置Artifacts,需要把jar包的依赖全部去掉,并设置好main class,如图:
Step 6:提交*.jar到spark集群,此处采用standalone模式,跑起来~
$SPARK_HOME/bin/spark-submit --class placeRecommender ./***.jar
最后PO上完整代码,欢迎大神们纠bug指教~
完整代码下载
- 基于Spark ALS的离线推荐系统实践
- 推荐系统实践1---基于spark ALS做的电影推荐,参考网上的做的,能跑起来
- 基于Spark ALS在线推荐系统
- 基于Spark ALS在线推荐系统
- 基于Spark ALS在线推荐系统
- 【推荐】基于Spark的ALS算法
- 基于ALS的线推荐系统
- 基于Spark mllib的矩阵分解(ALS)推荐算法
- 基于ALS算法的简易在线推荐系统
- 基于ALS算法的简易在线推荐系统
- Spark ALS推荐系统用户ID非整数的解决思路
- ALS推荐系统实战
- ALS 推荐系统
- 基于Spark的电影推荐系统
- 基于spark的精准推荐系统
- 基于spark的精准推荐系统
- ALS推荐算法在Spark上的优化
- 推荐系统ALS矩阵分解
- js == 与 === 的区别
- 曲线拟合的几种解释
- 51nod-1067 Bash游戏 V2
- jquery和javascript的区别(常用方法比较)
- 百度API获取某个工作日之后的时间
- 基于Spark ALS的离线推荐系统实践
- c++primer 第八章IO操控流的条件状态
- 详细说明上一篇 scenario
- Vuforia开发入门二-资源介绍
- 设计模式之代理模式 Android代码分析
- 平衡搜索树中的左单旋&右单旋&双旋
- 滲透 Facebook 的思路與發現
- Ubuntu16.04 Nvidia 显卡驱动安装
- BZOJ 1968 [Ahoi2005]COMMON 约数研究