1.典型的信息流架构
信息流是推荐系统应用中的当红炸子鸡,它表现形式有很多:社交网络的动态信息流、新闻阅读的图文信息流、短视频信息流等等。
整体框架图如下:
具体模块:
这张架构图划分成几个大的模块:日志收集、内容发布、机器学习、信息流服务、监控。这里分别介绍一下:
1.日志收集
是所有排序训练的数据来源,要收集的最核心数据就是用户在信息流上产生的行为,用于机器学习更新排序模型;
- 总体数据模型
信息流的基本数据有三个:用户(User)、内容(Activity)和关系(Connection)。用户不用说,就是区别不同用户的身份 ID,我来说一说其他的两种。 - 具体数据
1)内容即 Activity。
一条 Activity 包含的元素有:Time、Actor、Verb、Object、Target、Title、Summary。下面详细解释一下这些元素。
2)Time:即“Activity 发生的时间”。
3)Actor:即“Activity 由谁发出的”。通常 Actor 就是用户 ID,但是我们也可以扩展到其他拟人化物体上,如关注的一个“店铺”,收藏的一部“电影”,或者用户喜欢的一个标签或者分类。也就是和用户建立连接的另一端。
3)Verb:动词,就是连接的名字,比如“Follow”“Like”等,也可以是隐含的连接,如挖掘出的用户兴趣词和用户之间这种潜规则。4)Object:即动作作用到最主要的对象,只能有一个,比如一个人赞过的一张照片,店铺上新的一件商品,一个分类下一篇新的文章。Target:动作的最终目标,与 verb 有关,可以没有。它对应英语中介词 to 后接的事物,比如“John saved a movie to his wishlist”(John 保存了一部电影到清单里),这里电影就是 Object,而清单就是 Target。
5)Title:这个是 Activity 的标题,用自然语言描述,用于展示给用户。
6)Summary:通常是一小段 HTML 代码,是对这个 Activity 的描述,还可能包含类似缩略图这样的可视化元素,可以理解为 Activity 的视图,不是必须的。
2.内容发布
内容发布就是用推或者拉的模式把信息流的内容从源头发布到受众端;
"拉模式"(Fan-out-on-load)
即:信息流是在用户登录或者刷新后实时产生的。这里有一个示意图:
上面这个步骤别看简单,在一个小型的社交网络上,通常很有效,而且 Twitter 早期也是这么做的
- 拉模式步骤:
1). 获取用户所有连接的终点(如好友、关注对象、兴趣标签);
2). 获取这些连接终点(关注对象)产生的新内容(Activity);
3). 按照某个指标排序后输出。 - “拉”模式的好处
1). 实现简单直接:一行 SQL 语句就搞定了。
2). 实时:内容产生了,受众只要刷新就看得见。 - “拉”模式的不足:
1). 随着连接数的增加,这个操作的复杂度指数级增加;
2). 内存中要保留每个人产生的内容;
3). 服务很难做到高可用。
"推模式"
与“拉”模式对应,还有一个“推”模式(Fan-out-on-write),这里有一个示意图:
- "推"模式步骤
1)用户A产生内容
2)不管受众在不在线,刷没刷新,都会立即将这条内容推送给相应的用户B(即和这个 Actor 建立了连接的人) - "推"模式好处
1)在用户访问自己的信息流时,几乎没有任何复杂的查询操作,所以服务可用性较高。 - "推"模式不足
1)大量的写操作:每一个粉丝都要写一次。
2)大量的冗余存储:每一条内容都要存储 N 份(受众数量)。
3)非实时:一条内容产生后,有一定的延迟才会到达受众信息流中。
4)无法解决新用户的信息流产生问题。
全局方案
既然两者各有优劣,那么实际上就应该将两者结合起来,一种简单的结合方案是全局的
- 对于活跃度高的用户,使用推模式,每次他们刷新时不用等待太久,而且内容页相对多一些;
- 对于活跃度没有那么高的用户,使用拉模式,当他们登录时才拉取最新的内容;
- 对于热门的内容生产者,缓存其最新的 N 条内容,用于不同场景下的拉取。
3.信息流排序(机器学习)
从收集的用户行为日志中训练模型,然后为每一个用户即将收到的信息流内容提供打分服务
- 信息流的排序,要避免陷入两个误区:
1)第一个误区“没有目标”意思就是说,设计排序算法之前,一定要先弄清楚为什么要对时间序重排?希望达到什么目标?只有先确定目标,才能检验和优化算法。
目前信息流采用机器学习排序,以提升类似互动率,停留时长等指标,这已经成为共识。比如说提高互动率则需要下面几个内容:
- 首先,定义好互动行为包括哪些,比如点赞、转发、评论、查看详情等;
- 其次,区分好正向互动和负向互动,比如隐藏某条内容、点击不感兴趣等是负向的互动。
基本上到这里就可以设计成一个典型的二分类监督学习问题了,对一条信息流的内容,在展示给用户之前,预测其获得用户正向互动的概率,概率就可以作为兴趣排序分数输出。能产生概率输出的二分类算法都可以用在这里,比如贝叶斯、最大熵、逻辑回归等。互联网常用的是逻辑回归(Logistic Regression),谁用谁知道,用过的都说好;也有 Facebook 等大厂采用了逻辑回归加梯度提升树模型(又称 GBDT)来对信息流排序,效果显著。对于线性模型,一个重要的工作就是特征工程。
信息流的特征有三类:
1.用户特征,包括用户人口统计学属性、用户兴趣标签、活跃程度等。
2.内容特征,一条内容本身可以根据其属性提取文本、图像、音频等特征,并且可以利用主题模型提取更抽象的特征。
3.其他特征,比如刷新时间、所处页面等。
排序模型在实际使用时,通常做成 RPC 服务,以供发布信息流时调用。
2)第二个误区是“人工量化”,也就是我们通常见到的产品同学或者运营同学要求对某个因素加权、降权。这样做很不明智,主要是不能很好地持续优化。
4.数据管道(信息流服务)
信息流是一个数据驱动的系统,既要通过历史数据来寻找算法的最优参数,又要通过新的数据验证排序效果,所以搭建一个数据流管道就是大家翘首期盼的。
这个管道中要使用的相关数据可能有:
-
互动行为数据,用于记录每一个用户在信息流上的反馈行为;
-
曝光内容,每一条曝光要有唯一的 ID,曝光的内容仅记录 ID 即可;
-
互动行为与曝光的映射关系,每条互动数据要对应到一条曝光数据;
-
用户画像内容,即用户画像,提供用户特征
用户画像 -
信息流的内容分析数据,提供内容特征,即物品画像。
对于一个从零开始的信息流,没必要做到在线实时更新排序算法的参数,所以数据的管道可以分成三块:
- 生成训练样本,可离线;
- 排序模型训练,可离线;
- 模型服务化,实时服务;
5.监控
这是系统的运维标配,保证系统的安全和稳定等。
2.经典架构(Netflix个性化推荐架构)
上面介绍的是当下最热门的推荐系统产品形式——信息流的架构,信息流并不是传统意义上的推荐系统,下面介绍一种更符合经典推荐系统的架构,这就是著名的流媒体 Netflix 的推荐系统架构。
下面这张图就是 Netflix 的推荐系统架构图。
整体看一下这个架构,一共分成三层:在线、近线、离线。
- 离线:不用实时数据,不提供实时服务;
- 近线:使用实时数据,不保证实时服务;
- 在线:使用实时数据,要保证实时服务。
1.具体介绍
数据流
- 数据流的产生和流向
1)产生:用户在产品 UI 上使用产品,消费展示的内容,产生行为事件数据,实时地被收集走。
2)流向:一边进入分布式的文件系统中存储,供离线阶段使用,另一边流向近线层的消息队列,供近线阶段的流计算使用。
2.数据的使用
1)离线存储的全量数据被抽取出来,组成离线计算所需的训练数据,这些训练数据被一个管理数据生成和发布的组件统一管理,要使用数据的下游,比如模型训练会在离线数据生成时得到这个组件的通知,从而开始训练,训练得到的模型用于进一步为用户计算推荐结果。
2)离线阶段的推荐结果或者模型在近线阶段被更新,进一步在在线阶段被直接使用,产生最终的推荐结果,呈现给用户。
在线层
在线层的触发时机是当用户发出请求,也就是用户进入一个推荐场景,推荐位等着展示推荐结果时,这个时候需要承担责任就是在线层。在线层就是实时响应用户请求。简单说,在线层的特点就是“使用实时数据,要保证实时服务”。
- 在线层的优势:
1)直接首次接触到大多数最新数据;
2)对用户请求时的上下文了如指掌;
3)只需计算必须的信息,不需要考虑所有的信息。 - 在线层的制约:
1.)严格的服务响应时间,不能超时,或者让用户等太久;
2)服务要保证可用性,稳定性;
3)传输的数据有限。 - 适合放在在线层的计算逻辑:
1)简单的算法逻辑;
2)模型的预测阶段;
3)商业目标相关的过滤或者调权逻辑;
4)场景有关的一些逻辑;
5)互动性强的一些算法。
4.注意点:
1)响应时长:在线阶段要处理的对象一般是已经预处理后的推荐结果,是少量物品集合。比如说当用户访问一个物品详情页,需要做相关推荐,那么在线阶段给在线服务的 Rest API 传入用户身份以及当前的物品 ID,实时地取出物品 ID 对应的相关物品 ID,再根据用户信息对这些物品 ID 做一些重排和过滤,就可以输出了,整个过程都是在 ms 级别完成。
2)推荐为空:这个实时响应的过程中,如果发生意外,比如说这个物品 ID 就没有相关的物品,那么这时候服务就需要降级,所谓的降级就是不能达到最好的效果了,但是不能低于最低要求,这里的最低要求就是必须要返回东西,不能开天窗。于是,这就降级为取出热门排行榜返回。虽然不是个性化的相关结果,但是总比开天窗要好。这就是服务的可用性。
3)重复推荐:在线阶段还要实时地分发用户事件数据,就是当用户不断使用产品过程产生的行为数据,需要实时地上报给有关模块。这一部分也是需要实时的,这样可以用于防重复推荐的过滤。
离线层
离线层就是躲在推荐系统的大后方,批量、周期性地执行一些计算任务。其特点是“不用实时数据,不提供实时服务”。
-
离线层的示意图:
-
数据源:Hadoop(HDFS)
-
数据抽取工具:Pig或Hive
-
离线阶段的任务:模型训练和推荐结果计算。通常机器学习类模型,尤其是监督学习和非监督学习,都需要大量的数据和多次迭代,这类型的模型训练任务最适合放在离线阶段。举个例子,你已经知道推荐系统中会有召回和融合排序这两个阶段。通常一些推荐算法,例如协同过滤就是在离线阶段计算出每个人的推荐结果,作为线上融合排序的候选集之一,也就是示意图中的“推荐结果”。另一方面,假如融合排序模型时逻辑回归,那么逻辑回归模型的参数也通常在离线阶段就训练完成的,在线阶段也只是取出来参数用于计算而已。另一方面,假如融合排序模型时逻辑回归,那么逻辑回归模型的参数也通常在离线阶段就训练完成的,在线阶段也只是取出来参数用于计算而已。
-
离线阶段的好处:
1)可以处理最大的数据量;
2)可进行批量处理和计算;
3)不用有响应时间等要求。 -
离线阶段的坏处:
1)无法及时响应前端需求;
2)面对的数据较静态,无法及时反应用户的兴趣变化。 -
离线计算框架:
大多数推荐算法,实际上都是在离线阶段产生推荐结果的。离线阶段的推荐计算和模型训练,如果要用分布式框架,通常可以选择 Spark 等。
近线层
近线层的特点是“使用实时数据,不保证实时服务”,把它的特点翻译得直白点就是:喂给我最新鲜的牧草,但是我不保证能马上给你挤奶。虽然这看上去蛮不讲理,但实际上这是一个非常重要的一层,它结合了离线层和在线层的好处,摒弃了两者的不足。
- 数据来源
实时的行为事件队列 - 数据去向
计算的结果并不是沿着输入数据的方向原路返回,而是进入了在线数据库中,得到用户真正发起请求时,再提供服务。 - 一个典型的近线计算任务
从事件队列中获取最新的一个或少许几个用户反馈行为,首先将这些用户已经反馈过的物品从离线推荐结果中剔除,进一步,用这几个反馈行为作为样本,以小批量梯度下降的优化方法去更新融合模型的参数。 - 近线计算框架
近线计算任务一个核心的组件就是流计算,因为它要处理的实时数据流。常用的流计算框架有 Storm,Spark Streaming,FLink 等,Netflix 采用的内部流计算框架 Manhattan,这和 Storm 类似。略有区别的是 Spark Streaming,实际上并不是实时流计算,而是小批量计算。
经典架构总结
关于这个架构你只需要记住一点:它有三层,三层分别是离线,近线,在线。
用如下的表格将这三层综合对比,并且简单举例:
2.简化架构
Netflix 是为全球多个国家同时提供在线服务的,因此推荐系统的架构略微复杂。倘若你现在刚刚接手一个新产品,要从 0 开始搭建一个推荐系统,那么可以以 Netflix 的架构作为蓝本,做一定的简化。
- 简化架构图
- 关键简化有两点:
1)完全舍弃掉近线层;
2)避免使用分布式系统。在一个新产品的场景下, 当数据量还没有那么大时,使用分布式存储或者计算框架,非常不划算。