协同过滤算法 R/mapreduce/spark mllib多语言实现

用户电影评分数据集下载

http://grouplens.org/datasets/movielens/

1) Item-Based,非个性化的,每个人看到的都一样

2) User-Based,个性化的,每个人看到的不一样

对用户的行为分析得到用户的喜好后,可以根据用户的喜好计算相似用户和物品,然后可以基于相似用户或物品进行推荐。这就是协同过滤中的两个分支了,基于用户的和基于物品的协同过滤。

在计算用户之间的相似度时,是将一个用户对所有物品的偏好作为一个向量,而在计算物品之间的相似度时,是将所有用户对某个物品的偏好作为一个向量。求出相似度后,接下来可以求相似邻居了。

3)基于模型(ModelCF)

按照模型,可以分为:

1)最近邻模型:基于距离的协同过滤算法

       2)Latent Factor Mode(SVD):基于矩阵分解的模型

       3)Graph:图模型,社会网络图模型

适用场景

对于一个在线网站,用户的数量往往超过物品的数量,同时物品数据相对稳定,因此计算物品的相似度不但

计算量小,同时不必频繁更新。但是这种情况只适用于电子商务类型的网站,像新闻类,博客等这类网站的

系统推荐,情况往往是相反的,物品数量是海量的,而且频繁更新。

r语言实现基于物品的协同过滤算法

  #引用plyr包
    library(plyr)
    #读取数据集
    train<-read.table(file="C:/users/Administrator/Desktop/u.data",sep=" ")
    train<-train[1:3]
    
    names(train)<-c("user","item","pref")
    
    #计算用户列表方法
    usersUnique<-function(){
      users<-unique(train$user)
      users[order(users)]
    }
    
    
    #计算商品列表方法
    itemsUnique<-function(){
      items<-unique(train$item)
      items[order(items)]
    }
    
    # 用户列表
    users<-usersUnique()
    # 商品列表
    items<-itemsUnique() 
    #建立商品列表索引
    index<-function(x) which(items %in% x)
    data<-ddply(train,.(user,item,pref),summarize,idx=index(item)) 
    
    #同现矩阵
    cooccurrence<-function(data){
      n<-length(items)
      co<-matrix(rep(0,n*n),nrow=n)
      for(u in users){
    idx<-index(data$item[which(data$user==u)])
    m<-merge(idx,idx)
    for(i in 1:nrow(m)){
      co[m$x[i],m$y[i]]=co[m$x[i],m$y[i]]+1
    }
      }
      return(co)
    }
    
    #推荐算法
    recommend<-function(udata=udata,co=coMatrix,num=0){
      n<-length(items)
      
      # all of pref
      pref<-rep(0,n)
      pref[udata$idx]<-udata$pref
      
      # 用户评分矩阵
      userx<-matrix(pref,nrow=n)
      
      # 同现矩阵*评分矩阵
      r<-co %*% userx
      
      # 推荐结果排序 
      # 把该用户评分过的商品的推荐值设为0
      r[udata$idx]<-0
      idx<-order(r,decreasing=TRUE)
      topn<-data.frame(user=rep(udata$user[1],length(idx)),item=items[idx],val=r[idx])
      topn<-topn[which(topn$val>0),]
      
      # 推荐结果取前num个
      if(num>0){
    topn<-head(topn,num)
      }
      
      #返回结果
      return(topn)
    }
    
    #生成同现矩阵
    co<-cooccurrence(data) 
    #计算推荐结果
    recommendation<-data.frame()
    for(i in 1:length(users)){
      udata<-data[which(data$user==users[i]),]
      recommendation<-rbind(recommendation,recommend(udata,co,0)) 
    }

mareduce 实现

参考文章:

http://www.cnblogs.com/anny-1980/articles/3519555.html

代码下载

https://github.com/bsspirit/maven_hadoop_template/releases/tag/recommend

spark ALS实现

Spark mllib里用的是矩阵分解的协同过滤,不是UserBase也不是ItemBase。

参考文章:

http://www.mamicode.com/info-detail-865258.html


