推荐系统-基于标签的Top-N个性化推荐代码实现

随着移动互联网的快速发展,UGC标签系统受到越来越多推荐应用,标签不但能反映用户的兴趣又能描述物品的本身特征。现有的标签推荐算法没有考虑用户的连续行为所产生的影响,于是人们提出了一种基于标签的个性化推荐算法。该算法将〈用户-标签-物品〉的三维关系拆分为〈用户-标签〉和〈标签-物品〉两个二维关系。 通过推荐标签集来匹配与其相对应的物品,为了提高推荐的精准率,该算法利用标签之间的影响,并基于匹配物品中所含标签间存在的关联关系对物品进行满意度建模,该模型是一种概率模型。在计算用户-标签和用户-物品之间的兴趣度和满意度时使用了协同过滤的思想来补全稀疏值。在公开的数据集中,与现有算法相比,该算法在精准率、召回率上均有明显提高。
因此,本文将主要探讨如何利用用户打标签的行为为其推荐物品。一个用户标签行为的数据集可以由一个三元组集合表示,其中每条样本(u,i,b)表示用户u为物品i打上了标签b。

1、标签作为特征/类别划分

我们可以将标签看做是LFM中的隐类(这里是显式的),用户u对物品i的兴趣度可表示为:
p ( u , i ) = ∑ b n u b n b i p(u,i)=\sum_{b}n_{ub}n_{bi} p(u,i)=bnubnbi
n u b n_{ub} nub:用户u打过标签b的次数,可以看做是用户u对b类物品的喜好程度;
n b i n_{bi} nbi:物品i被打过b标签的次数,可以看做物品i属于b类的”概率“值
仔细研究以上公式我们可以发现如下缺点:

  • 热门标签给 n u b n_{ub} nub的权重很大;
  • 热门物品给 n b i n_{bi} nbi的权重也很大;

借鉴TF-IDF的思路,可以通过惩罚用户或物品中热门标签的方式来优化以上公式:
p ( u , i ) = ∑ b n u b l o g ( 1 + n b u ) n b i l o g ( 1 + n i u ) p(u,i)=\sum_{b}\frac{n_{ub}}{log(1+n_b^u)}\frac{n_{bi}}{log(1+n_i^u)} p(u,i)=blog(1+nbu)nublog(1+niu)nbi

  • 1 + n b u 1+n_b^u 1+nbu:标签b被多少个用户使用过;
  • n i u n_i^u niu:物品i被多少个用户打过标签;
    标签的稀疏性:对于新用户或新物品,集合B(u)⋂B(i)中的标签数量很少。
1.1 标签扩展

为提高推荐准确率,需要对标签集合进行进一步扩展,如果用户使用过某个标签,我们可以将与这个标签相似的其他标签也加入到用户标签集合中去。扩展标签的方式有很多,常用的有话题模型,这里介绍一种基于邻域的方法,核心是计算标签之间的相似度。可以用两个标签下物品的重合度来计算它们之间的相似度
Alt

2、 适用场景:

  • 商城类:用户偏好商品UGC标签推荐;
  • 社交类:用户喜欢UGC标签推荐;

3、冷启动问题解决方案:

  • 客户注册时,勾选喜欢的标签,如是商城勾选喜欢的商品标签,如是社交内网站勾选喜欢社交类别;
  • 热门商品填充;

4、基于商品标签推荐代码

/**商品数据*/
case class Product(productId:Int, name:String, imageUrl:String, categories:String, tags:String)
//mongodb 配置
case class MongoConfig(uri:String, db:String)
//定义标准推荐对象
case class Recommendation(productId:Int, score:Double)
//定义商品相似度列表
case class ProductRecs(productId:Int, recs:Seq[Recommendation])

object ContentRecommender {
  //定义数据存储mongodb存储的表名
  val MONGODB_PRODUCT_COLLECTION = "product"
  //定义一个基于内容推荐商品列表
  val CONTENT_PRODUCT_RECS = "ContentBasedProductRecs"
  //总特征数量:本身词汇比较多,不设置会按照很大特征值(消耗内存高), 特征数量其实Hash桶数量,设置少会导致hash碰撞
  var NUM_FEATURES = 800
  //推荐商品数,最小相似度值控制
  val PRODUCT_SIMILAR_RATE = 0.4

