实习做了一个个性化推荐项目,尝试了协同过滤和word2vec两种算法,现在实习结束了做点记录。本篇介绍协同过滤算法,公司大数据平台开发环境简陋,没有Python编译环境,脚本是用Scala写的。
协同过滤
协同过滤(collaborative filtering)是一种在推荐系统中广泛使用的技术。该技术通过分析用户或者事物之间的相似性(“协同”),来预测用户可能感兴趣的内容并将此内容推荐给用户。这里的相似性可以是人口特征(性别、年龄、居住地等)的相似性,也可以是历史浏览内容的相似性(比如都关注过和中餐相关的内容),还可以是个人通过一定机制给予某个事物的回应(比如一些教学网站会让用户对授课人进行评分)。比如,用户A和B都是居住在北京的年龄在20-30岁的女性,并且都关注过化妆品和衣物相关的内容。这种情况下,协同过滤可能会认为,A和B相似程度很高。于是可能会把A关注B没有关注的内容推荐给B,反之亦然。
在协同过滤算法中,基于用户的相似性推荐叫UserCF,基于商品的推荐叫ItemCF。
算法思路
电商场景中产品规模大而用户购买行为矩阵稀疏,应选用ItemCF进行相似性推荐。
算法思想:
使用用户订单记录计算商品相似性,如果一个用户同时购买了商品1和商品2,则认为这两个商品具有比较高的相似性。根据商品相似性进行推荐,如果计算得出商品1和商品2的相似性较高,就对已购买了商品1且未购买商品2的用户推荐商品2。
实现思路如下:
- 构建共现矩阵。根据用户的行为,构建以用户为行坐标,物品为纵坐标的共现矩阵。
- 构建物品相似度矩阵。根据共现矩阵计算两两物品之间的相似度,得到物品相似度矩阵。
- 获取Topn相似物品。根据用户历史正反馈物品,找出最相似的n件物品。
- 计算用户对Topn物品的喜好度。用户对物品的喜好度定义为:当前物品和用户历史物品评分的加权和,加权系数是前面计算的物品相似度。在我的问题背景中,用户只是购买了产品而未对其进行评分,因此使用用户对某件物品的购买次数作为偏好。计算方法如下所示:
$$r_{u,p}=\sum_{i}w_{p,i} \cdot r_{u,i}.$$ - 根据喜好度生成排序结果。
完整代码
首先定义一些通用类:
1 | package recommend |
定义相似度计算:
1 | object ItemSimilarity{ |
模型调用
1 | package recommend |
进行推荐
1 | package recommend |
这个算法实现之后在公司跑了一下,发现虽然算法很简单,但需要的计算资源很大,即使在Spark集群中,跑100万条记录的数据量也很费劲(当然可能跟分配的资源有关系),所以后来就没有继续使用了。
写着写着发现word2vec的代码忘记自己备份了,嘿嘿,那就先发这个吧。
word2vec因为spark中封装了相应的方法,实现起来比ItemCF容易许多,计算速度也很快。但很让人头痛的地方是spark提供的包中封装的方法太少,如果要在该算法上做一些调整,可能还需要从更底层开始实现。