1.1-概览

8/2/2021

# 推荐系统的意义是什么?

推荐系统的作用就是在随着网络世界的内容信息过载的情况下,主动在人和内容之间建立高效的连接,建立起用户与信息之间的粘性,从而将用户留存下来,消费更多的时间和金钱。

# 请简要阐述一个推荐系统是如何运行的?

第一步:给物料打标签,通过人工或者内容理解算法根据封面、标题生成;
第二步:建立倒排索引,key是标签,value是被打上这个标签的所有物料;
第三步:推荐系统接受用户请求,检索得到用户uid对应的兴趣爱好标签;
第四步:拿用户的兴趣爱好标签去建立的倒排索引中检索,召回用户可能感兴趣的物料;
第五步:通过模型计算用户对物料的喜爱程度,对Score按降序排列,即排序阶段;
第六步:对排序得到的结果进行重排、截断等,在前端展示给用户;
第七步:将用户的点击行为记录到日志中,回传给上游,更新用户的兴趣和物料的质量

# 推荐系统中为什么要有召回?在推荐系统中召回和排序有什么异同?

首先,在实际应用中,推荐算法往往是在线上使用,可用的设备资源和响应时间都是有限的。而整个物品集的规模往往十分庞大,在线上对大量物品进行排序是对性能的较大挑战,很难实现。召回可以视为一个粗排序的过程,这个过程的主要目的是在有限的资源条件下提供尽可能准确的一个小候选集,从而减轻排序阶段的计算负担和耗时。
其次,即使资源和时间足够对整个物品集进行扫描,先使用较为简单的方法进行召回往往也是比较有利的,先进行召回意味着可以排除大部分无关物品,从而允许在排序阶段对更小的候选集使用更多的特征和更复杂的模型,以提高排序的准确率。
召回层一般待计算的候选集合大、速度快、模型简单、特征较少,尽量让用户感兴趣的物品在这个阶段能够快速被召回,即保证相关物品的召回率。在离线处理物料时,因为不知道将来要访问的用户是谁,所以召回模型在结构与特征上,不能出现用户信息与物料信息的交叉,这限制了其表达能力和预测精度。工业界主流的召回方式是采用多路召回策略,采用多个简单策略叠加的方式得到最终的召回结果。
排序层的首要目标是得到精准的排序结果,需处理的物品数量少,可利用多特征,使用比较复杂的模型。

# 请简述粗排的主要功能和特点

召回的精度一般,用数量弥补质量,倾向于召回更多物料,送往下游。而精排为了提升预测精度,不断加大模型复杂度,而牺牲了模型的吞吐能力。因为这一增一减,如果让召回直接对接精排,笨重的精排面对召回送来的越来越多的候选物料,肯定又会吃不消了。粗排为了解决这一矛盾,接在召回后面,一般将召回的10000个结果再过滤掉9成,只保留最具潜力的1000个,再交给精排重点考察。
由此可见,粗排夹在召回与精排之间,又是一个速度与精度折衷妥协的产物,地位有些尴尬。在一些小型推荐系统中,召回的结果也不太大,干脆就放弃粗排,召回结果都喂入精排。
粗排在技术上也夹在召回与精排之间,不上不下的:

  1. 由于候选集规模比召回小得多,相比召回,粗排模型可以接入更多特征,使用更复杂的结构。
  2. 另一方面,由于候选集比精排还大得多,粗排模型比精排又简单太多。比如主流粗排模型仍然依赖"离线计算+在线缓存"模式来处理候选物料,所以仍然不能使用用户信息与物料信息交叉的特征与结构。

# 请简述重排的主要功能和特点

精排时,相似内容(比如相同话题、相同标签) 会被粗排模型打上相近的分数,从而在结果集中排在相近的位置。如果将这样的排序结果直接呈现给用户,用户连看几条相似内容,很容易审美疲劳,从而伤害用户体验。所以,精排结果还需要经过重排。与前面三个环节不同,重排的主要目的不是为了过滤筛选,而是为了调整精排结果的顺序,将相似内容打散,保证用户在一屏之内看到的推荐结果,丰富而多样。
虽然重排与粗排都属于"配角",但是与粗排在小型推荐系统中可有可无的地位不同,无论系统规模,重排都是不可或缺的。只不过在小型系统中,重排比较简单,用几条启发性规则就能实现。而到了互联网大厂的推荐系统中,重排也用上了比较复杂的模型。