import org.apache.spark.SparkConf
import org.apache.spark.mllib.recommendation.{ALS, MatrixFactorizationModel, Rating}
import org.apache.spark.rdd._
import org.apache.spark.SparkContext
import scala.io.Source

object MovieLensALS {

  def main(args:Array[String]) {

    //设置运行环境

    val sparkConf = new SparkConf().setAppName("MovieLensALS").setMaster("local[5]")

    val sc = new SparkContext(sparkConf)

    //装载用户评分,该评分由评分器生成(即生成文件personalRatings.txt)

    val myRatings = loadRatings(args(1))

    val myRatingsRDD = sc.parallelize(myRatings, 1)

    //样本数据目录

    val movielensHomeDir = args(0)

    //装载样本评分数据,其中最后一列Timestamp取除10的余数作为key,Rating为值,即(Int,Rating)

    val ratings = sc.textFile(movielensHomeDir + "/ratings.dat").map {

      line =>

        val fields = line.split("::")

        // format: (timestamp % 10, Rating(userId, movieId, rating))

        (fields(3).toLong % 10, Rating(fields(0).toInt, fields(1).toInt, fields(2).toDouble))

    }

    //装载电影目录对照表(电影ID->电影标题)

    val movies = sc.textFile(movielensHomeDir + "/movies.dat").map {

      line =>

        val fields = line.split("::")

        // format: (movieId, movieName)

        (fields(0).toInt, fields(1))

    }.collect().toMap

    //统计有用户数量和电影数量以及用户对电影的评分数目

    val numRatings = ratings.count()

    val numUsers = ratings.map(_._2.user).distinct().count()

    val numMovies = ratings.map(_._2.product).distinct().count()

    println("Got " + numRatings + " ratings from " + numUsers + " users " + numMovies + " movies")

    //将样本评分表以key值切分成3个部分,分别用于训练 (60%,并加入用户评分), 校验 (20%), and 测试 (20%)

    //该数据在计算过程中要多次应用到,所以cache到内存

    val numPartitions = 4

    val training = ratings.filter(x => x._1 < 6).values.union(myRatingsRDD).repartition(numPartitions).persist()

    val validation = ratings.filter(x => x._1 >= 6 && x._1 < 8).values.repartition(numPartitions).persist()

    val test = ratings.filter(x => x._1 >= 8).values.persist()

    val numTraining = training.count()

    val numValidation = validation.count()

    val numTest = test.count()

    println("Training: " + numTraining + " validation: " + numValidation + " test: " + numTest)

    //训练不同参数下的模型,并在校验集中验证,获取最佳参数下的模型

    val ranks = List(8, 12)

    val lambdas = List(0.1, 10.0)

    val numIters = List(10, 20)

    var bestModel: Option[MatrixFactorizationModel] = None

    var bestValidationRmse = Double.MaxValue

    var bestRank = 0

    var bestLambda = -1.0

    var bestNumIter = -1

    for (rank <- ranks; lambda <- lambdas; numIter <- numIters) {

      val model = ALS.train(training, rank, numIter, lambda)

      val validationRmse = computeRmse(model, validation, numValidation)

      println("RMSE(validation) = " + validationRmse + " for the model trained with rank = "

        + rank + ",lambda = " + lambda + ",and numIter = " + numIter + ".")

      if (validationRmse < bestValidationRmse) {

        bestModel = Some(model)

        bestValidationRmse = validationRmse

        bestRank = rank

        bestLambda = lambda

        bestNumIter = numIter

      }

    }

    //用最佳模型预测测试集的评分,并计算和实际评分之间的均方根误差(RMSE)

    val testRmse = computeRmse(bestModel.get, test, numTest)

    println("The best model was trained with rank = " + bestRank + " and lambda = " + bestLambda

      + ", and numIter = " + bestNumIter + ", and its RMSE on the test set is " + testRmse + ".")

    //create a naive baseline and compare it with the best model

    val meanRating = training.union(validation).map(_.rating).mean()

    val baselineRmse = math.sqrt(test.map(x => (meanRating - x.rating) * (meanRating - x.rating)).reduce(_ + _) / numTest)

    val improvement = (baselineRmse - testRmse) / baselineRmse * 100

    println("The best model improves the baseline by " + "%1.2f".format(improvement) + "%.")

    //推荐前十部最感兴趣的电影,注意要剔除用户已经评分的电影

    val myRatedMovieIds = myRatings.map(_.product).toSet

    val candidates = sc.parallelize(movies.keys.filter(!myRatedMovieIds.contains(_)).toSeq)

    val recommendations = bestModel.get

      .predict(candidates.map((0, _)))

      .collect()

      .sortBy(-_.rating)

      .take(10)

    var i = 1

    println("Movies recommended for you:")

    recommendations.foreach { r =>

      println("%2d".format(i) + ": " + movies(r.product))

      i += 1

    }

    sc.stop()

  }