  def main(args: Array[String]): Unit = {
    val config = Map(
      "spark.cores" -> "local[*]",
      "mongo.uri" -> "mongodb://localhost:27017/spark-recommender",
      "mongo.db" -> "spark-recommender"
    )
    val sparkConf = new SparkConf().setMaster(config("spark.cores")).setAppName("ContentRecommender")
    val spark = SparkSession.builder().config(sparkConf).getOrCreate()
    import spark.implicits._
    implicit val mongoConfig = MongoConfig(config("mongo.uri"), config("mongo.db"))

    //1、加载商品数据
    val productTagsDF = spark.read
      .option("uri", mongoConfig.uri)
      .option("collection", MONGODB_PRODUCT_COLLECTION)
      .format("com.mongodb.spark.sql")
      .load()
      .as[Product]
      .map {
        item =>
          val tags = item.tags.replace('|', ' ')
          (item.productId, item.name, tags)
      }
      .toDF("productId", "name", "tags")
      .cache()

    //2、计算文档总分词数
    val dsTags:Dataset[Array[String]] = productTagsDF.select("tags").map(x => x.toString.split(" "))
    val all_terms: Array[String] = dsTags.flatMap(iterArr => iterArr).distinct().collect()
    NUM_FEATURES = all_terms.length

    //3: 用TF-IDF提取商品特征向量
    val tokenizer = new Tokenizer().setInputCol("tags").setOutputCol("words")
    val wordsDataDF = tokenizer.transform(productTagsDF)

    //4、计算TF:定义一个HashingTF工具,计算频次
    val hashingTF = new HashingTF().setInputCol("words").setOutputCol("rawFeatures").setNumFeatures(NUM_FEATURES)
    val featurizedDataDF = hashingTF.transform(wordsDataDF)
    
    //5、定义一个IDF工具,计算TF-IDF
    val idf = new IDF().setInputCol("rawFeatures").setOutputCol("features")
    val idfModel = idf.fit(featurizedDataDF)
    val rescaledTfIDF = idfModel.transform(featurizedDataDF)

    //6、对数据进行转换,得到RDD的features
    val productFeatures = rescaledTfIDF.map {
      row => (row.getAs[Int]("productId"), row.getAs[SparseVector]("features").toArray)
    }.rdd
      .map {
        case (productId, features) => (productId, new DoubleMatrix(features))
      }

    //计算余弦相似度
    val productRecsDF = productFeatures.cartesian(productFeatures)
      .filter {
        case (a, b) => a._1 != b._1 
      }
      .map {
        case (a, b) =>
          val simScore = cosineSim(a._2, b._2) 
          (a._1, (b._1, simScore))
      }
      .filter(_._2._2 > PRODUCT_SIMILAR_RATE) 
      .groupByKey()
      .map {
        case (productId, recs) =>
          val list = recs.toList
          ProductRecs(productId, list.map(x => Recommendation(x._1, x._2)))
      }.toDF()
    storeDFInMongoDB(productRecsDF, CONTENT_PRODUCT_RECS)

    spark.stop()
  }


  /**
   * 存储信息到mongodb数据库
   *
   * @param df
   * @param collectionName
   * @param mongoConfig
   */
  def storeDFInMongoDB(df: DataFrame, collectionName: String)(implicit mongoConfig: MongoConfig): Unit = {
    df.write
      .option("uri", mongoConfig.uri)
      .option("collection", collectionName)
      .mode(SaveMode.Overwrite)
      .format("com.mongodb.spark.sql")
      .save()
  }