# 召回模型有什么显著区别于排序模型的特点?

  • 特征选择上

召回面对的候选item是百万级、千万级,一般此类召回模型都是双塔型的,以便单独生成user embedding和item embedding,喂入的特征禁止含有user/item之间的交叉特征。user特征喂入user tower得到user embedding,item特征喂入item tower得到item embedding。离线时,先将item embedding喂入FAISS建立索引,线上召回时,拿user embedding去FAISS里进行top-k近邻搜索,找到与其最接受的item embedding。

  • 样本选择上

正样本没有太多的争议,以内容推荐为例,选“用户点击”的item为正样本。最多考虑一下用户停留时长,将“用户误点击”排除在外;负样本的选择比较有讲究。如果说排序是特征的艺术,那么召回就是(负)样本的艺术。原则之一就是不能(只)拿“曝光未点击”做负样本,负样本的绝大部分应该由“随机负采样”生成。原则之二就是要打压热门item。

  • 损失函数上

因为绝大多数负样本是通过随机采样生成的,含有一定的噪声,因此召回不适合采用CTR预估常用的pointwise cross-entropy loss,而经常采用pairwise loss,比如margin-based bpr loss或hinge loss。因此喂入模型的样本,区别于排序中常见的<user, item, label>,而是三元组<user, item+, item->,预测的目标是MatchScore(user, item+)要远高于MatchScore(user, item-)

# 计算视频的点击率在具体的技术实践中有哪些难点?

  1. 首先,为了保证统计结果的有效性,我们需要将统计窗口拉得长一些,比如统计过去一周每个视频的曝光数、点击数。但是大型互联网系统每天产生的日志数以T计,要回溯的历史越长,涉及的计算量也就越大。
  2. 其次,时间上还非常紧张。线上预测时,从接到用户请求到返回推荐结果的总耗时要严格限制在百十毫秒,而且其中的大头还被好几次模型调用占据了,留给所有特征的准备时间不会超过10毫秒。
  3. 最后,回溯数据已经存储在Hadoop分布式文件系统(Hadoop Distributed File System,HDFS)上的那部分日志,也就是所谓的"冷数据"(Cold Data)。但受HDFS只支持批量读写的性质所限,还有许多用户行为未来得及组成用户日志,或者未来得及落盘在HDFS上,即所谓的"热数据"(HotData)。比如我们在下午3点想获得最新的指标数据,但是HDFS上的日志才保存到下午1点,计算出来也是2小时前的过时数据,这2小时的缺口如何填补?

# 推荐系统大数据系统的Lambda架构是什么样的?请简要概括一下。

image.png
其大致的流程如下:

  1. 将数据请求拆解为分别针对冷、热数据的两个子请求。
  2. 针对冷数据的请求,由"离线层”批量完成计算,其结果由”近线层”缓存并提供快速查询。
  3. 针对热数据的请求,由”在线层”基于流式算法进行处理。
  4. 汇总从冷、热数据分别获得的子结果,得到最终的计算结果。

# 以计算视频的点击率CTR为例,简述在离线层、近线层和在线层分别是如何运作的?

这个任务可以拆解为以下两个子任务:

  1. 在冷数据上计算代表一个视频长期、稳定的受欢迎程度的
  2. 在热数据上计算代表一个视频V短期、当下的受欢迎程度的
  • 离线层:

