Spark实现之 好友推荐

本文介绍了一种基于邻接表的好友推荐算法,并使用Spark进行实现。该算法通过分析用户与其好友间的关系,找出用户好友的好友并与用户非直接好友的用户,将其作为推荐对象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

网上好多好推荐之类的博客都是基于二度好友的推荐,下面介绍基于邻接表的好友推荐的spark实现。

输入:

    1 2,3,4,5,6,7,8  
    2 1,3,4,5,7  
    3 1,2  
    4 1,2,6  
    5 1,2  
    6 1,4  
    7 1,2  
    8 1  
第一列表示用户,后面的表示用户的所有好友。

需求:找出用户好友的好友且与用户不是好友的,推荐给用户。

思路:1、key为user,value可设计成user有关联关系的人及关联关系的说明,例如:

                    key:"1"  value:<"2", "yes"> 表示"1"与"2"已经是好友关系

                    key:"2" value:<"3", "1">表示"2"与"3"共同的好友为"1"

            2、对reduce后的key的value做归类,比如把key为"2"的value的第一个值为"3"的value归为一组,这一组value中的第二个值若没有"yes"出现,则把"3"推荐给"2",若有"yes"出现,说明"2"与"3"已为好友关系。

步骤:1、map:读取每行数据,组合user与每一个好友,两两组合user的好友。

            2、reduce:分析value的第一个值是否时key好友,若不是则可以推荐给key。

package dabook

import org.apache.spark.{SparkConf, SparkContext}
import collection.mutable.{ HashMap, MultiMap, Set }

import scala.collection.mutable

object RecommFriend {

  def mymap(x:String): List[(String, (String, String))] ={
    var result = List[(String, (String, String))]()
    val arr = x.split(" ")
    if(arr.length != 2){
      return result
    }
    val host = arr(0).trim //主体
    val friends = arr(1).trim
    val arr_frinds = friends.split(",") //主体的列表

    for (s <- arr_frinds){
      result ::= (host, (s, "yes")) //yes表示已为好友关系
    }

    for(i <- Range(0, arr_frinds.length); j <- Range(i+1, arr_frinds.length)){
      result ::= (arr_frinds(i), (arr_frinds(j), host)) //好友列表两两分组,host是他们共同的好友
      result ::= (arr_frinds(j), (arr_frinds(i), host))
    }
    result
  }

  def myreduce(x:Iterable[(String, String)]): String ={
    var result = new String()

    var mm = new mutable.HashMap[String, Set[String]] with mutable.MultiMap[String, String]
    for(s <- x){
      mm.addBinding(s._1, s._2)
    }
    var sb = new mutable.StringBuilder()
    val ks = mm.keys
    for(k <- ks){
      var flag = true
      val values = mm.get(k)
      for (v <- values.get){
        if(v.equals("yes")){
          flag = false
        }
      }
      if(flag){
        sb.append("推荐好友:" + k + " 共同的好友:")
        sb.append(values.get.mkString(", "))
        sb.append(" | ")
      }
      if(sb.length > 2){
        result = sb.substring(0, sb.length-3)
      }
      else {
        result = sb.toString()
      }
    }
    result
  }

  def main(args: Array[String]): Unit = {
    val sparkConf = new SparkConf().setMaster("local[2]").setAppName("recommfriend")
    val sc = new SparkContext(sparkConf)
    val input = sc.textFile("/home/xdk/file/friend")
    val res = input.flatMap(x=>mymap(x)).groupByKey().map(x=>(x._1, myreduce(x._2)))
    res.foreach(println)

    //test1()

  }

  def test(): Unit ={
    val ss = "1 2,3,4"
    val res = mymap(ss)
    println(res.size)
    println(res)
  }

  def test1(): Unit ={
    var mmm = new mutable.HashMap[String, Set[String]] with mutable.MultiMap[String, String]
    mmm.addBinding("123", "asd")
    mmm.addBinding("123", "dsad")
    mmm.addBinding("43345", "dasd")

    val keys1 = mmm.keys
    println(keys1)
    for(s <- keys1){
      println(s)
    }
  }

}

