spark als推荐算法笔记
转自: https://www.cnblogs.com/mstk/p/7208674.html ——上面的测试集实际用的训练集
参考: https://blog.csdn.net/delltower/article/details/82219676
参考: http://www.cnblogs.com/mooba/p/6539142.html
参考: https://www.cnblogs.com/followees/p/8854406.html
参考: https://blog.csdn.net/huangyueranbbc/article/details/84401542
参考: https://www.cnblogs.com/charlesblc/p/6243352.html
参考: https://www.zhihu.com/question/31509438
参考: https://blog.csdn.net/ebzxw/article/details/82961316 ——求导公式
参考: https://blog.csdn.net/lipengcn/article/details/52815429——求导公式
参考: https://www.cnblogs.com/zlslch/p/7478395.html ——相对全面
参考: http://www.cnblogs.com/arachis/p/ALS.html ——算法过程的求导前后维度对不上,应该是错了
参考: https://blog.csdn.net/qq_34531825/article/details/52334436 ——实例
参考论文: https://www.researchgate.net/publication/254464370_Alternating_least_squares_for_personalized_ranking
1. Alternating Least Square
ALS(Alternating Least Square),交替最小二乘法。在机器学习中,特指使用最小二乘法的一种协同推荐算法。如下图所示,u表示用户,v表示商品,用户给商品打分,但是并不是每一个用户都会给每一种商品打分。比如用户u6就没有给商品v3打分,需要我们推断出来,这就是机器学习的任务。
由于并不是每个用户给每种商品都打了分,可以假设ALS矩阵是低秩的,即一个m*n的矩阵,是由m*k和k*n两个矩阵相乘得到的,其中k<<m,n。
Am×n=Um×k×Vk×n
这种假设是合理的,因为用户和商品都包含了一些低维度的隐藏特征,比如我们只要知道某个人喜欢碳酸饮料,就可以推断出他喜欢百世可乐、可口可乐、芬达,而不需要明确指出他喜欢这三种饮料。这里的碳酸饮料就相当于一个隐藏特征。上面的公式中,Um×k表示用户对隐藏特征的偏好,Vk×n表示产品包含隐藏特征的程度。机器学习的任务就是求出Um×k和Vk×n。可知uiTvj是用户i对商品j的偏好,使用Frobenius范数来量化重构U和V产生的误差。由于矩阵中很多地方都是空白的,即用户没有对商品打分,对于这种情况我们就不用计算未知元了,只计算观察到的(用户,商品)集合R。
这样就将协同推荐问题转换成了一个优化问题。目标函数中U和V相互耦合,这就需要使用交替二乘算法。即先假设U的初始值U(0),这样就将问题转化成了一个最小二乘问题,可以根据U(0)可以计算出V(0),再根据V(0)计算出U(1),这样迭代下去,直到迭代了一定的次数,或者收敛为止。虽然不能保证收敛的全局最优解,但是影响不大。
2. MLlib的ALS实现
MLlib的ALS采用了数据分区结构,即将U分解成u1,u2,u3,...um,V分解成v1,v2,v3,...vn,相关的u和v存放在同一个分区,从而减少分区间数据交换的成本。比如通过U计算V时,存储u的分区是P1,P2...,存储v的分区是Q1,Q2...,需要将不同的u发送给不同的Q,存放这个关系的块称作OutBlock;在P中,计算v时需要哪些u,存放这个关系的块称作InBlock。
比如R中有a12,a13,a15,u1存放在P1,v2,v3存放在Q2,v5存放在Q3,则需要将P1中的u1发送给Q2和Q3,这个信息存储在OutBlock;R中有a12,a32,因此计算v2需要u1和u3,这个信息存储在InBlock。
直接上代码:
import org.apache.log4j.{ Level, Logger }
import org.apache.spark.{ SparkConf, SparkContext }
import org.apache.spark.mllib.recommendation.ALS
import org.apache.spark.mllib.recommendation.Rating/*** Created by Administrator on 2017/7/19.*/
object ALSTest01 {def main(args:Array[String]) ={// 设置运行环境val conf = new SparkConf().setAppName("ALS 01").setMaster("spark://master:7077").setJars(Seq("E:\\Intellij\\Projects\\MachineLearning\\MachineLearning.jar"))val sc = new SparkContext(conf)Logger.getRootLogger.setLevel(Level.WARN)// 读取样本数据并解析val dataRDD = sc.textFile("hdfs://master:9000/ml/data/test.data")val ratingRDD = dataRDD.map(_.split(',') match {case Array(user, item, rate) =>Rating(user.toInt, item.toInt, rate.toDouble)})// 拆分成训练集和测试集val dataParts = ratingRDD.randomSplit(Array(0.8, 0.2))val trainingRDD = dataParts(0)val testRDD = dataParts(1)// 建立ALS交替最小二乘算法模型并训练val rank = 10val numIterations = 10val alsModel = ALS.train(trainingRDD, rank, numIterations, 0.01)// 预测val user_product = trainingRDD.map {case Rating(user, product, rate) =>(user, product)}val predictions =alsModel.predict(user_product).map {case Rating(user, product, rate) =>((user, product), rate)}val ratesAndPredictions = trainingRDD.map {case Rating(user, product, rate) =>((user, product), rate)}.join(predictions)val MSE = ratesAndPredictions.map {case ((user, product), (r1, r2)) =>val err = (r1 - r2)err * err}.mean()println("Mean Squared Error = " + MSE)println("User" + "\t" + "Products" + "\t" + "Rate" + "\t" + "Prediction")ratesAndPredictions.collect.foreach(rating => {println(rating._1._1 + "\t" + rating._1._2 + "\t" + rating._2._1 + "\t" + rating._2._2)})}}
其中ALS.train()函数的4个参数分别是训练用的数据集,特征数量,迭代次数,和正则因子。
开始瞎编的50行数据运行结果出现严重过拟合,测试集合实际打分和预测分值差很大!
对比SVD和ALS,参考:https://blog.csdn.net/y990041769/article/details/69567838 但这解释我不认可,svd分解为3个矩阵,als是两个。而且和SVD这种矩阵分解不同,ALS所用的矩阵分解技术在分解之前不用把系数矩阵填充成稠密矩阵之后再分解,这不但大大减少了存储空间,而且spark可以利用这种稀疏性用简单的线性代数计算求解。这几点使得本算法在大规模数据上计算非常快,解释了为什么spark mllib目前只有ALS一种推荐算法。
按照最小二乘法,我们直接求出导数为0的点,但是有时候很难解出方程,就考虑使用迭代的方法,首先取一个随机数,然后每一次去想着目标结果逼近,而为了效率最高,我们向着梯度下降最快的方向,既θ在偏导数上的取值。而α是学习速率,是个很重要的参数,设置过大会导致超过最小值,过小则学习的太慢。
注释:
有的地方叫基于最小二乘法的协同过滤,也有的叫混合协同过滤,属于隐语义模型的一种。我认为这是FM矩阵分解只有用户、商品id时候的特殊形式。这里不妨叫rankALS更贴切些(参考论文 https://www.researchgate.net/publication/254464370_Alternating_least_squares_for_personalized_ranking ),毕竟als这个名字本身更多的时候代表最优化的计算方法——最小二乘法而已。
这里易混淆的有MF、FM、SVD、rankALS(也有人叫MF),它们都是矩阵分解,但公式不同,其中FM一般在TensorFlow之类的机器学习包里实现的多,SVD则参考R的recommendlib包实现,rankALS则在spark ML库中有现成的包调用实现(spark官网叫Alternating Least Squares (ALS) matrix factorization)。
spark als推荐算法笔记相关推荐
- 基于聚类的推荐算法笔记——以豆瓣电影为例(二)(附源代码)
基于聚类的推荐算法笔记--以豆瓣电影为例(二)(附源代码) 第一章 聚类算法介绍 基于聚类的推荐算法笔记一 第二章 数据介绍 基于聚类的推荐算法笔记二 第三章 实现推荐算法 基于聚类的推荐算法笔记三 ...
- 基于聚类的推荐算法笔记——以豆瓣电影为例(三)(附源代码)
基于聚类的推荐算法笔记--以豆瓣电影为例(三)(附源代码) 第一章 聚类算法介绍 基于聚类的推荐算法笔记一 第二章 数据介绍 基于聚类的推荐算法笔记二 第三章 实现推荐算法 基于聚类的推荐算法笔记三 ...
- 【推荐系统系列6】ALS推荐算法原理
ALS算法原理 ALS算法是2008年以来,用的比较多的协同过滤算法.它已经集成到Spark的Mllib库中,使用起来比较方便. 从协同过滤的分类来说,ALS算法属于User-Item CF,也叫做混 ...
- 开源精选 - Spark个性化推荐算法
源码:https://github.com/wolf-song-ml/RecommendationSystem 实战篇 1 项目技术架构 2 项目涉及关键技术 Redis:存储用户最近评测队列 Mon ...
- 大数据Spark MLlib推荐算法
目录 1 相似度算法 1.1 欧几里德距离算法 1.2 基于夹角余弦相似度算法 2 最近邻域 3 交替最小二乘法 3.1 最小二乘法 3.2 交替最小二乘法 3.3 ALS算法流程 3.4 ALS算法 ...
- 基于Spark实现推荐算法-1:推荐算法简介
个性化推荐系统简介 个性化推荐系统的定义在 1997 年由 Resnick 和 Varian 提出:利用互联网向用户提供信 息和建议,帮助用户选择产品,或模拟售货员帮助用户完成购买行为的系统 .通常推 ...
- spark mllib推荐算法使用
2019独角兽企业重金招聘Python工程师标准>>> 一.pom.xml <!-- 机器学习包 --><dependency><groupId> ...
- 想要成为推荐算法工程师,都要准备哪些东西
作者在<推荐算法工程师的成长之道>这篇文章中讲到推荐算法工程师是一个好的职业选择,并且讲解了职业发展路径及定位.怎么成长等话题(还没看的可以看起来). 如果大家认可我讲的并且也愿意将来从事 ...
- 推荐算法工程师学习路线及工作指南
干货!推荐算法工程师学习路线及工作指南 以下文章来源于大数据与人工智能 ,作者gongyouliu 本文从我自己的学习成长经历.如何判断自己是否适合从事推荐算法.推荐算法工程师需要的知识储备.怎么找一 ...
最新文章
- linux下的lamp环境的搭建!!!
- [安卓] 12、开源一个基于SurfaceView的飞行射击类小游戏
- Drupal的高速缓存配置APC
- C#之windows桌面软件第十课:电脑ADC值显示(上位机)(单通道显示)
- selenium处理iframe定位于切换问题解决办法
- 干货 | 公众号历史文章精选(附资源)
- Linux中的 硬链接ln和软连接ln -s
- java远程插件动态注册机制_Spring运行时动态注册bean的方法
- Windows下搭建HTK
- 用EZBOOT制作多个gho文件的安装盘
- 跟着开源项目学因果推断——mr_uplift(十五)
- php中include,require的文件包含问题,以及$_SERVER['PHP_SELF']和__FILE__的区别
- 获取ul下li标签里点击的是哪一个li并获取li里a标签的值
- linux调度器(九)——调度器的配置参数
- 3992. 树上有猴-AcWing题库
- 计算机员工工资管理系统源代码,C员工工资管理系统源代码.doc
- My BlackBerry
- React:栈调和(Reconciliation)
- 经典单片机c语言教程 pdf下载,51单片机经典教程.pdf
- 老生常谈:frame和Bounds的区别