协同过滤之ALS

搜索推荐,主要有以下几种形式:一、根据人口统计学推荐:此推荐方式需要建立用户模型,并且需要获取用户的具体信息,然后根据矩阵运算,计算相似度,此方式最大缺陷是获取用户的隐私,应用不多;

               二、基于内容的推荐:根据特定用户的历史数据,推荐出相似的产品。缺点是需要建立item model,比较费时。

               三、基于协同过滤,是目前搜索推荐中应用最广泛的,不需要建立item model,省事,效果比较好。协同过滤的本质,可以概括为"物以类聚,人以群分",分别指基于物品的协同过滤和基于user的协同过滤。还有基于机器学习的协同过滤,总共这三种形式。第一种的优点是没有冷启动问题,基于用户历史行为的推荐,有冷启动问题。

亚马逊是搜索推荐的鼻祖,把搜索推荐运用到了极致,主要有以下形式:一,基于内容的推荐,主要有:①每日新产品的推荐;②基于用户历史数据的推荐(比如猜你喜欢);二,基于协同过滤的推荐:①根据KNN算法,计算相似用户,推荐其他用户群喜欢的产品(去重)②根据FP-Growth model进行相关度挖掘,捆绑销售③基于ALS算法,推荐产品。关于ALS算法,有一篇经典的博文,是spark MLlib的源码贡献者之一写的,很深入。地址:http://www.csdn.net/article/2015-05-07/2824641 认真研究几遍,会有很多收获。本文主要讲ALS应用,所以会比较简单,但是,想成为这个领域的佼佼者,一定要深入研究理论,寻求突破和创新,切不可一辈子做一个低级的码奴。废话不说了,上代码:

package com.txq.spark.test

import java.io.Fileimport org.apache.log4j.{Level, Logger}import org.apache.spark.mllib.recommendation.{ALS, MatrixFactorizationModel, Rating}import org.apache.spark.rdd.RDDimport org.apache.spark.{SparkConf, SparkContext}import scala.io.Source

