引言
信息大爆炸的互联网时代,推荐系统是帮助人们更高效获取信息的手段之一。从淘宝天猫的商品推荐,到头条的信息流推荐,再到短视频推荐,推荐系统已经渗透到我们生活的方方面面。作为公众号的开篇系列,我们将分享关于推荐系统的各种技术,从传统的协同过滤,到深度学习在推荐领域的应用。总结多年工作实践所得,帮助读者更全面深入地了解推荐系统。
协同过滤是推荐系统最基础的算法,它可以简单分为User-based CF和Item-based CF。ItemCF的核心思想是选择当前用户偏好的物品的相似物品作为推荐结果。而UserCF是选择当前用户的相似用户偏好的物品作为这个用户的推荐结果。这篇文章将介绍如何基于Spark用不到一百行的代码实现相似物品的计算。
数据准备
推荐系统是由数据驱动的,在实际企业工作中,用户行为数据存储在数据仓库中。假设数据仓库上有一张用户行为日志表:t_user_interaction,它的DDL如下:
CREATE TABLE t_user_interaction(
`user_id` string COMMENT 'User ID',
`item_id` string COMMENT 'Item Id',
`action_time` bigint COMMENT '动作发生的时间')
PARTITIONED BY (
dt bigint)
通过Spark的SQL引擎很容易获取我们需要的数据:
val sql =
s"""
|select
|user_id,
|item_id
|from t_user_interaction
|where dt>=${param.startDt} and dt<=${param.endDt}
""".stripMargin
val interactions = spark.sql(sql)
.rdd
.map(r => {
val userId = r.getAs[String]("user_id")
val itemId = r.getAs[String]("item_id")
(userId, itemId)
})
这里我们设置了两个参数:startDt
,endDt
,即一个滑动时间窗的开始时间和结束时间。实际生产环境,用户的行为日志在连续不断的产生,线上会不间断的收集这些行为日志,然后按一定时间窗,比如一个小时,保存一次。ItemCF的计算任务也需要按一定时间滑动窗口周期运行,因为会不断有新的物品出现,系统需要尽可能快地计算出新物品的相似物品,才能在用户对新物品产生新的行为后尽快做出响应。
相似度计算
物品的相似度计算有很多公式,这里我们以最常用的余弦相似度为例:
s i m X , Y = X Y ∣ ∣ X ∣ ∣ ∣ ∣ Y ∣ ∣ = ∑ i = 1 n ( x i y i ) ∑ i = 1 n ( x i ) 2 × ∑ i = 1 n ( y i ) 2 sim_{X,Y}=\frac{XY}{||X||||Y||}=\frac{ \sum_{i=1}^n(x_iy_i)}{\sqrt{\sum_{i=1}^n(x_i)^2}\times\sqrt{\sum_{i=1}^n(y_i)^2}}