输出:

(8,推荐好友:2 共同的好友:1 | 推荐好友:5 共同的好友:1 | 推荐好友:7 共同的好友:1 | 推荐好友:4 共同的好友:1 | 推荐好友:6 共同的好友:1 | 推荐好友:3 共同的好友:1)
(7,推荐好友:5 共同的好友:1, 2 | 推荐好友:8 共同的好友:1 | 推荐好友:4 共同的好友:1, 2 | 推荐好友:6 共同的好友:1 | 推荐好友:3 共同的好友:1, 2)
(4,推荐好友:5 共同的好友:1, 2 | 推荐好友:8 共同的好友:1 | 推荐好友:7 共同的好友:1, 2 | 推荐好友:3 共同的好友:1, 2)
(5,推荐好友:8 共同的好友:1 | 推荐好友:7 共同的好友:1, 2 | 推荐好友:4 共同的好友:1, 2 | 推荐好友:6 共同的好友:1 | 推荐好友:3 共同的好友:1, 2)
(6,推荐好友:2 共同的好友:4, 1 | 推荐好友:5 共同的好友:1 | 推荐好友:8 共同的好友:1 | 推荐好友:7 共同的好友:1 | 推荐好友:3 共同的好友:1)
(3,推荐好友:5 共同的好友:1, 2 | 推荐好友:8 共同的好友:1 | 推荐好友:7 共同的好友:1, 2 | 推荐好友:4 共同的好友:1, 2 | 推荐好友:6 共同的好友:1)
(2,推荐好友:8 共同的好友:1 | 推荐好友:6 共同的好友:4, 1)
(1,)





### 基于 Spark 实现好友推荐系统 #### 构建环境准备 为了利用Apache Spark构建高效的好友推荐系统,需先准备好运行环境。确保已安装并配置好Spark集群,并能够使用Scala、Java、Python或R编程语言之一来操作数据集[^1]。 #### 数据收集与预处理 在实际应用中,通常会从社交网络获取用户之间的互动记录作为输入源。这些原始日志可能包含了时间戳、发起者ID、接收方ID以及其他上下文信息。对于本项目而言,假设已经拥有一份CSV文件`interactions.csv`,其中每行代表一次交互行为: | user_id | friend_id | |---------|-----------| | 0 | 1 | | 0 | 2 | | ... | ... | 可以采用如下方式加载此表格到DataFrame对象内以便后续分析: ```python from pyspark.sql import SparkSession spark = SparkSession.builder.appName('FriendRecommendation').getOrCreate() df_interactions = spark.read.option("header", "true").csv("path/to/your/file/interactions.csv") ``` #### 计算相似度矩阵 接下来要做的就是计算所有用户的两两之间共同朋友数量,以此为基础建立关联强度指标。这里可以通过自连接的方式找出所有的(userA, userB)组合及其共有的联系人数目: ```sql SELECT a.user_id AS user_a, b.user_id AS user_b, COUNT(*) as common_friends_count FROM df_interactions a JOIN df_interactions b ON (a.friend_id=b.friend_id AND a.user_id<b.user_id) GROUP BY a.user_id,b.user_id; ``` 上述SQL语句的结果可以直接保存成新的表结构供下一步骤调用。 #### 推荐候选列表生成 有了之前得到的相似度评分之后,就可以针对每一个目标个体挑选出最有可能成为新伙伴的对象集合了。考虑到性能因素,在实践中往往只会保留前N名候选人;另外还需注意排除掉那些已经被标记为现有好友的关系配对以免重复推荐。 ```python top_n_recommendations = ( df_similarity_scores.filter(f"user_a={target_user}") .orderBy(desc("common_friends_count")) .limit(10)) ``` 此处仅展示了如何选取特定用户的潜在交友建议,而完整的业务逻辑还需要进一步完善以适应更广泛的应用场景需求。 #### 结果评估与持续改进 最后一步是对整个流程的效果进行全面衡量,包括但不限于精确率(Precision)、召回率(Recall)等常见评价标准。根据反馈不断调整参数设置直至达到满意水平为止。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值