/**  * ALS矩阵分解搜索推荐:  * 两个数据源:①rating.dat ----->userid  itemid  rate  *            ②items.dat----itemid->item(Map)  * 思路:1.实现数据的partitions,数据格式为(key,value)形式,key为时间戳,对10求余数,根据余数分区,提高计算的  * 并行度;  * 2.取上述数据的values部分,训练出一个最优的model出来,评判标准为MSE;  * 3.根据最优model对特定用户推荐产品,注意去除该用户已经评分的产品.  */object MovieLensALS {  System.setProperty("hadoop.home.dir", "D://hadoop-2.6.2")  val userId = 0//被推荐用户的id号  def main(args: Array[String]): Unit = {    //屏蔽不必要的日志显示在终端上    Logger.getLogger("org.apache.spark").setLevel(Level.WARN)    Logger.getLogger("org.eclipse.jetty.server").setLevel(Level.OFF)

if(args.length != 2){      println("Usage:/path/to/spark/bin/spark-submit --driver-memory 2g --class " +        "week6.MovieLensALS" + "target/scala-*/movielens-als-ssembly-*.jar movieLensHomeDir personalRatingsFile")      sys.exit(1)    }    //设置运行环境    val conf = new SparkConf().setAppName("MovieLensALS")    val sc = new SparkContext(conf)

//装载用户评分,该评分由评分器生成    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(new File(movieLensHomeDir,"ratings.dat").toString).map{ line =>      val fields = line.split("::")      (fields(3).toLong % 10,Rating(fields(0).toInt,fields(1).toInt,fields(2).toDouble))    }    //装载电影目录对照表(电影ID->电影标题)    val movies = sc.textFile(new File(movieLensHomeDir,"movies.dat").toString).map{line =>      val fields = line.split("::")      (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 on" + numMovies + " movies.")    //将样本评分表以key值切分成3个部分,分别用于训练(60%,并加入用户评分),校验(20%),测试(20%)    //该数据在计算过程中要多次应用到,所以cache到内存    val numPartitions = 4    val training = ratings.filter(x => x._1 < 6).values.union(myRatingsRDD).repartition(numPartitions).cache()    val test = ratings.filter(x => x._1 >= 8).values.repartition(numPartitions).cache()    val validation = ratings.filter(x => x._1>= 6 && x._1 < 8).values.repartition(numPartitions).cache()

val numTraining = training.count()    val numValidation = validation.count()    val numTest = test.count()

println("Training: "+ numTraining + ",validation: " + numValidation + ",test: " + numTest)    //训练不同参数下的模型,并在校验集中校验,获取最佳参数下的模型    val ranks = List(8,9)    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)      println("RMSE(validation) = " + validationRmse + " for the model trained with rank = " + rank + " with lambda = " + lambda + " with numIterations = " + numIter)      if(validationRmse < bestValidationRmse){        bestModel = Some(model)        bestValidationRmse = validationRmse        bestRank = rank        bestLambda = lambda        bestNumIter = numIter      }    }    //用最佳模型预测测试集的评分,并计算和实际评分之间的均方根误差    val testRmse = computeRmse(bestModel.get,test)    println("The best model was trained with rank = " + bestRank + " with lambda = " + bestLambda + " with best NumIterations = " + bestNumIter)    //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 => math.pow(meanRating - x.rating,2)).mean())    val improvement =(testRmse-baselineRmse) / baselineRmse * 100    println("The best model improves the base line 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((userId,_))).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 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    }  }  /** 计算**/  def computeRmse(model:MatrixFactorizationModel,data:RDD[Rating]):Double = {    val precisions:RDD[Rating] = model.predict(data.map(x => (x.user,x.product)))    val precisionsAndReal = precisions.map(x => ((x.user,x.product),x.rating)).join(data.map(line =>((line.user,line.product    ),line.rating))).values    math.sqrt(precisionsAndReal.map(x => math.pow(x._1 - x._2,2)).mean())  }}佟氏出品,必属精品。坚持算法和数据挖掘领域的研究,不断改进代码的质量,跻身一流程序员行列!
时间: 2024-10-13 14:32:04

协同过滤之ALS的相关文章

机器学习(十三)——机器学习中的矩阵方法(3)病态矩阵、协同过滤的ALS算法(1)

http://antkillerfarm.github.io/ 向量的范数(续) 范数可用符号∥x∥λ表示.常用的有: ∥x∥1=|x1|+?+|xn| ∥x∥2=x21+?+x2n???????????√ ∥x∥∞=max(|x1|,-,|xn|) 这里不做解释的给出如下示意图: 其中,0范数表示向量中非0元素的个数.上图中的图形被称为lp ball.表征在同一范数条件下,具有相同距离的点的集合. 范数满足如下不等式: ∥A+B∥≤∥A∥+∥B∥(三角不等式) 向量范数推广可得到矩阵范数.某些

共轭梯度法求解协同过滤中的 ALS

协同过滤是一类基于用户行为数据的推荐方法,主要是利用已有用户群体过去的行为或意见来预测当前用户的偏好,进而为其产生推荐.能用于协同过滤的算法很多,大致可分为:基于最近邻推荐和基于模型的推荐.其中基于最近邻推荐主要是通过计算用户或物品之间的相似度来进行推荐,而基于模型的推荐则通常要用到一些机器学习算法.矩阵分解可能是被研究地最多的基于模型的推荐算法,在著名的 Netflix 大赛中也是大放异彩,核心思想是利用低维隐向量为每个用户和物品建模,进而推测用户对物品的偏好.现在的关键问题是如果要用矩阵分解

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

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

Spark(十一) -- Mllib API编程 线性回归、KMeans、协同过滤演示

本文测试的Spark版本是1.3.1 在使用Spark的机器学习算法库之前,需要先了解Mllib中几个基础的概念和专门用于机器学习的数据类型 特征向量Vector: Vector的概念是和数学中的向量是一样的,通俗的看其实就是一个装着Double数据的数组 Vector分为两种,分别是密集型和稀疏型 创建方式如下: val array:Array[Double] = ... val vector = Vector.dense(array)//创建密集向量 val vector = Vector.

基于MLlib的机器学习--协同过滤与推荐

<Spark快速大数据分析> 11.5.4 协同过滤与推荐 协同过滤是一种根据用户对各种产品的交互与评分来推荐新产品的推荐系统技术. 协同过滤引入的地方就在于它只需要输入一系列用户/产品的交互记录: 无论是显式的交互(例如在购物网站上进行评分)还是隐式的(例如用户访问了一个 产品的页面但是没有对产品评分)交互皆可.仅仅根据这些交互,协同过滤算法就能 够知道哪些产品之间比较相似(因为相同的用户与它们发生了交互)以及哪些用户之间 比较相似,然后就可以做出新的推荐. 尽管MLlib的API使用了用户

隐性反馈行为数据的协同过滤推荐算法

<Collaborative Filtering for Implicit Feedback Datasets>论文笔记 本文是我阅读<CollaborativeFiltering for Implicit Feedback Datasets>论文的笔记,介绍的是对于隐性反馈行为数据协同过滤算法,采取的是隐语义模型(LFM),求解方式是ALS. 显性反馈行为包括用户明确表示对物品喜好的行为 隐性反馈行为指的是那些不能明确反应用户喜好 的行为.最具代表性的隐性反馈行为就是页面浏览行为

机器学习之协同过滤

机器学习之协同过滤 [睡着的水-hzjs-2016.08.18][求点赞] 一.协同过滤的基本概念 协同过滤是推荐引擎的一种算法,经常用到的地方像亚马逊.京东.淘宝.今日头条等隐形推荐场景.这些计算旨在补充用户-商品关联矩阵中所缺失的部分.像下面的推荐引擎就是我们的推荐系统: #MLlib 当前支持基于模型的协同过滤,其中用户和商品通过一小组隐性因子进行表达,并且这些因子也用于预测缺失的元素,MLlib 使用最小二乘法(ALS)来学习这些隐性因子. 在Mllib中实现的有如下参数: ---num

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

用户电影评分数据集下载 http://grouplens.org/datasets/movielens/ 1) Item-Based,非个性化的,每个人看到的都一样 2) User-Based,个性化的,每个人看到的不一样 对用户的行为分析得到用户的喜好后,可以根据用户的喜好计算相似用户和物品,然后可以基于相似用户或物品进行推荐.这就是协同过滤中的两个分支了,基于用户的和基于物品的协同过滤. 在计算用户之间的相似度时,是将一个用户对所有物品的偏好作为一个向量,而在计算物品之间的相似度时,是将所有

Apache mahout 源码阅读笔记--协同过滤, PearsonCorrelationSimilarity

协同过滤源码路径: ~/project/javaproject/mahout-0.9/core/src $tree main/java/org/apache/mahout/cf/taste/ -L 2 main/java/org/apache/mahout/cf/taste/ ├── common │   ├── NoSuchItemException.java │   ├── NoSuchUserException.java │   ├── Refreshable.java │   ├── T