为了计算,我们启动一个小时级的定时任务,每个小时都向前回溯一周的用户行为日志,统计这个时间窗口内每个视频V的曝光数与点击数,再相除就得到了。为了加速,我们可以定时跑另一个小时级的批量任务,统计每个小时内每个视频的曝光、点击总数,并保存结果。有了这些小时级中间结果的加持,"统计一周的"只需要汇总168个中间结果就行了,而无须从头分析统计每条用户日志,计算效率大为提高。另外,这些小时级的中间结果也能够被其他上层计算任务所复用,避免重复计算。
以上这些定时扫描日志的批量计算任务,就构成了Lambda架构中的"离线层"。技术上,这些批量计算任务可以凭借Hadoop、Spark、Flink等大数据框架来完成,而多个任务之间的协同可以由Airflow来完成。

  • 近线层

离线层计算完毕之后,所有视频过去一周的CTR还停留在HDFS上。 而HDFS是一种擅长批量读写,但随机读写效率极低的存储介质,不利于线上快速读取。为了提高查询速度,我们将离线批量计算的结果导入Cassandra、Redis这样的"健~值"(Key-Value, KV) 型数据库。这些起缓存、加速访问作用的KV数据库就构成了Lambda架构中的”近线层"。
回到视频CTR这个例子中,KV数据库存储离线计算好的该视频过去一周的CTR,线上服务以每个视频的ID作为键,在其中快速检索。

  • 在线层

离线批量计算只能处理已经落盘在HDFS上的冷数据。但是因为HDFS只支持批量读写,所以用户行为从发生到被记录在HDFS上,之间存在着小时级别的延时。这也就意味着,用户最新的行为都未能体现在离线批量计算的结果中。假设现在是下午4点,我可以根据某视频的ID,从"近线层"提取到该视频过去一周的CTR,但是这个CTR是以下午2点为终止时间向前回溯一周的统计结果,和当前时间有着2小时的缺口,已经过时了。下午3~4点这两小时内,该视频的消费情况,我们还一无所知呢。"在线层"正是为了弥补上这块短板。这一层凭借Storm、Flink等流式计算框架,对接用户的行为数据流,不等数据落地,就直接对它们进行分析计算,计算结果也缓存在Redis这样支持随机读写的数据库中,方便线上查询。
回到视频CTR,我们在Redis中以"<xx视频,xx日xx小时>"为键,存储某视频在某个时间段上的曝光数、点击数,并通过流式计算程序加以在线实时更新。由于在线层只为了弥补冷、热数据间的时延缺口,而这个缺口不过个把小时而已,所以Redis中只需要保留最近几个小时的数据,不会占用太多资源。线上访问的时候,我们已知"近线层"中存储的是从下午2点向前回溯的结果,所以我们从"在线层"的Redis中查询到今天下午3~4点这两个小时内的曝光数与点击数,从而计算出CTR。
到目前为止,对于"视频V的CTR"的这次查询,我们得到了两个子答案,代表长期受欢迎程度的和代表当前受欢迎程度的。我们可以想出一个策略,将两个数字合并成一个数字。而最常见的处理方法则是,把这两个指标都喂入模型,使模型具备不同时间维度的视角。

# 简述一下推荐、广告、搜索之间的联系。

从本质上说,推广搜都是针对用户需求找到最匹配的信息。只不过用户需求的表达方式,区分了是推荐还是搜索;信息服务的对象,区分了是推搜还是广告。

  1. 推广搜都遵循"先由召回模块粗筛,再由排序模块精挑细选的功能架构。
  2. 数据架构上,推广搜都遵循Lambda架构。
  3. 因为从业务本质到系统架构都是高度相似的,很多算法、模型在“推广搜三个领域都是通用的。一个领域发表的论文,很容易在其他两个领域复现;由于技术栈也是相同的,一个领域的工程师也很容易转到其他两个领域。
  4. 推广搜都需要高度的个性化。大家对个性化推荐已经习以为常了,而事实上广告对个性化的需求更高,毕竞推荐结果不符合用户兴趣,只是有损用户体验而已,而广告如果不满足用户需求的话,浪费的可是真金白银。搜索也不能仅仅满足于返回的文档的确包含了搜索关键词。比如不同用户搜索"苹果价格,显示的结果肯定是不同的,至于显示的是水果价格还是手机价格,就取决于搜索系统对用户画像的掌握与利用。

