程序员的自我修养
Home » Apache Spark, 机器学习 » Spark MLlib之协同过滤

Spark MLlib之协同过滤

23条评论19,196次浏览

什么是协同过滤

协同过滤(Collaborative Filtering, 简称CF),wiki上的定义是:简单来说是利用某兴趣相投、拥有共同经验之群体的喜好来推荐使用者感兴趣的资讯,个人透过合作的机制给予资讯相当程度的回应(如评分)并记录下来以达到过滤的目的进而帮助别人筛选资讯,回应不一定局限于特别感兴趣的,特别不感兴趣资讯的纪录也相当重要。

以上定义太拗口,举个简单的例子:我现在多年不看日本anime的新番了,最近突然又想看几部新番,但又不知道这么多新番中看哪些比较好,于是我就找几个同样喜欢日本动漫的朋友来咨询。我第一个想咨询的朋友是和我口味最像的,我们都特别喜欢看《虫师》、《黑之契约者》、《寒蝉》这样的小众动画;我问的第二个朋友和我口味差不多,他特别喜欢看《钢炼》《无头骑士异闻录》这样的动画,我虽然喜欢,但不像他那么喜欢;由于身边喜欢日本动画的朋友不多,剩下第三个可以咨询的是一个宅女,平常经常看腐、宅、基的动漫,完全跟我不是一路人,于是问了下她推荐的片子,并将这些片子打上的黑名单的标签。然后我就开始看第一个朋友推荐的片子了,要是时间特别多又很无聊我可能会看第二个朋友推荐的,但打死我也不会看第三个朋友推荐的。这就是协同过滤的一个简化、小众版。

如何进行相似度度量

接着上面的例子,我可以通过我和其它朋友共同喜欢某个或某类动漫来确定我们的口味是否一样,那么如何以数学或者机器的形式来表示这个“口味一样”呢?通常,是通过“距离”来表示,例如:欧几里得距离、皮尔逊相关度、曼哈顿距离、Jaccard系数等等。

欧几里得距离

欧几里德距离(Euclidean Distance),最初用于计算欧几里得空间中两个点的距离,在二维空间中,就是我们熟悉的两点间的距离,x、y表示两点,维度为n:

\(d(x,y)=\sqrt {(\sum_i^n (x_i-y_i)^2)}\)

相似度:

\(sim(x,y)={1\over {1+d(x,y)}}\)

皮尔逊相关度

皮尔逊相关度(Pearson Correlation Coefficient),用于判断两组数据与某一直线拟合程度的一种度量,取值在[-1,1]之间。当数据不是很规范的时候(如偏差较大),皮尔逊相关度会给出较好的结果。

\(p(x,y)={{\sum {x_iy_i}-n\overline{xy}}\over {(n-1)S_xS_y}}={{n\sum {x_iy_i}-\sum x_i\sum y_i}\over{\sqrt{n\sum{x_i^2}-(\sum x_i)^2}{\sqrt{n\sum{y_i^2}-(\sum y_i)^2}}}}\)

曼哈顿距离

曼哈顿距离(Manhattan distance),就是在欧几里得空间的固定直角坐标系上两点所形成的线段对轴产生的投影的距离总和。

\(d(x,y)={\sum{\|x_i-y_i\|}}\)

Jaccard系数

Jaccard系数,也称为Tanimoto系数,是Cosine相似度的扩展,也多用于计算文档数据的相似度。通常应用于x为布尔向量,即各分量只取0或1的时候。此时,表示的是x,y的公共特征的占x,y所占有的特征的比例:

\(T(x,y)={x\bullet y\over{\|x\|^2}+\|y\|^2-x\bullet y}={\sum{x_iy_i}\over{\sqrt{\sum{x_i^2}}}+\sqrt{\sum{y_i^2}}-\sum{x_iy_i}}\)

计算推荐

根据上述“距离”的算法,我们可以找出与自己“口味一样”的人了,但这并不是目的,目的是找出推荐的物品。一种常用的做法是选出与你兴趣相同的N个人,然后根据这N个人的记录来进行加权推荐。具体如下,假设已经计算出欧几里得相似度:

朋友 相似度 银魂 S.x银魂 食灵零 S.x食灵零 雨月 S.x雨月
A 0.95 10.0 9.5 9.0 8.55 - -
B 0.80 8.5 6.8 7.5 6 5.0 4
C 0.25 - - 6.5 1.625 9.0 2.25
总计 16.3 16.175 6.25
Sim.Sum 1.75 2 1.05
总计/Sim.Sum 9.31 8.09 5.95

其中,S.x开头的表示相似度与评分的乘积,Sim.Sum表示打过分的朋友的相似度之和。可以看出根据三位友人的推荐,我从这三部动漫中应该选择银魂来看。

Item CF与User CF

基于用户的协同过滤(User CF),其基本思想相当简单,基于用户对物品的偏好找到相邻邻居用户,然后将邻居用户喜欢的推荐给当前用户。上述过程就属于User CF。

基于物品的CF(Item CF)的原理和基于用户的CF类似,只是在计算邻居时采用物品本身,而不是从用户的角度,即基于用户对物品的偏好找到相似的物品,然后根据用户的历史偏好,推荐相似的物品给他。

两者的计算复杂度和适用场景皆不同,详细可参见参考资料。

Spark协同过滤实现

训练数据

其中第一列为userid,第二列为movieid,第三列为评分,第四列为timestamp(未使用)。

完整版下载:MovieLens(解压后的u.data文件)。

代码实现

