推荐系统实践(项亮)第七章

第七章 推荐系统实例

如何设计一个真实的推荐系统处理不同的数据,根据不同的数据设计算法,并将算法融合到系统中?

本章介绍推荐系统的外围架构,以及推荐系统架构每个模块的设计。

7.1 外围架构

一般来说,每个网站会有一个UI系统,负责展示网页和交互,网站会通过日志系统将UI上的各种行为记录到用户行为日志中,并存储在内存缓存、数据库或文件系统中,推荐系统分析日志,然后生成推荐列表展示在网页界面上。

image-20220415114106381

因此,推荐系统的作用依赖于两个条件:界面展示和用户行为数据。

数据收集和存储

image-20220415114808417

按照数据的规模和是否需要实时存取,不同的行为数据将被存储在不同的媒介中。一般来说,需要实时存取的数据存储在数据库和缓存中,而大规模的非实时地存取数据存储在分布式文件系统(如HDFS)中。

数据能否实时存取在推荐系统中非常重要,因为推荐系统的实时性主要依赖于能否实时拿到用户的新行为。只有快速拿到大量用户的新行为,推荐系统才能够实时地适应用户当前的需求,给用户进行实时推荐。

7.1 推荐系统架构

推荐系统联系用户和物品的方式主要有三种:

image-20220415115141245

实际上,也可以把用户喜欢的物品、和用户兴趣相似的其他用户看作一种用户特征,一言以蔽之,用户和物品是通过特征联系的。因此,推荐系统的核心任务有两部分:1.如何为给定用户生成特征;2.如何根据特征找到物品。

image-20220415115459769

用户的特征种类eg:

  • 人口统计学特征包括用户的年龄、性别、国籍和民族等用户在注册时提供的信息。
  • 用户的行为特征包括用户浏览过什么物品、收藏过什么物品、给什么物品打过什么样的分数等用户行为相关的特征。同时,用户行为从时间上也可以分为用户近期的行为和长期的行为。
  • 用户的话题特征可以根据用户的历史行为利用话题模型(topic model)将电视剧和电影聚合成不同的话题,并且计算出每个用户对什么话题感兴趣。比如用户如果看了《叶问》、《新龙门客栈》和《醉拳》,那么可以认为用户对“香港武侠电影”这个话题感兴趣。

推荐任务eg:

  • 将最新加入的物品推荐给用户。
  • 将商业上需要宣传的物品推荐给用户。
  • 给用户推荐不同种类的物品,比如亚马逊会推荐图书、音像、电子产品和服装等。
  • 给用户混合推荐,有时需要将图书和音像制品放到一个推荐列表中展示给用户。
  • 对于不同的产品推荐不同新颖度的物品。比如在首页给用户展示比较热门的推荐结果,在推荐系统页面给用户展示长尾中的物品。
  • 考虑到用户访问推荐系统的上下文,比如当你在豆瓣音乐找到“李宗盛”时,右侧会有一个链接告诉你可以在豆瓣电台收听“李宗盛”。单击了这个链接后,豆瓣电台给你推荐的音乐就考虑了“李宗盛”这个上下文。

如果要在一个系统中把上面提到的各种特征和任务都统筹考虑,那么系统将会非常复杂,而且很难通过配置文件方便地配置不同特征和任务的权重。因此,推荐系统需要由多个推荐引擎组成,每个推荐引擎负责一类特征和一种任务,而推荐系统的任务只是将推荐引擎的结果按照一定权重或者优先级合并、排序然后返回。

image-20220415120141533

这样做有两个好处:

  • 可以方便地增加/删除引擎,控制不同引擎对推荐结果的影响。对于绝大多数需求,只需要通过不同的引擎组合实现。
  • 可以实现推荐引擎级别的用户反馈。每一个推荐引擎其实代表了一种推荐策略,而不同的用户可能喜欢不同的推荐策略。有些用户可能喜欢利用他的年龄性别作出的推荐,有些用户可能比较喜欢看到新加入的和他兴趣相关的视频,有些用户喜欢比较新颖的推荐,有些用户喜欢专注于一个邻域的推荐,有些用户喜欢多样的推荐。我们可以将每一种策略都设计成一个推荐引擎,然后通过分析用户对推荐结果的反馈了解用户比较喜欢哪些引擎推荐出来的结果,从而对不同的用户给出不同的引擎组合权重。

将推荐系统拆分成不同推荐引擎后,如何设计一个推荐引擎变成了推荐系统设计的核心部分。下一节将讨论推荐引擎的设计方法。