  /** 校验集预测数据和实际数据之间的均方根误差 **/

  def computeRmse(model:MatrixFactorizationModel,data:RDD[Rating],n:Long):Double = {

    val predictions:RDD[Rating] = model.predict(data.map(x => (x.user,x.product)))

    val predictionsAndRatings = predictions.map{ x =>((x.user,x.product),x.rating)}

      .join(data.map(x => ((x.user,x.product),x.rating))).values

    math.sqrt(predictionsAndRatings.map( x => (x._1 - x._2) * (x._1 - x._2)).reduce(_+_)/n)

  }

  /** 装载用户评分文件 personalRatings.txt **/

  def loadRatings(path:String):Seq[Rating] = {

    val lines = Source.fromFile(path).getLines()

    val ratings = lines.map{

      line =>

        val fields = line.split("::")

        Rating(fields(0).toInt,fields(1).toInt,fields(2).toDouble)

    }.filter(_.rating > 0.0)

    if(ratings.isEmpty){

      sys.error("No ratings provided.")

    }else{

      ratings.toSeq

    }

  }

}

参考文章:

http://blog.csdn.net/acdreamers/article/details/44672305

http://www.cnblogs.com/technology/p/4467895.html

http://blog.fens.me/rhadoop-mapreduce-rmr/

时间: 2024-08-05 11:53:37

协同过滤算法 R/mapreduce/spark mllib多语言实现的相关文章

基于Spark MLlib平台的协同过滤算法---电影推荐系统

基于Spark MLlib平台的协同过滤算法---电影推荐系统 又好一阵子没有写文章了,阿弥陀佛...最近项目中要做理财推荐,所以,回过头来回顾一下协同过滤算法在推荐系统中的应用. 说到推荐系统,大家可能立马会想到协同过滤算法.本文基于Spark MLlib平台实现一个向用户推荐电影的简单应用.其中,主要包括三部分内容: 协同过滤算法概述 基于模型的协同过滤应用---电影推荐 实时推荐架构分析     一.协同过滤算法概述 本人对算法的研究,目前还不是很深入,这里简单的介绍下其工作原理. 通常,

Spark机器学习(11):协同过滤算法

协同过滤(Collaborative Filtering,CF)算法是一种常用的推荐算法,它的思想就是找出相似的用户或产品,向用户推荐相似的物品,或者把物品推荐给相似的用户.怎样评价用户对商品的偏好?可以有很多方法,如用户对商品的打分.购买.页面停留时间.保存.转发等等.得到了用户对商品的偏好,就可以给用户推荐商品.有两种方法:用户A喜欢物品1,商品2和物品1很相似,于是把物品2推荐给用户A:或者用户A和用户B很类似,B喜欢商品2,就将商品2推荐给用户A.所以协同过滤分为两类:基于用户的协同过滤

spark基于用户的协同过滤算法与坑点,提交job

承接上文: http://blog.csdn.net/wangqi880/article/details/52875524 对了,每台机子的防火墙要关闭哈,不然spark集群启动不起来 前一次,已经把spark的分布式集群布置好了,今天写一个简单的案例来运行.会写一些关于spark的推荐的东西,这里主要有4点,1基于用户协同过滤,2基于物品协同过滤,3基于模型的协同过滤,4基于关联规则的推荐(fp_growth),只写核心代码啊. 基于spark用户协同过滤算法的实现 1用户协同过滤算法 1.1

协同过滤算法(天池竞赛试题)

一:推荐算法分类: 1.按数据使用划分: 协同过滤算法:UserCF, ItemCF, ModelCF 基于内容的推荐: 用户内容属性和物品内容属性 社会化过滤:基于用户的社会网络关系 2.案例:天池大数据竞赛 我们会开放如下数据类型: 字 段 字段说明 提取说明 user_id 用户标记 抽样&字段加密 Time 行为时间 精度到天级别&隐藏年份 action_type 用户对品牌的行为类型 包括点击.购买.加入购物车.收藏4种行为 (点击:0 购买:1 收藏:2 购物车:3) bran

Collaborative Filtering(协同过滤)算法详解

基本思想 基于用户的协同过滤算法是通过用户的历史行为数据发现用户对商品或内容的喜欢(如商品购买,收藏,内容评论或分享),并对这些喜好进行度量和打分.根据不同用户对相同商品或内容的态度和偏好程度计算用户之间的关系.在有相同喜好的用户间进行商品推荐.简单的说就是如果A,B两个用户都购买了x.y.z三本图书,并且给出了5星的好评.那么A和B就属于同一类用户.可以将A看过的图书w也推荐给用户B. 基于用户协同过滤算法的原理图 所以,协同过滤算法主要分为两个步骤: 1.寻找相似的用户集合: 2.寻找集合中

基于用户的协同过滤算法(UserCF)

基于用户的协同过滤算法: 找到和目标用户相似的用户集合 找到这个集合中用户喜欢的但目标用户没有听过的物品 #encoding: utf-8 from Similarity import Person from Sort import select_sort file=open('user_bookmark','r') filew=open('user_bookRecommend','w') #加载训练集 trainSet={} while True: line=file.readline().s

探秘推荐引擎之协同过滤算法小综述

数学大神.统计学大神和数据挖掘推荐大神请关注. 一.数学期望的理解 早些时候,法国有两个大数学家,一个叫做布莱士·帕斯卡,一个叫做费马.帕斯卡认识两个赌徒,这两个赌徒向他提出了一个问题.他们说,他俩下赌金之后,约定谁先赢满5局,谁就获得全部赌金.赌了半天,A赢了4局,B赢了3局,时间很晚了,他们都不想再赌下去了.那么,这个钱应该怎么分?是不是把钱分成7份,赢了4局的就拿4份,赢了3局的就拿3份呢?或者,因为最早说的是满5局,而谁也没达到,所以就一人分一半呢?这两种分法都不对.正确的答案是:赢了4

《推荐系统》基于用户和Item的协同过滤算法的分析与实现(Python)

1:协同过滤算法简介 2:协同过滤算法的核心 3:协同过滤算法的应用方式 4:基于用户的协同过滤算法实现 5:基于物品的协同过滤算法实现 一:协同过滤算法简介 关于协同过滤的一个最经典的例子就是看电影,有时候不知道哪一部电影是我们喜欢的或者评分比较高的,那么通常的做法就是问问周围的朋友,看看最近有什么好的电影推荐.在问的时候,都习惯于问跟自己口味差不 多的朋友,这就是协同过滤的核心思想. 协同过滤是在海量数据中挖掘出小部分与你品味类似的用户,在协同过滤中,这些用户成为邻居,然后根据他们喜欢的东西

基于物品的协同过滤算法ItemCF算法实现

基于物品的协同过滤算法(ItemCF)的基本思想是:给用户推荐那些和他们之前喜欢的物品相似的物品. 比如,该算法会因为你购买过<Java从入门到精通>而给你推荐<Java并发编程实战>.不过,基于物品的协同过滤算法并不利用物品的内容属性计算物品之间的相似度,二是通过分析用户的行为数据计算物品之间的相似度.该算法认为,物品A和物品B具有很大的相似度是因为喜欢物品A的用户大都也喜欢物品B. 实现代码: # -*- coding=utf-8 -*- from operator impor