运行结果

参考资料

(转载本站文章请注明作者和出处 程序员的自我修养 – SelfUp.cn ,请勿用于任何商业用途)
23条评论
  1. 张三说道:

    你好,有学习价值,但是代码不全哦,如rating -> new T...、以及(line -> {....等

  2. 张三说道:

    你好,推荐列表如何出了?

    • yurnom说道:

      有环境的话跑一下,结果一目了然的

      • Alexandra说道:

        “This is effectively confiscating part of their wealth in order to advance someone else’s idea of better tao1l.&#822t;sney this isn’t true. when the land was upzoned around the denny triangle, lot values tripled. upzoning doesn’t make land less valuable, it does the opposite, generally. unless it’s done in places that don’t make sense.

  3. 张三说道:

    你好,小弟初学spark,有不少问题,能否加你QQ,有问题可以请教请教,邮箱:meiboqi@126.com

  4. 张三说道:

    或者可否把您的这些示例的源码发我一份,供学习学习~

    • yurnom说道:

      上面贴的就是全部源码了。。数据下载链接也有。。我的idea连不上github,所以暂时无法共享出来。。抱歉。等过几天能连上时候我传上去给你

      • Maggie说道:

        Hiya MariaThank you so VERY much for all that you have done for PASIC especially over the last few months, you have been phenomenal!So many more people know about PASIC now and I am sure that will mean that we get more support than ever.If you count up all that you have raised for PASIC since you’ve known about us I am pretty sure that it would exceed £23,000 and that’s a huge achievement in an;eon&#8217ys books.Perhaps you can slow down a little now and get your life back! LOLLuvnhugsBea

  5. 李四说道:

    上面写的是基于相似度的 协同过滤算法,后面实现 是als算法是 基于矩阵分解的。

  6. 匿名说道:

    你好,请问不使用java8的话,代码怎么写

  7. jchubby说道:

    你好,代码中用的是ALS算法,我想请问一下,ALS是UserBase还是ItemBase的协同过滤?

  8. TTT说道:

    rank is the number of latent factors in the model.
    rank是干嘛的

  9. 匿名说道:

    你好我想问一下要运行您的程序,用eclipse可以吗,需要配置什么jar包吗

  10. 匿名说道:

    JavaPairRDD usersProducts = ratings.mapToPair(rating -> new Tuple2(rating.user(), rating.product())); 写法有问题
    换了Function 不支持maptopair了

    • Trudy说道:

      Omenirea merita un pumn in mecla ca sa-si revina. Nu mai putem continua in stilul asta pazairtar de a suge resursele planetei. Ne omoram gazda sau cel putin asa credem, planeta poate oricand sa scape de niste paraziti ca noi.

  11. 匿名说道:

    Rating 的x,y超过Int的最大值,怎么办?
    我的x=19891349869

  12. sunddenly说道:

    你好能共享一下代码吗

  13. 匿名说道:

    你好,受益匪浅,刚学spark,能否加你,以后有什么问题请教您。我qq1246296864

发表评论


profile
  • 文章总数:78篇
  • 评论总数:252条
  • 分类总数:31个
  • 标签总数:43个
  • 运行时间:946天

大家好,欢迎来到selfup.cn。

这不是一个只谈技术的博客,这里记录我成长的点点滴滴,coding、riding and everthing!

最新评论
  • pacificLee: :twisted:
  • 小码: 为什么没有后面的呢,只有前10个
  • Anonymous: :lol:
  • Anonymous: :razz: 楼主是属于会聊天的。 我想问,sqoop发了几个版本了,应该没这些问题了吧。
  • Anonymous: Config.kafkaConfig.kafkaGroupI d 这个是指自己配置的group id 还是从 import org.apache.kafka.common.config .Config 这个类...
  • Anonymous: ZkUtils.getPartitionsForTopics (zkClient, Config.kafkaConfig.topic) 那个方法是在 spark-streaming_2.10 中 kafka...
  • Anonymous: ZkUtils.getPartitionsForTopics (zkClient, Config.kafkaConfig.topic) 你确定 kafka 里面有这个类 ? 个人在kafka 最新 稳定版...
  • Anonymous: :roll:
  • Anonymous: 很不错,试问有java版的吗?
  • Anonymous: 赞
  • Anonymous: 哈哈 看楼主的吐槽乐死了 where子句是可以写的 同样找不到资料 一点点试出来的 select id from xxxx where ${CONDITIONS} and 1=1 and 2=2 limit 4
  • EVIL: 我在运行完C4.5的代码后,显示 defined object DecisionTreeTest 是什么意思?这是有错误吗?运行结果在哪里看?
  • sf: 楼主的问题,我都遇到。。。没办法项目已经定型了,最后都硬着头 皮一个一个的改了源码
  • zz: 我去,楼主你真及时,我们今天上了新的HTTP2 push之后也发现速度曲线很奇怪,开始有200k/min,跟 另一台老的推送协议速度差不多,但是过了一会,立马降到只有几k /min,百思不得其解,我们还用了一个海外代理,在...
  • qi365: :mad: 很可恶,百度助纣为虐~
  • qi365: :? :shock: haha~ very good~
  • 张是大: 《深入浅出Spark机器学习实战(用户行为分析)》 课程网盘下载:http://pan.baidu.com/s/ 1mixvUli 密码:1pfn
  • Anonymous: :???:
  • Anonymous: 我用着sqoop感觉还可以,select 几十个字段也没事,估计是版本低。。
  • Anonymous: :grin: