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

news2025/2/25 11:43:12

随着移动互联网的快速发展,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 =>
          //通过对tags的|替换为 ' '空格,后面分词器默认按照空格分割
          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(" "))
    //使用flatMap合并Array[String]所有项
    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")
    //计算逆文件频率: 训练一个idf的模型
    val idfModel = idf.fit(featurizedDataDF)
    //将词频(TF)转换为TF-IDF向量: 得到增加新列feature的DF,(最终特征向量)
    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())
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/767865.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【idea】idea全局设置Maven配置

Idea版本:2021.1.1 1、点击File->Close project 2、点击Customize->All settings 3、设置Maven

2023年8个最佳WordPress电子书主题

您是正在为您的网站寻找最佳的WordPress电子书主题吗?无论您是独立作家、出版社还是同时销售电子书和实体书的在线书店,拥有一个可以直接销售电子书的网站都是一个好主意。 销售电子书可能有助于分销和扩大影响力,但也会侵蚀您的利润。例如&…

11、动手学深度学习——语言模型和数据集:代码详解

我们了解了如何将文本数据映射为词元,以及将这些词元可以视为一系列离散的观测,例如单词或字符。 假设长度为 T T T的文本序列中的词元依次为 x 1 , x 2 , … , x T x_1, x_2, \ldots, x_T x1​,x2​,…,xT​。于是, x t x_t xt​&#xff08…

spring整合dataJPA