# 简述一下推荐和搜索的差异。

  1. 用户表达其意图的方式不同

搜索中,用户通过输入查询语句显式表达其意图,

  • u表示当前用户,q表示用户输入的查询语句,t表示某一个候选物料
  • 表示搜索模型,衡量物料t对用户u输入的查询q的匹配程度
  • 注意用户信息u也是公式的输入条件。不同用户输入相同的查询语句q,得到的结果也是不一样的,这正是个性化搜索的体现。

推荐中,用户无须显式表达其意图。推荐系统通过自己的长期观察,猜测用户意图,完成推荐。

  • 表示推荐模型,衡量物料t对用户u的匹配程度。

对比两个公式,查询语句q是搜索中表达用户意图最重要的信息来源,在搜索模型中享受VIP待遇。比如,推荐中最重要的特征来源于用户信息与物料信息的交叉,而搜索中最重要的特征要让位于查询语句与物料信息的交叉。查询语句q在搜索模型中也处于关键位置,比如在Attention结构中,q能够用来衡量用户过去行为历史的重要性。

  1. 搜索对结果的准确性要求更加严格

推荐与搜索第二个差异在于,搜索对结果的准确性要求得更加严格。这种准确性一方面体现在对多个查询条件的处理上。
当某用户搜索"二战德国坦克",搜索结果如公式所示。

  • 代表带有"二战"标签的文章的集合,含义类似。
  • 代表搜索结果,是三个标签集合的交集,即由同时包含所有标签的文章组成。

当用户点击了中的一篇并阅读完毕,此时会触发相关推荐,给用户推荐与刚才那篇文章类似的文章。推荐结果如公式所示:

代表推荐结果,是由三个标签的文章集合的并集组成,目的是为了能够更大范围地涵盖用户兴趣。

搜索结果对准确性要求更高,还体现在对扩展性的容忍程度上。如果用户画像中包含"二战、德国、坦克"这三个标签,推荐系统对这些标签扩展一下,给该用户推荐一篇讲"二战苏联飞机"的文章,也是可以接受的,不会认为是一个Bug,反而有利于对用户的兴趣探索。但是如果用户搜索"二战德国坦克",用户的需求已经非常明确了,再展示"二战苏联飞机"的文章,就是不可接受的,说明搜索系统出了Bug。

# 简述一下搜推和广告的区别

首先推搜是为了留用用户来制造流量,所以要服务的目标比较简单,就是为了给用户提供最佳使用体验。而广告是为了将流量变现,所以要兼顾用户、广告主、平台三方面的利益,参与方更多、更复杂,优化起来难度更高。
推搜的目标基本上都是能够即时完成的,比如点击、完成播放等。而广告关注的目标是更深层次的"转化”。比如给用户展示一个电商APP的广告,只有用户点击广告、下载安装APP、 注册、成功下单后,才算一次完完整整的"转化”。广告的转化链条越长,延时反馈的问题越严重(比如用户今天下载APP,明天才下单)最后成功转化的正样本越稀疏,建模难度越高。
推广搜都要预测点击率(CTR) 转化率(CVR) 之类的指标,但对精度的要求不同。推荐与搜索对预测出来的CTR/CVR只要求相对准确性",即它们的预测精度能够将用户最喜欢的物料排在最前面,这就足够了。举例来说,如果用户喜爱A物料超过B物料,如果推荐模型给B物料的打分是0.8,那么推荐模型给A物料的打分是0.81还是0.9都不影响产生将A排在B前面的正确排序。
而广告则不同,由于预测出来的CTR/CVR要参与对广告费用的计算,误差一点都将带来真金白银的损失,因此广告对预测精度要求"绝对准确性”。在模型的预测结果出来之后,广告还需要对其修正、校准。
不过,毕竟制作、投放广告还存在一定技术、财力上的门槛,因此相比于推搜几十万、上百万的候选集合,广告的候选集就会小很多,从而能够简化过程,降低一些 系统复杂度。比如有的广告系统就忽略了粗排环节,将召回的广告直接喂入精排。