推薦系統之余弦相似度的Spark實現
(1)原理分析
余弦相似度度量是相似度度量中最常用的度量關系,從程序分析中,
- 第一步是數據的輸入,
- 其次是使用相似性度量公式
- 最后是對不同用戶的遞歸計算。
本例子是基於歐幾里得舉例的相似度計算。
(2)源代碼
1 package com.bigdata.demo 2 3 import org.apache.spark.{SparkContext, SparkConf} 4 5 /** 6 * Created by SimonsZhao on 3/29/2017. 7 */ 8 object CollaborativeFilteringSpark { 9 //1.設置環境變量 10 val conf=new SparkConf().setMaster("local").setAppName("CollaborativeFilteringSpark") 11 //2.實例化環境 12 val sc=new SparkContext(conf) 13 //3.設置用戶 14 val users=sc.parallelize(Array("aaa","bbb","ccc","ddd","eee")) 15 //4.設置電影名 16 sc.parallelize(Array("smzdm","ylxb","znb","nhsc","fcwr")) 17 //5.使用一個source嵌套map作為姓名電影名和分值的存儲 18 var source=Map[String,Map[String,Int]]() 19 //6.設置一個用以存放電影分的map 20 val filmSource =Map[String,Int]() 21 //7.設置電影評分 22 def getSource():Map[String,Map[String,Int]]={ 23 val user1FilmSource=Map("smzdm"->2,"ylxb"->3,"znb"->1,"nhsc"->0,"fcwr"->1) 24 val user2FilmSource=Map("smzdm"->1,"ylxb"->2,"znb"->2,"nhsc"->1,"fcwr"->4) 25 val user3FilmSource=Map("smzdm"->2,"ylxb"->1,"znb"->0,"nhsc"->1,"fcwr"->4) 26 val user4FilmSource=Map("smzdm"->3,"ylxb"->2,"znb"->0,"nhsc"->5,"fcwr"->3) 27 val user5FilmSource=Map("smzdm"->5,"ylxb"->3,"znb"->1,"nhsc"->1,"fcwr"->2) 28 //存儲人的名字 29 source += ("aaa" -> user1FilmSource) 30 //存儲人的名字 31 source += ("bbb" -> user2FilmSource) 32 //存儲人的名字 33 source += ("ccc" -> user3FilmSource) 34 //存儲人的名字 35 source += ("ddd" -> user4FilmSource) 36 //存儲人的名字 37 source += ("eee" -> user5FilmSource) 38 //返回嵌套的map 39 source 40 } 41 //采用余弦相似度兩兩計算分值 42 def getCollaborateSource(user1:String,user2:String):Double={ 43 //獲得第一個用戶的評分 44 val user1FilmSource =source.get(user1).get.values.toVector 45 //獲得第二個用戶的評分 46 val user2FileSource=source.get(user2).get.values.toVector 47 //對公示分子部分進行計算 48 val member=user1FilmSource.zip(user2FileSource).map(d => d._1 *d._2).reduce(_+_).toDouble 49 //求解分母的第一個變量 50 val temp1=math.sqrt(user1FilmSource.map(num=>{math.pow(num,2)}).reduce(_+_)) 51 //求解分母第二個變量 52 val temp2=math.sqrt(user2FileSource.map(num=>{math.pow(num,2)}).reduce(_+_)) 53 //求出分母 54 val denominator=temp1*temp2 55 //求出分式的值 56 member/denominator 57 } 58 def main(args: Array[String]) { 59 //初始化分數 60 getSource() 61 //設定目標對象 62 val name="bbb" 63 //進行迭代計算 64 users.foreach(user=>{ 65 println(name+" 相對於"+user+"的相似性分數是:"+getCollaborateSource(name,user)) 66 }) 67 } 68 }
點擊可復制代碼
1 package com.bigdata.demo 2 3 import org.apache.spark.{SparkContext, SparkConf} 4 5 /** 6 * Created by SimonsZhao on 3/29/2017. 7 */ 8 object CollaborativeFilteringSpark { 9 //1.設置環境變量 10 val conf=new SparkConf().setMaster("local").setAppName("CollaborativeFilteringSpark") 11 //2.實例化環境 12 val sc=new SparkContext(conf) 13 //3.設置用戶 14 val users=sc.parallelize(Array("aaa","bbb","ccc","ddd","eee")) 15 //4.設置電影名 16 sc.parallelize(Array("smzdm","ylxb","znb","nhsc","fcwr")) 17 //5.使用一個source嵌套map作為姓名電影名和分值的存儲 18 var source=Map[String,Map[String,Int]]() 19 //6.設置一個用以存放電影分的map 20 val filmSource =Map[String,Int]() 21 //7.設置電影評分 22 def getSource():Map[String,Map[String,Int]]={ 23 val user1FilmSource=Map("smzdm"->2,"ylxb"->3,"znb"->1,"nhsc"->0,"fcwr"->1) 24 val user2FilmSource=Map("smzdm"->1,"ylxb"->2,"znb"->2,"nhsc"->1,"fcwr"->4) 25 val user3FilmSource=Map("smzdm"->2,"ylxb"->1,"znb"->0,"nhsc"->1,"fcwr"->4) 26 val user4FilmSource=Map("smzdm"->3,"ylxb"->2,"znb"->0,"nhsc"->5,"fcwr"->3) 27 val user5FilmSource=Map("smzdm"->5,"ylxb"->3,"znb"->1,"nhsc"->1,"fcwr"->2) 28 //存儲人的名字 29 source += ("aaa" -> user1FilmSource) 30 //存儲人的名字 31 source += ("bbb" -> user2FilmSource) 32 //存儲人的名字 33 source += ("ccc" -> user3FilmSource) 34 //存儲人的名字 35 source += ("ddd" -> user4FilmSource) 36 //存儲人的名字 37 source += ("eee" -> user5FilmSource) 38 //返回嵌套的map 39 source 40 } 41 //采用余弦相似度兩兩計算分值 42 def getCollaborateSource(user1:String,user2:String):Double={ 43 //獲得第一個用戶的評分 44 val user1FilmSource =source.get(user1).get.values.toVector 45 //獲得第二個用戶的評分 46 val user2FileSource=source.get(user2).get.values.toVector 47 //對公示分子部分進行計算 48 val member=user1FilmSource.zip(user2FileSource).map(d => d._1 *d._2).reduce(_+_).toDouble 49 //求解分母的第一個變量 50 val temp1=math.sqrt(user1FilmSource.map(num=>{math.pow(num,2)}).reduce(_+_)) 51 //求解分母第二個變量 52 val temp2=math.sqrt(user2FileSource.map(num=>{math.pow(num,2)}).reduce(_+_)) 53 //求出分母 54 val denominator=temp1*temp2 55 //求出分式的值 56 member/denominator 57 } 58 def main(args: Array[String]) { 59 //初始化分數 60 getSource() 61 //設定目標對象 62 val name="bbb" 63 //進行迭代計算 64 users.foreach(user=>{ 65 println(name+" 相對於"+user+"的相似性分數是:"+getCollaborateSource(name,user)) 66 }) 67 } 68 }
(3)結果分析