  /**
   * 计算两个向量集合的余弦相似度
   *
   * @param product1 商品1的矩阵
   * @param product2 商品2的矩阵
   */
  def cosineSim(product1: DoubleMatrix, product2: DoubleMatrix): Double = {
    product1.dot(product2) / (product1.norm2() * product2.norm2())
  }
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
【项目介绍】 基于Django协同过滤和spark-als的电影推荐系统源码+项目使用说明+设计报告.zip 该资源内项目代码都是经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也适合小白学习进阶, 或者实际项目借鉴参考! 当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。如果基础还行,也可在此代码基础上进行修改,以实现其他功能。 说明 1. 新手建议结合pycharm使用,https://www.jetbrains.com/pycharm/,下载专业版试用30天。 2. 注册普通用户通过web界面来设置,创建创建用户通过creeatsuperuser创建。下文有详细命令 3. 导入电影信息通过insert_movies_script.py来操作 (会删除已有的所有信息!) 4. 前端展示 浏览最多,评分最多,收藏最多,写的比较直白,你可以改的委婉点: 最热电影,火爆排行...之类的。每种有10条。 我猜你喜欢为基于用户推荐,item推荐为基于项目推荐。两种推荐思路下文有介绍 系统采用的技术 前端: bootstrap3 css 框架 后端: django 2.2.1 + sqlite3数据库 (MVC框架) 数据: python异步爬虫从豆瓣top250抓取数据,保存到本地csv文件中 主要功能: 录入图书信息,用户打分,电影标签分类,电影推荐,电影分享,电影收藏,后台管理系统。 整体采用MVC架构,前端页面通过django template模板来实现实现了模板的复用功能。同时前端页面的组织结构较为清晰。 推荐算法思路 通过协调过滤计算和其他用户的距离,然后进行筛选。如果用户数量不足,推荐数目不够15条,就会自动从 所有未打分的电影中按照浏览数降序选一部分填充进去。 基于用户的推荐 1. 用户需要给电影打分。通过用户已打分的部分来计算相似度,如果用户未打分,或者没有其他用户,则按照浏览数降序返回。 2. 通过pearson算法来计算用户之间的距离,找到距离最近的N个用户。将这些用户中已打分的电影(且要推荐的用户未看过的部分)返回。 基于item的推荐 1. 计算物品相似度矩阵: https://www.jianshu.com/p/27b1c035b693 2. 遍历当前用户已打分的item,计算和未打分的item的相似距离。 3. 对相似距离进行排序 返回 主要实现的功能 1. 登录注册页面 2. 基于协同过滤的电影的分类,排序,搜索,打分,排序功能。 3. 基于协同过滤的周推荐和月推荐 4. 观影分享会等活动功能,用户报名功能 (需要额外添加) 5. 发帖留言论坛功能 (要额外添加) 6. 基于spark的ALS算法 (要额外添加) 7. Mysql适配 8. movielens数据集适配 fixed 1. 首页导航栏链接错误 2. 首页面为空 3. 登录注册页面 4. 推荐跳转登录 5. 周推荐用户没有评分时随机推荐 6. 按照收藏数量排序 7. 重新设计了 action 和UserAction model,拆分出了UserAction 电影模型 1. 浏览量 每次刷新页面的浏览数 2. 收藏量 user manytomany field 每个用户收藏一次 3. 评分 rate 每个用户评分一次 4. 在电影下面的评论加点赞功能 安装运行方法 安装依赖 1. 将项目导入pycharm, 在pycharm配置python解释器,3.7及以下都可以。可以通过conda或者其他的虚拟环境来安装 2. 打开终端 输入pip install -r requirements.txt 若提示无pip。去下载get-pip.py 运行python get-pip.py 3. 在pip安装过程中如果报错C++ 14依赖问题。则安装c++依赖工具。找不到找我要。如果安装速度过慢,请更换国内镜像https://blog.csdn.net/chenghuikai/article/details/55258957 4. 安装成功后,进入运行阶段 运行 1. 运行服务器: python manage.py runserver 2. 如果无数据,运行项目根目录下的数据迁移脚本 populate开头。 3. python manage.py createsuperuser 创建超级管理员, (密码输入时终端暂时看不到) 4. 进入后台: 127.0.0.1:8000/admin
基于Python的个性化电影推荐系统的源代码可以包括以下几个主要部分: 1. 数据预处理:首先需要准备电影和用户的数据集,包括电影的特征信息和用户的评分信息。可以使用pandas库进行数据读取和处理,例如将电影特征转换为向量表示。 2. 特征工程:根据电影和用户的特征信息,可以进行特征工程,例如提取电影的类型、导演、演员等特征,以及用户的历史评分、观看记录等特征。可以使用scikit-learn库进行特征提取和转换。 3. 相似度计算:根据电影的特征信息,可以计算电影之间的相似度。常用的相似度计算方法包括余弦相似度、欧氏距离等。可以使用scikit-learn库或者自定义函数进行相似度计算。 4. 推荐算法:根据用户的历史评分和电影的相似度,可以使用推荐算法来生成个性化的电影推荐结果。常用的推荐算法包括基于内容的推荐、协同过滤推荐等。可以使用scikit-learn库或者其他推荐算法库进行推荐算法的实现。 5. 用户界面:可以使用Flask等Web框架搭建一个简单的用户界面,用户可以输入自己的喜好和评分,系统根据用户的输入进行电影推荐。 以下是一个简单的示例代码,用于基于内容的电影推荐: ```python import pandas as pd from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.metrics.pairwise import cosine_similarity # 读取电影数据集 movies = pd.read_csv('movies.csv') # 特征工程:将电影类型转换为向量表示 tfidf = TfidfVectorizer() genre_matrix = tfidf.fit_transform(movies['genres']) # 计算电影之间的相似度 similarity_matrix = cosine_similarity(genre_matrix) # 根据用户的历史评分和电影相似度进行推荐 def recommend_movies(user_ratings, similarity_matrix, movies): # 根据用户评分筛选出未观看的电影 unrated_movies = movies[~movies['movieId'].isin(user_ratings.keys())] # 计算每部未观看电影的推荐分数 scores = [] for index, movie in unrated_movies.iterrows(): movie_id = movie['movieId'] similarity_scores = similarity_matrix[movie_id] weighted_sum = sum([score * user_ratings[movie_id] for score in similarity_scores]) scores.append((movie_id, weighted_sum)) # 根据推荐分数排序并返回前N部电影 scores.sort(key=lambda x: x[1], reverse=True) top_movies = scores[:10] return top_movies # 示例使用:假设用户已经观看并评分了电影1和电影2 user_ratings = {1: 5, 2: 4} # 生成推荐结果 recommendations = recommend_movies(user_ratings, similarity_matrix, movies) # 打印推荐结果 for movie_id, score in recommendations: movie_title = movies[movies['movieId'] == movie_id]['title'].values[0] print(f"推荐电影:{movie_title},推荐分数:{score}") ``` 这只是一个简单的示例代码,实际的个性化电影推荐系统可能会更加复杂,涉及到更多的特征工程和推荐算法。希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Moutai码哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值