1.入门案例 1.1 项目整体结构 表:sql DROP TABLE IF EXISTS t_user; CREATE TABLE t_user ( user_id int(0) NOT NULL AUTO_INCREMENT, user_name varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, real_name varchar(255) CHAR…

关于互联网金融平台性能测试的过程经历分享

目录 项目角色 测试范围 测试策略 项目角色 性能测试专家,负责互金平台以及5个关联外围系统性能测试方案制定、测试策略制定,测试前期配合架构组,某某云根据平台内各模块的目标处理能力流量统计来计算调用占比并估算机器设备配置。端对端…

数据结构 ~ 栈、队列

栈 一个后进先出的数据结构、JS中没有栈,可以使用 Array 模拟 const stack [] stack.push(1) // 入栈 stack.push(2) // 入栈 const item1 stack.pop() // 出栈 const item2 stack.pop() // 出栈以上代码可以使用 nodeJs 断点调试(F5启动&#xff0…

伊利投资者日:千亿航母如何“加速度”?

7月14日,伊利股份举办了投资者日活动。在交流中,伊利股份管理层积极表示了实现 “2025年实现全球乳业前三,2030年实现全球乳业第一”的目标信心,也展示了公司目前的成绩以及长期成长的规划。 从投资者日活动来看,伊利透…

10.6.4 【Linux】字符转换命令: tr, col, join, paste, expand

tr tr 可以用来删除一段讯息当中的文字,或者是进行文字讯息的替换。 其实这个指令也可以写在“正则表达式”里头!因为他也是由正则表达式的方式来取代数据的!以上面的例子来说,使用 [] 可以设置一串字呢!也常常用来取…

C语言项目小游戏之俄罗斯方块

今天给大家带来一个用C语言实现的俄罗斯方块小游戏 游戏截图&#xff1a; 首先我们先创建一个名为mywindows.h的头文件。用来设置我们操作台的各种功能实现 mywindows.h #ifndef MYWINDOWS_H_INCLUDED #define MYWINDOWS_H_INCLUDED//系统调用模块 #include <windows.h&g…

华为OD机试真题 Java 实现【计算最接近的数】【2023 B卷 100分】,附详细解题思路

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、具体解题步骤六、Java算法源码七、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xf…

HCIP第六次作业

1.创建VLAN&#xff0c;并改变相连各自PC接口的类型&#xff0c;同时划分VLAN&#xff0c;做策略即保证&#xff1a;pc2可以访问PC4/5/6;但PC4可以访问Pc5&#xff0c;不能访问PC6 &#xff1b;PC5不能访问PC6 [sw1]vlan batch 2 to 5 批量创建VLAN [sw1]int g0/0/1 [sw1-Gig…

MySQL数据库与表的基本操作 + 表的基本CRUD(增删改查)操作

文章目录 前言一、库的基本操作显示当前所有数据库创建数据库使用数据库删除数据库 二、表的基本操作创建表查看库中所有表查看表结构删除表 三、表的增删改查(基础)新增数据(Create)全列插入指定列插入 查询数据(Retrieve)全列查询指定列查询查询字段为表达式指定列的别名去重…

微服务: 04-springboot中rabbitmq配置,消息回收,序列化方式

目录 1. 本文简介: 1.1 java序列化的缺点 ---> 1.1.1 无法跨语言 --->1.1.2 易被攻击 ---> 1.1.3 序列化后的流太大 ---> 1.1.4 序列化性能太差 2. 配置总览 2.1 基础配置 2.2 连接重试配置 2.3 异常重试机制 2.4 确认模式(本篇是自动) ---> 2.4.1…

VoIP监控工具有什么作用

VoIP 监控工具利用思科的 IPSLA 技术生成合成流量并监控客户端体验的呼叫质量。与被动监控VoIP指标相反&#xff0c;IPSLA技术允许IT管理员主动并在潜在问题发生之前检测到它们&#xff0c;这使组织能够轻松遵守严格的SLA指标。 思科 IPSLA 技术在两台设备之间创建流量&#x…

【Ceph集群应用】Ceph块存储之RBD接口详解

Ceph块存储之RBD接口详解 1.创建Ceph块存储系统RBD接口1.1 删除镜像1.2 还原镜像1.3 在线扩容1.4 回滚镜像到指定位置1.5 删除快照1.6 快照分层1.7 快照展平1.8 镜像的导出导入 接上文基于ceph-deploy部署Ceph集群详解 1.创建Ceph块存储系统RBD接口 &#xff08;1&#xff09;…

一文9个步骤带你从0到1入门接口自动化测试!

1.请问你是如何做接口测试的&#xff1f; 大体来说&#xff0c;经历以下过程&#xff1a;接口需求调研、接口测试工具选择、接口测试用例编写、接口测试执行、接口测试回归、接口测试自动化持续集成。 具体来说&#xff0c;接口测试流程分成以下九步&#xff1a; 第一步&…

设计模式 ~ 观察者模式

概念 观察者模式是一种设计模式&#xff0c;也被称为发布-订阅模式或事件模式&#xff1b; 用于在对象之间建立一种一对多的依赖关系&#xff0c;当一个对象的状态发生改变时&#xff0c;所有依赖于它的对象都会得到通知并自动更新&#xff1b; ~ 如&#xff1a;DOM事件、vue …

【Windows】重新安装显卡

我的设备&#xff1a; ROG 幻15 显卡重装教程&#xff1a; 进入nvidia官网 https://www.nvidia.cn/geforce/drivers/ 下载GeForce Game Ready 驱动程序

哇~真的是你呀!今天是LIUNX中的SAMBA。

目录 前言 一、概述 二、安装 三、在SAMBA服务器中设置共享目录 四、客户端查看共享目录及登录 五、本地映射 六、客户端自动挂载 七、用户别名 八、访问控制 总结 前言 SAMBA是一个开源的软件套件&#xff0c;用于在Linux和UNIX系统上实现SMB/CIFS网络协议。SMB&#xff08;S…

blender 阵列修改器

效果 tab 键进入编辑模式&#xff0c;全选制作好的模型&#xff0c;gx 移动模型置于游标原点&#xff1b; 阵列修改器&#xff1a; 相对偏移&#xff1a;以物体的长宽高为比例&#xff0c;调整x y z 的数值&#xff0c;在 x y z 方向上做不同比例的偏移&#xff1b; 恒定偏移…