7.3 推荐引擎的架构

推荐引擎架构主要包括3部分。

  • A——从数据库或者缓存中拿到用户行为数据,通过分析不同行为,生成当前用户的特征向量。不过如果是使用非行为特征,就不需要使用行为提取和分析模块了。该模块的输出是用户特征向量。
  • B——将用户的特征向量通过特征-物品相关矩阵转化为初始推荐物品列表。
  • C——对初始的推荐列表进行过滤、排名等处理,从而生成最终的推荐结果。
image-20220415120521704

7.3.1 生成用户特征向量(A部分)

上面提到的用户行为特征可分为两类:

  • 直接从用户注册信息提取出来的,如人口统计学特征。使用这类特征的推荐引擎,可以直接将信息缓存在内存中,推荐时直接读取特征数据并生成特征向量

  • 而行为特征,话题模型这些都是从用户行为中计算得到的

特征向量由特征及其权重组成,利用用户行为计算特征向量时需要考虑:

  • 用户行为的种类 不同行为对物品特征的权重影响不同,一般的标准就是用户付出代价越大的行为权重越高。比如,购买和浏览物品,显然前者对反映用户的真实兴趣影响更大。
  • 用户行为产生的时间 一般来说,用户近期的行为比较重要,因此,如果用户最近购买过某一个物品,那么这个物品对应的特征将会具有比较高的权重。
  • 用户行为的次数 用户对同一个物品的同一种行为发生的次数也反映了用户对物品的兴趣,行为次数多的物品对应的特征权重越高。
  • 物品的热门程度 如果用户对一个很热门的物品产生了行为,往往不能代表用户的个性。特别是在用户对一个热门物品产生了偶尔几次不重要的行为(比如浏览行为)时,就更说明用户对这个物品可能没有什么兴趣。反之,如果用户对一个不热门的物品产生了行为,就说明了用户的个性需求。因此,推荐引擎在生成用户特征时会加重不热门物品对应的特征的权重。

7.3.2 特征-物品相关推荐(B部分)

得到用户的特征向量后,可根据离线的相关表得到初始的物品推荐列表。离线相关表可以存储在MySQL中,对于每个特征,可以在相关表中存储和它最相关的$N$个物品的ID。

image-20220415182057885

在线使用的特征一物品相关表一般都不止一张。以论文之间的相关表为例,计算论文之间的相关性既可以使用协同过滤算法(即如果两篇论文的读者重合度很大说明两部电视剧相似),也可以通过内容计算(比如有相同的作者、关键词、相似的标题等)。即使是协同过滤,也可以根据不同的用户行为数据得到不同的相关表。比如可以根据用户的打分行为计算论文之间的相关性,也可以根据用户的浏览行为计算论文之间的相关性。总之,对于一个推荐引擎,可以在配置文件中配置很多相关表以及它们的权重,而在线服务在启动时会将这些相关表按照配置的权重相加,然后将最终的相关表保存在内存中,而在给用户进行推荐时,用的已经是加权后的相关表了。

架构图中的候选物品集合,其目的是保证推荐结果只包含候选物品集合中的物品,应用场合一般是产品需求,例如要求推荐最近一周新加入的物品,候选集和就包括最近一周新加的物品;也有可能是用户自己的选择,例如只看某个价格区间的物品。

7.3.3 过滤模块(C部分)

初步的推荐列表还需要按照产品需求对结果进行过滤,一般会过滤掉:

  • 用户已经产生过的行为物品 保证新颖性
  • 候选物品以外的物品
  • 某些质量很差的物品 一般以历史评分为依据

7.3.4 排名模块(C部分)

经过过滤后的推荐结果,如果对其进行一些排名,会提升效果,排名模块一般包括以下子模块:

新颖性排名

此模块是为了给用户尽量推荐他们不知道的、长尾中的物品。

虽然之前的过滤模块过滤掉了用户有过行为的物品,但用户在当前网站对某个物品没有行为不代表用户不知道这个物品。这种情况显然是难以准确了解的,因此使用以下近似方式,对推荐结果中热门物品进行降权:
$$
p_{ui}=\frac{p_{ui}}{log(1+\alpha\cdot popularity(i))}
$$
除了对推荐结果进行降权,还需要再推荐引擎的各个部分考虑该问题。

