推荐算法,基于隐语义模型的协同过滤推荐之商品相似度矩阵

项目采用ALS作为协同过滤算法,根据MongoDB中的用户评分表计算离线的用户商品推荐列表以及商品相似度矩阵。

通过ALS计算商品相似度矩阵,该矩阵用于查询当前商品的相似商品并为实时推荐系统服务。

离线计算的ALS 算法,算法最终会为用户、商品分别生成最终的特征矩阵,分别是表示用户特征矩阵的U(m x k)矩阵,每个用户有 k个特征描述;表示物品特征矩阵的V(n x k)矩阵,每个物品也由 k 个特征描述。

V(n x k)表示物品特征矩阵,每一行是一个 k 维向量,虽然我们并不知道每一个维度的特征意义是什么,但是k 个维度的数学向量表示了该行对应商品的特征。

所以,每个商品用V(n x k)每一行的向量表示其特征,于是任意两个商品 p:特征向量为,商品q:特征向量为之间的相似度sim(p,q)可以使用和的余弦值来表示:

数据集中任意两个商品间相似度都可以由公式计算得到,商品与商品之间的相似度在一段时间内基本是固定值。最后生成的数据保存到MongoDB的ProductRecs表中。

核心代码如下:

//计算商品相似度矩阵


//获取商品的特征矩阵,数据格式 RDD[(scala.Int, scala.Array[scala.Double])]


val productFeatures = model.productFeatures.map{case (productId,features) =>


  (productId, new DoubleMatrix(features))


}


// 计算笛卡尔积并过滤合并
val productRecs = productFeatures.cartesian(productFeatures)


  .filter{case (a,b) => a._1 != b._1} 
  .map{case (a,b) =>


    val simScore = this.consinSim(a._2,b._2) // 求余弦相似度


    (a._1,(b._1,simScore))


  }.filter(_._2._2 > 0.6)   
  .groupByKey()            
  .map{case (productId,items) =>


    ProductRecs(productId,items.toList.map(x => Recommendation(x._1,x._2)))


  }.toDF()


productRecs


  .write


  .option("uri", mongoConfig.uri)


  .option("collection",PRODUCT_RECS)


  .mode("overwrite")


  .format("com.mongodb.spark.sql")


  .save()

其中,consinSim是求两个向量余弦相似度的函数,代码实现如下:

//计算两个商品之间的余弦相似度
def consinSim(product1: DoubleMatrix, product2:DoubleMatrix): Double ={
  product1.dot(product2) / ( product1.norm2()  * product2.norm2() )
}

在上述模型训练的过程中,我们直接给定了隐语义模型的rank,iterations,lambda三个参数。对于我们的模型,这并不一定是最优的参数选取,所以我们需要对模型进行评估。通常的做法是计算均方根误差(RMSE),考察预测评分与实际评分之间的误差。

有了RMSE,我们可以就可以通过多次调整参数值,来选取RMSE最小的一组作为我们模型的优化选择。

在scala/com.atguigu.offline/下新建单例对象ALSTrainer,代码主体架构如下:

def main(args: Array[String]): Unit = {


  val config = Map(


    "spark.cores" -> "local[*]",


    "mongo.uri" -> "mongodb://localhost:27017/recommender",


    "mongo.db" -> "recommender"


  )


  //创建SparkConf


  val sparkConf = new SparkConf().setAppName("ALSTrainer").setMaster(config("spark.cores"))


  //创建SparkSession


  val spark = SparkSession.builder().config(sparkConf).getOrCreate()

  val mongoConfig = MongoConfig(config("mongo.uri"),config("mongo.db"))

  import spark.implicits._

  //加载评分数据


  val ratingRDD = spark


    .read


    .option("uri",mongoConfig.uri)


    .option("collection",OfflineRecommender.MONGODB_RATING_COLLECTION)


    .format("com.mongodb.spark.sql")


    .load()


    .as[ProductRating]


    .rdd


    .map(rating => Rating(rating.userId,rating.productId,rating.score)).cache()


  // 将一个RDD随机切分成两个RDD,用以划分训练集和测试集

  val splits = ratingRDD.randomSplit(Array(0.8, 0.2))

  val trainingRDD = splits(0)


  val testingRDD = splits(1)

  //输出最优参数

  adjustALSParams(trainingRDD, testingRDD)

  //关闭Spark


  spark.close()

}

其中adjustALSParams方法是模型评估的核心,输入一组训练数据和测试数据,输出计算得到最小RMSE的那组参数。代码实现如下:

//输出最终的最优参数
def adjustALSParams(trainData:RDD[Rating], testData:RDD[Rating]): Unit ={
//这里指定迭代次数为5,rank和lambda在几个值中选取调整  
val result = for(rank <- Array(100,200,250); lambda <- Array(1, 0.1, 0.01, 0.001))


    yield {


      val model = ALS.train(trainData,rank,5,lambda)


      val rmse = getRMSE(model, testData)


      (rank,lambda,rmse)


    }


  // 按照rmse排序


  println(result.sortBy(_._3).head)


}