本章推荐系统的架构主要基于物品的推荐算法,其推荐公式为$p_{ui}=\sum_{j\in N(u)\cap S(i,K)}w_{ji}r_{uj}$,可以将$j$看作联系用户和物品的特征。$r_{uj}$在通过用户行为生成用户特征向量时计算,而$w_{ji}$是离线计算的物品相似度。

  • 对于$r_{uj}$:如果用户对一热门物品$j$产生行为,有很大的$r_{uj}$,那么和该热门物品相似的其他物品都会在用户的推荐列表中排在靠前的位置,因此需要对$r_{uj}$降权:

$$
r_{uj}=\frac{r_{uj}}{log(1+\alpha \cdot popularity(j))}
$$

  • 对于$w_{ji}$:热门/冷门物品倾向于和热门/冷门物品相似。因此,假设用户对一热门物品$j$产生行为,那么和$j$相似的且比$j$热门的物品,用户也有较大概率知道,因此可以降低权重$w_{ji}$:

$$
w_{ji}=\frac{w_{ji}}{log(1+\alpha \cdot popularity(j))}\qquad(popularity(i)>popularity(j))
$$

此外,还可以引入内容相似度矩阵,因为内容相似度矩阵中每个物品相似的物品都不是很热门,因此引入内容相似度矩阵也能提高最终推荐结果的新颖度。

多样性

此模块是为了让推荐结果覆盖尽可能多的用户兴趣(需要注意的是,提高多样性并不是都很好,例如有时人们在某一时刻的兴趣是固定的),提高多样性的方法有:

  • 将推荐结果按照某种物品的内容属性分成几类,在每个类中选择排名最高的物品然后再组合形成最终的推荐列表。这种方法简单直观,但缺点是选择什么样的内容属性进行分类对结果的影响很大,并且物品属于哪个类别并不一定能获得用户公认。
  • 第二种方法是控制不同推荐结果的推荐理由出现的次数,要提高推荐结果多样性,就应该让推荐结果尽量来自不同的特征,具有不同的推荐理由。

时间多样性

时间多样性是为了保证用户不要每天来推荐系统都看到相同的推荐结果,第五章提到提高时间多样性有两点:

  • 在用户有新行为时能实时调整推荐结果 这一点,本章的设计中已经考虑到,行为提取和分析模块能实时拿到行为数据并转化为新的特征,然后经过特征—物品相关模块就能实时拿到行为数据并转化为新的特征,然后经过特征—物品相关模块转换成和新特征最相关的物品。
  • 在用户没有行为时也能保证推荐结果每天变化,可通过如下方式:
    • 记录用户每次登陆系统时看到的推荐结果
    • 将这些结果发回日志系统。这种数据不需要实时存储,只要能保证小于一天的延时即可
    • 在用户登录时拿到用户昨天及之前看过的推荐结果列表,从当前推荐结果将用户已经看到的推荐结果降权

用户反馈

排名模块最重要的部分是用户反馈模块,该模块通过分析用户之前和推荐结果的交互日志,预测用户会对什么样的推荐结果比较感兴趣。

如果推荐系统的目标是提高用户对推荐结果的点击率,那么可以利用点击模型(click model)预测用户是否会点击推荐结果。点击模型在很多领域得到了广泛应用,比如搜索结果的点击预测、搜索广告的点击预测、上下文广告的点击预测。点击预测的主要问题是预测用户看到某个推荐结果时是否会点击。那么要进行点击率预测,首先需要提取特征。在推荐系统的点击率预测中可以用如下特征预测用户$u$会不会点击物品$i$:

  • 用户$u$相关的特征,比如年龄、性别、活跃程度、之前有没有点击行为;
  • 物品$i$相关的特征,比如流行度,平均分,内容属性;
  • 物品$i$在推荐列表中的位置。用户的点击和用户界面的设计有很高的相关性,因此物品在推荐列表中的位置对预测用户是否点击很重要;
  • 用户之前是否点击过和推荐物品$i$具有同样推荐解释的其他推荐结果;
  • 用户之前是否点击过和推荐物品i来自同样推荐引擎的其他推荐结果。

点击模型需要离线计算好,在线将模型加载到内存中。为了提高在线预测的效率,一般只可以使用线性模型。

7.4 总结

关于推荐系统架构方面的文章很多,不过详细介绍架构的技术报告不多。例如亚马逊和Netflix等都只给出了一些简单的线索。

本章提到的推荐系统架构主要是作者基于在Hulu工作时使用的架构抽象发挥出来的,对于Hulu架构感兴趣的读者可以参考Hulu的技术博客

本章提出的推荐系统架构基本上是从基于物品的推荐算法衍生出来的,因此本章的架构并不适合用来解决社会化推荐问题。如果要了解社会化推荐方面的架构,可以参考Twitter公开的一些文档。