计算RMSE的函数getRMSE代码实现如下:

def getRMSE(model:MatrixFactorizationModel, data:RDD[Rating]):Double={


  val userProducts = data.map(item => (item.user,item.product))


  val predictRating = model.predict(userProducts)
val real = data.map(item => ((item.user,item.product),item.rating))


  val predict = predictRating.map(item => ((item.user,item.product),item.rating))


  // 计算RMSE


  sqrt(


    real.join(predict).map{case ((userId,productId),(real,pre))=>


      // 真实值和预测值之间的差


      val err = real - pre


      err * err


    }.mean()


  )


}

运行代码,我们就可以得到目前数据的最优模型参数。

### 回答1: Java基于内容的协同过滤推荐算法有以下几种: 1. 基于用户的协同过滤(User-Based Collaborative Filtering):该算法通过分析用户之间的相似性,将相似用户的喜好进行推荐。具体步骤包括计算用户之间的相似性,选择与目标用户最相似的用户集合,然后根据这些相似用户的喜好来预测目标用户的喜好。 2. 基于物协同过滤(Item-Based Collaborative Filtering):该算法通过分析物之间的相似性,将用户对相似的喜好进行推荐。具体步骤包括计算物之间的相似性,选择目标用户已经喜欢的物,根据这些物相似来进行推荐。 3. 基于模型协同过滤(Model-Based Collaborative Filtering):该算法通过构建一个模型,通过该模型来预测用户的喜好。具体步骤包括通过训练数据构建一个模型,然后使用该模型来进行用户喜好的预测和推荐。 4. 混合协同过滤(Hybrid Collaborative Filtering):该算法是将多种推荐算法进行结合使用,以提高推荐的准确性和个性化程度。例如可以将基于用户的协同过滤和基于物协同过滤进行结合,利用它们各自的优势进行推荐。 以上是一些常见的基于内容的协同过滤推荐算法,每种算法都有其适用场景和优缺点,具体应根据实际需求来选择使用。 ### 回答2: Java基于内容的协同过滤推荐算法有以下几种: 1. 基于用户的推荐算法:该算法通过分析用户之间的相似度推荐给用户与其兴趣相似的物。在Java中,可以通过计算用户之间的相关系数、欧氏距离或余弦相似度来度量用户之间的相似度,并基于此进行推荐。 2. 基于物推荐算法:该算法通过分析物之间的相似度推荐给用户与其喜好相似的物。在Java中,可以使用基于余弦相似度或皮尔逊相关系数等方法来计算物之间的相似度,并根据相似度进行推荐。 3. 基于图的推荐算法:该算法建立用户和物之间的关系图,通过分析图的拓扑结构来进行推荐。Java中可以使用图算法库(如JGraphT)来构建和处理关系图,并基于图的特性进行推荐。 4. 基于语义模型推荐算法:该算法通过降维分析来提取和表示用户与物之间的含特征,并基于特征向量来进行推荐。在Java中,可以使用矩阵分解等方法来构建语义模型,并基于模型进行推荐。 总之,Java提供了丰富的数据处理和算法库,可以方便地实现基于内容的协同过滤推荐算法。开发者可以根据具体的需求和数据特点选择和实现适合的推荐算法。 ### 回答3: Java基于内容的协同过滤推荐算法主要有以下几种: 1. 基于用户的协同过滤算法(User-Based Collaborative Filtering):该算法通过分析用户的历史行为数据,找出与目标用户兴趣相似的其他用户,然后将这些用户的兴趣推荐给目标用户。 2. 基于项目的协同过滤算法(Item-Based Collaborative Filtering):该算法通过分析项目的内容和特征,找出与目标项目相似的其他项目,然后将这些项目推荐给用户。该算法更适用于项目数量大、用户数量相对较小的场景。 3. 基于模型协同过滤算法(Model-Based Collaborative Filtering):该算法通过建立概率模型或机器学习模型来预测用户对项目的兴趣,并根据预测结果进行推荐。常用的模型包括朴素贝叶斯模型语义模型矩阵分解模型等。 4. 基于标签的协同过滤算法(Tag-Based Collaborative Filtering):该算法通过分析用户对项目的标签(如电影的类型、音乐的风格等),找出与目标用户兴趣相似的其他用户,然后基于这些用户的兴趣推荐相似的项目给目标用户。 5. 基于社交网络的协同过滤算法(Social Network-Based Collaborative Filtering):该算法通过分析用户在社交网络中的关系和互动,在利用社交网络的信息,如好友关系、用户之间的交互等,进行推荐。该算法可以更好地利用用户之间的社交关系来提高推荐的准确度。 总之,基于内容的协同过滤推荐算法主要包括基于用户、项目、模型、标签和社交网络的算法,可以根据不同的应用场景选择合适的算法来实现个性化推荐
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值