This commit is contained in:
louzefeng
2024-07-11 05:50:32 +00:00
parent bf99793fd0
commit d3828a7aee
6071 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,211 @@
<audio id="audio" title="24 | 典型的信息流架构是什么样的" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/90/15/901e6069552bdf59aff757d8f5d45415.mp3"></audio>
从今天起,我们不再单独介绍推荐算法的原理,而是开始进入一个新的模块——工程篇。
在工程实践的部分中,我首先介绍的内容是当今最热门的信息流架构。
信息流是推荐系统应用中的当红炸子鸡,它表现形式有很多:社交网络的动态信息流、新闻阅读的图文信息流、短视频信息流等等。
如果要搭建一个自己的信息流系统,它应该是怎么样的呢?今天,我就来带你一探信息流架构的究竟。
## 整体框架
信息流通常也叫作feed这个英文词也很有意思就是“喂”给用户的意思。
传统的信息流产品知识简单按照时间排序而被推荐系统接管后的信息流逐渐成为主流按照兴趣排序也叫作“兴趣feed”。
所以我们通常提到信息流或者兴趣feed其实都是在说同一个话题。
这里温馨提示一下如果要搜索feed相关的技术文章你应该用“Activity Stream”作为关键词去搜而不应该只用“feed”搜索Activity Stream之于feed就好比多潘立酮之于吗丁啉前者是行话后者是通俗说法。
要实现一个信息流,整体逻辑上是比较清楚的。可以划分为两个子问题。
1. 如何实现一个按照时间顺序排序的信息流系统?
1. 如何给信息流内容按照兴趣重排序?
我这里先给出一个整体的框架,然后再分别详谈。
<img src="https://static001.geekbang.org/resource/image/50/b2/50f449d3d62886748e79294d6c8f5db2.png" alt="" />
这张架构图划分成几个大的模块:日志收集、内容发布、机器学习、信息流服务、监控。这里分别介绍一下:
1. 日志收集,是所有排序训练的数据来源,要收集的最核心数据就是用户在信息流上产生的行为,用于机器学习更新排序模型;
1. 内容发布,就是用推或者拉的模式把信息流的内容从源头发布到受众端;
1. 机器学习,从收集的用户行为日志中训练模型,然后为每一个用户即将收到的信息流内容提供打分服务;
1. 信息流服务为信息流的展示前端提供Rest API
1. 监控,这是系统的运维标配,保证系统的安全和稳定等。
## 数据模型
信息流的基本数据有三个用户User、内容Activity和关系Connection<br />
用户不用说就是区别不同用户的身份ID我来说一说其他的两种。
### 1.内容即Activity。
用于表达Activity的元素有相应的规范叫作Atom你可以参考它并结合产品需求定义出自己的信息流数据模型来。
根据Atom规范的定义一条Activity包含的元素有Time、Actor、Verb、Object、Target、Title、Summary。下面详细解释一下这些元素。
1. Time即“Activity发生的时间”。
1. Actor即“Activity由谁发出的”。通常Actor就是用户ID但是我们也可以扩展到其他拟人化物体上如关注的一个“店铺”收藏的一部“电影”或者用户喜欢的一个标签或者分类。也就是和用户建立连接的另一端。
1. Verb动词就是连接的名字比如“Follow”“Like”等也可以是隐含的连接如挖掘出的用户兴趣词和用户之间这种潜规则。
1. Object即动作作用到最主要的对象只能有一个比如一个人赞过的一张照片店铺上新的一件商品一个分类下一篇新的文章。
1. Target动作的最终目标与verb有关可以没有。它对应英语中介词to后接的事物比如“John saved a movie to his wishlist”John保存了一部电影到清单里这里电影就是Object而清单就是Target。
1. Title这个是Activity的标题用自然语言描述用于展示给用户。
1. Summary通常是一小段HTML代码是对这个Activity的描述还可能包含类似缩略图这样的可视化元素可以理解为Activity的视图不是必须的。
举个例子: 2016年5月6日23:51:01Time@刑无刀Actor 分享了Verb 一条微博Object@极客时间 Target。把前面这句话去掉括号后的内容就是它的TitleSummary暂略。
除了上面的字段外还有一个隐藏的ID用于唯一标识一个Activity。社交电商Etsy在介绍他们的信息流系统时还创造性地给Activity增加了Owner属性同一个Activity可以属于不同的用户相当于考虑了方向。
### 2.关系即连接。
互联网产品里处处皆连接,有强有弱,好友关系、关注关系等社交是较强的连接,还有点赞、收藏、评论、浏览,这些动作都可以认为是用户和另一个对象之间建立了连接。有了连接,就有信息流的传递和发布。
定义一个连接的元素有下面几种。
1. From连接的发起方。
1. To被连接方。
1. Type/Name就是Atom模型中的Verb即连接的类型关注、加好友、点赞、浏览、评论等等。
1. Affinity连接的强弱。
如果把建立一个连接视为一个Activity模型的话From就对应Activity中的ActorTo就对应Activity中的Object。
连接的发起从From到To内容的流动从To到From。Connection和Activity是相互加强的这是蛋和鸡的关系有了Activity就会产生Connection有了Connection就可以“喂”feed给你更多的Activity。
在数据存储上可以选择的工具有下面的几种:
Activity存储可以采用MySQL、Redis、Cassandra等<br />
Connection存储可以采用MySQL<br />
User存储可以采用MySQL。
## 动态发布
用户登录或者刷新后信息流是怎么产生的呢我们把动态内容出现在受众的信息流中这个过程称为Fan-out直觉上是这样实现的
1. 获取用户所有连接的终点(如好友、关注对象、兴趣标签);
1. 获取这些连接终点关注对象产生的新内容Activity
1. 按照某个指标排序后输出。
上面这个步骤别看简单在一个小型的社交网络上通常很有效而且Twitter早期也是这么做的。这就是江湖行话说的“拉”模式Fan-out-on-load信息流是在用户登录或者刷新后实时产生的。这里有一个示意图你可以点击查看。
<img src="https://static001.geekbang.org/resource/image/d9/af/d90963931af6803bf76bbbed3daf13af.png" alt="" />
拉模式就是当用户访问时信息流服务才会去相应的发布源拉取内容到自己的feed区来这是一个阻塞同步的过程。“拉”模式的好处也显而易见主要有下面两种。
1. 实现简单直接一行SQL语句就搞定了。
1. 实时:内容产生了,受众只要刷新就看得见。
但是也有很大的不足:
1. 随着连接数的增加,这个操作的复杂度指数级增加;
1. 内存中要保留每个人产生的内容;
1. 服务很难做到高可用。
与“拉”模式对应还有一个“推”模式Fan-out-on-write。我在文稿里放了一张图你可以点击查看。
<img src="https://static001.geekbang.org/resource/image/91/dc/919f382a02ae833393adaf8cb4ecc8dc.png" alt="" />
当一个Actor产生了一条Activity后不管受众在不在线刷没刷新都会立即将这条内容推送给相应的用户即和这个Actor建立了连接的人系统为每一个用户单独开辟一个信息流存储区域用于接收推送的内容。如此一来当用户登录后系统只需要读取他自己的信息流即可。
“推”模式的好处显而易见:在用户访问自己的信息流时,几乎没有任何复杂的查询操作,所以服务可用性较高。
“推”模式也有一些不足。
1. 大量的写操作:每一个粉丝都要写一次。
1. 大量的冗余存储每一条内容都要存储N份受众数量
1. 非实时:一条内容产生后,有一定的延迟才会到达受众信息流中。
1. 无法解决新用户的信息流产生问题。
既然两者各有优劣,那么实际上就应该将两者结合起来,一种简单的结合方案是全局的:
1. 对于活跃度高的用户,使用推模式,每次他们刷新时不用等待太久,而且内容页相对多一些;
1. 对于活跃度没有那么高的用户,使用拉模式,当他们登录时才拉取最新的内容;
1. 对于热门的内容生产者缓存其最新的N条内容用于不同场景下的拉取。
还有一种结合方案是分用户的这是Etsy的设计方案
1. 如果受众用户与内容产生用户之间的亲密度高,则优先推送,因为更可能被这个受众所感兴趣;
1. 如果受众用户与内容产生用户之间的亲密度低,则推迟推送或者不推送;
1. 也不是完全遵循亲密度顺序,而是采用与之相关的概率。
在中小型的社交网络上,采用纯推模式就够用了,结合的方案可以等业务发展到一定规模后再考虑。
对于信息流的产生和存储可以选择的工具有:
- 用户信息流的存储可以采用Redis等KV数据库, 使用uid作为key。
- 信息流推送的任务队列可以采用Celery等成熟框架。
## 信息流排序
信息流的排序,要避免陷入两个误区:
1. 没有目标;
1. 人工量化。
第一个误区“没有目标”意思就是说,设计排序算法之前,一定要先弄清楚为什么要对时间序重排?希望达到什么目标?只有先确定目标,才能检验和优化算法。
第二个误区是“人工量化”,也就是我们通常见到的产品同学或者运营同学要求对某个因素加权、降权。这样做很不明智,主要是不能很好地持续优化。
目前信息流采用机器学习排序,以提升类似互动率,停留时长等指标,这已经成为共识。比如说提高互动率则需要下面几个内容。
<li>
首先,定义好互动行为包括哪些,比如点赞、转发、评论、查看详情等;
</li>
<li>
其次,区分好正向互动和负向互动,比如隐藏某条内容、点击不感兴趣等是负向的互动。
</li>
基本上到这里就可以设计成一个典型的二分类监督学习问题了,对一条信息流的内容,在展示给用户之前,预测其获得用户正向互动的概率,概率就可以作为兴趣排序分数输出。
能产生概率输出的二分类算法都可以用在这里,比如贝叶斯、最大熵、逻辑回归等。
互联网常用的是逻辑回归Logistic Regression谁用谁知道用过的都说好也有Facebook等大厂采用了逻辑回归加梯度提升树模型又称GBDT来对信息流排序效果显著。
如今大厂都已经转向深度学习了,但我还是建议小厂或者刚起步的信息流先采用线性模型。
对于线性模型,一个重要的工作就是特征工程。信息流的特征有三类:
1. 用户特征,包括用户人口统计学属性、用户兴趣标签、活跃程度等;
1. 内容特征,一条内容本身可以根据其属性提取文本、图像、音频等特征,并且可以利用主题模型提取更抽象的特征。
1. 其他特征,比如刷新时间、所处页面等。
排序模型在实际使用时通常做成RPC服务以供发布信息流时调用。
## 数据管道
信息流是一个数据驱动的系统,既要通过历史数据来寻找算法的最优参数,又要通过新的数据验证排序效果,所以搭建一个数据流管道就是大家翘首期盼的。
这个管道中要使用的相关数据可能有:
1. 互动行为数据,用于记录每一个用户在信息流上的反馈行为;
1. 曝光内容每一条曝光要有唯一的ID曝光的内容仅记录ID即可
1. 互动行为与曝光的映射关系,每条互动数据要对应到一条曝光数据;
1. 用户画像内容即用户画像提供用户特征具体请见我在第4、5、6三篇中的内容
1. 信息流的内容分析数据,提供内容特征,即物品画像。
对于一个从零开始的信息流,没必要做到在线实时更新排序算法的参数,所以数据的管道可以分成三块:
1. 生成训练样本,可离线;
1. 排序模型训练,可离线;
1. 模型服务化,实时服务;
像Pinterest早期的管道也差不多就是这样。
在离线训练优化模型时关注模型的AUC是否有提升线上AB测试时关注具体的产品目标是否有提升比如互动率等同时还要根据产品具体形态关注一些辅助指标。
另外,互动数据相比全部曝光数据,数量会小得多,所以在生成训练数据时需要对负样本(展示了却没有产生互动的样本)进行采样,采样比例也是一个可以优化的参数。
固定算法和特征后在0.1~0.9之间遍历对比实验选择最佳的正负比例即可。经验比例在2:3左右即负样本略大于正样本你可以用这个比例做启发式搜索。
## 总结
今天我逐一梳理了实现一个通用信息流的关键模块,及其已有的轮子,从而能最大限度地降低开发成本。
这些对于一个中小型的社交网络来说已经足够,当你面临更大的社交网络,会有更多复杂的情况出现,尤其是系统上的。
所以,壮士,请好自为之,时刻观察系统的监控、日志的规模。
你在了解了典型的信息流架构之后可以说一说Facebook这样的社交网络feed和头条这样的资讯信息流之间的差别和共同点吗欢迎给我留言。
<img src="https://static001.geekbang.org/resource/image/87/b0/873b086966136189db14874181823fb0.jpg" alt="" />

View File

@@ -0,0 +1,176 @@
<audio id="audio" title="25 | Netflix个性化推荐架构" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/77/13/77437303cc652c9b6f6feeaf1339a013.mp3"></audio>
你是否常常被乱花渐欲迷人眼的推荐算法绕得如坠云中,觉得好像算法就是推荐系统的全部,哪怕就算不是全部,也肯定至少是个嫡生的长子。
然而,实际上工程实现才是推荐系统的骨架,如果没有很好的软件实现,算法不能落地产生效果,产品不能顺畅地服务用户,不能顺利地收集到用户的反馈,更不能让推荐系统往更好的方向进化。
一个好的推荐系统不仅仅是在线下模型评测指标多么好,也不仅仅是在某个时刻像是灵光乍现一样击中了用户某个口味,而是随着用户的不断使用,产品和用户一起变好,产品背后的人得到进步,用户也越来越喜欢产品。
虽然影响是否用户产品的因素有很多很多,但是能否流畅地给用户提供服务是一个最基本的标准。
## 架构的重要性
推荐系统向来是一个锦上添花的东西,因此传统的观点是推荐系统更加注重线下的模型效果,而非线上的服务质量。但是你也知道,时至今日,推荐系统不再只是锦上添花,而是承担了产品的核心功能。因此,对推荐系统架构的要求也高了很多。
一个好的推荐系统架构应该具有这些特质:
1. 实时响应请求;
1. 及时、准确、全面记录用户反馈;
1. 可以优雅降级;
1. 快速实验多种策略。
上一篇专栏文章介绍的是当下最热门的推荐系统产品形式——信息流的架构信息流并不是传统意义上的推荐系统今天我要介绍一种更符合经典推荐系统的架构这就是著名的流媒体Netflix的推荐系统架构。
通过这篇文章,我会为你介绍,实现一个简化版的推荐系统架构应该至少包含哪些元素,同时,我会带你一起总结出,一个经典推荐系统架构应该有的样子。
## 经典架构
好了废话少说我先上图。下面这张图就是Netflix的推荐系统架构图。
<img src="https://static001.geekbang.org/resource/image/a8/b4/a81afe3013542c6b22617ea56c025bb4.png" alt="" />
我先整体看一下这个架构,一共分成三层:在线、近线、离线。
你是不是也发现似乎有一个不太熟识的词出现:近线。对,这个近线是通常不太提的一个概念,或者通常就把它归入了在线的范畴。
实际上,可以这样定义这三个层级:
1. 离线:不用实时数据,不提供实时服务;
1. 近线:使用实时数据,不保证实时服务;
1. 在线:使用实时数据,要保证实时服务。
在具体介绍这些内容之前,我先来说说数据流的情况。
### 1.数据流
用户在产品UI上使用产品消费展示的内容产生行为事件数据实时地被收集走一边进入分布式的文件系统中存储供离线阶段使用另一边流向近线层的消息队列供近线阶段的流计算使用。
离线存储的全量数据被抽取出来,组成离线计算所需的训练数据,这些训练数据被一个管理数据生成和发布的组件统一管理,要使用数据的下游,比如模型训练会在离线数据生成时得到这个组件的通知,从而开始训练,训练得到的模型用于进一步为用户计算推荐结果。
离线阶段的推荐结果或者模型在近线阶段被更新,进一步在在线阶段被直接使用,产生最终的推荐结果,呈现给用户。
这是整个数据流情况。下面我一一详细介绍每个部分。
### 2.在线层
在线层的触发时机是当用户发出请求,也就是用户进入一个推荐场景,推荐位等着展示推荐结果时,这个时候需要承担责任就是在线层。在线层就是实时响应用户请求。简单说,在线层的特点就是“使用实时数据,要保证实时服务”。
在线层的优势有:
1. 直接首次接触到大多数最新数据;
1. 对用户请求时的上下文了如指掌;
1. 只需计算必须的信息,不需要考虑所有的信息。
在线层也有严格的制约:
1. 严格的服务响应时间,不能超时,或者让用户等太久;
1. 服务要保证可用性,稳定性;
1. 传输的数据有限。
在线层常常展现出的形式就是Rest API形式后端则通常是RPC服务内部互相调用以用户ID、场景信息去请求通常就在ms响应时间内返回Json形式的推荐结果。那么哪些计算逻辑适合放在在线层呢
1. 简单的算法逻辑;
1. 模型的预测阶段;
1. 商业目标相关的过滤或者调权逻辑;
1. 场景有关的一些逻辑;
1. 互动性强的一些算法。
在线阶段要处理的对象一般是已经预处理后的推荐结果,是少量物品集合。
比如说当用户访问一个物品详情页需要做相关推荐那么在线阶段给在线服务的Rest API传入用户身份以及当前的物品ID实时地取出物品ID对应的相关物品ID再根据用户信息对这些物品ID做一些重排和过滤就可以输出了整个过程都是在ms级别完成。
这个实时响应的过程中如果发生意外比如说这个物品ID就没有相关的物品那么这时候服务就需要降级所谓的降级就是不能达到最好的效果了但是不能低于最低要求这里的最低要求就是必须要返回东西不能开天窗。
于是,这就降级为取出热门排行榜返回。虽然不是个性化的相关结果,但是总比开天窗要好。这就是服务的可用性。
在线阶段还要实时地分发用户事件数据,就是当用户不断使用产品过程产生的行为数据,需要实时地上报给有关模块。这一部分也是需要实时的,比如用于防重复推荐的过滤。
### 3.离线层
讲完在线层,再来看看离线层。离线层就是躲在推荐系统的大后方,批量、周期性地执行一些计算任务。其特点是“不用实时数据,不提供实时服务”。
离线层的示意图如下:
<img src="https://static001.geekbang.org/resource/image/0c/a9/0c1c5458053a7e3481fb90db003065a9.png" alt="" />
离线阶段主要面对的数据源就是Hadoop实质上是HDFS。收集到的所有日志都存在这里面是一个全量的数据中心。
通过Pig或者Hive等工具从全量日志中按照算法要求抽取出不同的数据再加上其他数据变成了不同算法所需的数据源。
如果这种数据源比较多时,就需要有专门的工具统一管理起来,这个管理上要求:
1. 数据准备好之后及时通知相关方,也就是要有订阅发布的模式;
1. 能够满足下游不同的存储系统;
1. 完整的监控体系,并且监控过程对于数据使用方是透明的。
在Netflix内部承担这个管理任务的工具叫做Hermes类似Kafka但是又有不同的内部工具。
离线阶段的任务主要是两类:模型训练和推荐结果计算。
通常机器学习类模型,尤其是监督学习和非监督学习,都需要大量的数据和多次迭代,这类型的模型训练任务最适合放在离线阶段。
举个例子,你已经知道推荐系统中会有召回和融合排序这两个阶段。通常一些推荐算法,例如协同过滤就是在离线阶段计算出每个人的推荐结果,作为线上融合排序的候选集之一,也就是示意图中的“推荐结果”。
另一方面,假如融合排序模型时逻辑回归,那么逻辑回归模型的参数也通常在离线阶段就训练完成的,在线阶段也只是取出来参数用于计算而已。
离线阶段有以下这么几个好处:
1. 可以处理最大的数据量;
1. 可进行批量处理和计算;
1. 不用有响应时间等要求。
当然坏处也是明显的:
1. 无法及时响应前端需求;
1. 面对的数据较静态,无法及时反应用户的兴趣变化。
大多数推荐算法实际上都是在离线阶段产生推荐结果的。离线阶段的推荐计算和模型训练如果要用分布式框架通常可以选择Spark等。
### 4.近线层
最后,我来讲讲近线层。近线层的特点是“使用实时数据,不保证实时服务”,这实在是一个很不讲道理的计算层,因为把它的特点翻译得直白点就是:喂给我最新鲜的牧草,但是我不保证能马上给你挤奶。
虽然这看上去蛮不讲理,但实际上这是一个非常重要的一层,它结合了离线层和在线层的好处,摒弃了两者的不足。
近线层,也叫做准实时层,所谓“准实时”,就是接近实时,但不是真的实时。
从前面的架构图中也可以看出,这一层的数据来源是实时的行为事件队列,但是计算的结果并不是沿着输入数据的方向原路返回,而是进入了在线数据库中,得到用户真正发起请求时,再提供服务。
一个典型的近线计算任务是这样的:从事件队列中获取最新的一个或少许几个用户反馈行为,首先将这些用户已经反馈过的物品从离线推荐结果中剔除,进一步,用这几个反馈行为作为样本,以小批量梯度下降的优化方法去更新融合模型的参数。
这两个计算任务都不会也不需要立即对用户做出响应,也不必须在下一次用户请求时就产生效果,就是说当用户实时请求时,不需要去等待近线任务的最新结果,因为两者是异步的。
近线计算任务一个核心的组件就是流计算因为它要处理的实时数据流。常用的流计算框架有StormSpark StreamingFLink等Netflix采用的内部流计算框架Manhattan这和Storm类似。
略有区别的是Spark Streaming实际上并不是实时流计算而是小批量计算。
## 简化架构
Netflix是为全球多个国家同时提供在线服务的因此推荐系统的架构略微复杂。倘若你现在刚刚接手一个新产品要从0开始搭建一个推荐系统那么可以以Netflix的架构作为蓝本做一定的简化。
<img src="https://static001.geekbang.org/resource/image/41/ad/41e435ba13a8078314be8d24da74f2ad.png" alt="" />
关键简化有两点:
1. 完全舍弃掉近线层;
1. 避免使用分布式系统。
其中第二点,在一个新产品的场景下, 当数据量还没有那么大时,使用分布式存储或者计算框架,非常不划算。
如果性能不足请升级单机配置。根据经验一个几千万用户几十万到百万的物品的协同过滤或者矩阵分解如果充分发挥单机的性能综合效率会远远优于在Spark上运行。
另外在一个推荐系统刚从0开始的阶段离线阶段的算法也没有那么多很多情况甚至都只有协同过滤结果这时候线上融合模型也不必那么复杂一个简单的加权融合就可以了因此在线层也不必复杂。
## 总结
今天我以Netflix架构为原型向你介绍了一个经典的推荐系统架构长什么样子。关于这个架构你只需要记住一点它有三层三层分别是离线近线在线。
我用如下的表格将这三层综合对比,并且简单举例,我们看看每一层分别放哪些任务。
<img src="https://static001.geekbang.org/resource/image/5a/20/5aa4a361a2f0c480a15608e205553120.png" alt="" />
以上就是对这个架构的宏观总结对比。如前所说,其实架构都是进化出来的,你千万不必在一开始就追求完美的架构,满足最低要求就好。
针对这个架构提一个问题前面讲到的Bandit算法你觉得应该在哪一层比较好呢欢迎留言讨论。
<img src="https://static001.geekbang.org/resource/image/87/b0/873b086966136189db14874181823fb0.jpg" alt="" />

View File

@@ -0,0 +1,115 @@
<audio id="audio" title="26 | 总览推荐架构和搜索、广告的关系" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/fd/58/fd58a405d169f71ad71323579ad25758.mp3"></audio>
在数字世界中,信息过载是必然的,应对信息过载重担先后交给了两种主要形式,包括以搜索为代表的各种主动寻找信息的形式,以及以推荐为代表的各种被动接受信息的形式。
## 三种信息获取方式
当用户想要从浩如烟海的网页中,找到对自己有用的信息,首选当然是搜索引擎,这是属于“已知的未知”需求,剩下的“未知的已知”和“未知的未知”则需要推荐系统去满足,只是推荐系统常常会出现画蛇添足去满足“已知的已知”这样的伪需求。
另外介于两者之间,还有一种商业化解决信息触达问题,就是广告系统。在线广告从条幅广告,到搜索广告再到社交精准广告,也逐渐形成了一个理念就是:把广告当成一种有用的信息去找到最需要它的人。
三者都是解决信息过滤问题的,那么它们有没有一些共同之处呢?答案是肯定的,这三者的确有共同之处,但是也有不同之处。
## 三者对比
搜索,推荐和广告本质上都在解决信息过载的问题,各自解决的手段、目标不相同,各自诞生在产品生命周期不同阶段,以至于系统实现也不尽相同。
我们从几个维度对比一下,看看它们不同和相同在哪。
<img src="https://static001.geekbang.org/resource/image/1f/80/1f4f3b2c917149d8e1ff62e246872480.png" alt="" />
搜索更关注内容消费者,搜索要解决的是精确快速找到想要的结果,最重要的目标是降低延迟和提高相关性。搜索引擎是一个效率工具,希望用户找到信息越快越好,而不是希望用户沉迷在搜索引擎中。
所以搜索一般不会像信息流产品那样变成时间杀手,不过现在有些搜索引擎会主推信息流,这个另当别论。
人们需要依赖搜索而不沉迷搜索,这就与搜索引擎的目标有关。在搜索解决用户的信息获取需求时,惊喜并不在考虑范围内,因此就不会随随便便地利用集体智慧去扩充一些不那么直接相关的结果。
推荐系统则不同,首先传统的推荐系统大都是起一个“锦上添花”的作用,一般很少会将其作为核心功能来承载产品。
由于推荐系统通常的目标不是帮用户找到相关内容,而是希望用户消费内容,消费越多越好,于是业界逐渐演变出一个比较畸形的认识,“好的推荐系统应该变成一个时间杀手,让用户走进去就不想出来”才是最好的。
推荐系统不同于搜索引擎,用户使用搜索时目标明确,而使用推荐系统往往总会漫无目的,这样一来,在推荐结果中就有很多发挥的余地,可以给用户制造一些惊喜,或者让推荐结果呈现多样性,这一点和搜索很不一样。
另外,搜索是针对个人用户的,一个用户发起一个请求,而推荐系统既可能针对单个用户进行推荐,也可能针对用户群进行推荐。
推荐和搜索除了这些不同,还有更多的是相同点。基于内容的推荐,本质上就是一个小的搜索引擎。
实际上很多推荐引擎底层的技术实现,尤其是数据存储上大量借鉴了搜索相关技术,比如使用用户的兴趣标签召回推荐结果,就需要先对推荐候选池按照兴趣标签建立倒排索引,从而检索出候选集。
最后,广告是一个很特殊的存在,前面也说了,搜索和推荐都是为人找信息,而广告是为信息找人。但它在形式上又像推荐,总是“不请自来”,在技术实现上又兼有推荐和搜索两者特点。
而且它背后包含的是纯粹的商业目标,说白了就是和广告的计费方式有关,如果按照展现次数计费,系统就是要多做展现。
如果按照点击付费,那么就是想办法消耗光广告主的充值,所以广告系统关注的是商业利益最大化,精准和相关都不是终极目的,只是其中的一个手段。
## 架构抽象
我们抽象一下三者的需求共性本质上都是在匹配匹配用户的兴趣和需求看成context但匹配的目标条件和策略不尽相同。示意图如下
<img src="https://static001.geekbang.org/resource/image/17/4e/17657b2b5f2313260e0f1371db1c664e.png" alt="" />
我们再进一步抽象下去,又可以分为三步:过滤候选、排序候选、个性化输出。
### 1.过滤候选
过滤候选这一步在搜索里天经地义,从查询关键字中解析得到查询意图,以及结构化的搜索条件,再用结构化的查询条件从倒排索引中检索出排序候选。
与之相似的是广告系统,搜索广告也是查询关键字去检索候选广告,而联盟广告则是拿着用户标签去需求方获取广告候选。
在推荐系统中,我之前一再强调有挖掘、召回和排序三个阶段,其中的召回阶段就是过滤候选阶段,基于内容的就和搜索一样,用标签检索候选,协同过滤则检索出相似物品来,等等。
一种离线阶段的推荐算法对应一种召回策略,为了保证高效地召回,都要建立相应的索引,这样一来,是不是搜索、广告和推荐都离不开过滤候选这一步,而过滤候选就离不开建立索引。
事实上,如果你的产品已有搜索,要增加推荐功能,最快的实现方式的确就是在已有搜索的基础上开发。
比如你已经有了ElasticSearch搭建的搜索引擎那么在后面开发推荐系统时完全可以把ElasticSearch作为管理各种推荐结果的数据库来使用。在ElasticSearch中按照不同方式建立索引再于在线阶段根据条件检索出来重新融合排序输出。
### 2.排序候选
候选排序这一步对于三者来说主要区别在于排序的目标和约束。搜索的排序目标是高相关性无论BM25为代表的传统排序模型还是以Learn to Rank为代表的机器学习排序皆是如此把用户每次在搜索上花费的时间是不是更少而不是更多来衡量搜索的效果。
推荐系统的排序则比较复杂,根据推荐系统不同的产品形式、产品目标,排序策略也不同。
前面讲过通常推荐系统用CTR预估来融合召回策略得到的候选集如果做得深入还需要考虑探索利用问题。附加的约束则是千变万化。电商中当天买过的当天就不能再推了新闻推荐里重复的新闻不能再推了。
某些场景需要推荐搭配某些场景需要推荐相似TopN 推荐还需要考虑多样性,序列推荐要考虑前序和后续等等。
广告系统的排序更多是从经济学角度去看CPC广告的排序方式是结合预估CTR、出价、广告质量三者一起考虑。同时还要考虑很多别的因素尤其是商业因素平台方的要求广告主的要求等等是一个纯动态的博弈。
### 3.个性化输出
个性化最被推荐系统所看重,而且在某些场合,个性化一度成为推荐系统的代名词,然而个性化只是推荐系统的衡量指标之一而已,个性化的前提也一定是信息够丰富够垂直才行。
搜索的个性化需求相对来说松弛一些,常见的是利用地域等人口统计学体现个性化,而且对于歧义较少的查询关键字,搜索如果太个性化既没意义又有风险。
### 4.三者的协同
搜索、推荐、广告三者业务和技术上已经有很多重叠,也能够产生很多协同作用。
有一部分搜索需求是无法用搜索相关性满足的比如“一个人的夜晚听什么歌”这样的query这就需要推荐系统去满足交互形式可能是眼下大热的聊天机器人也可能是流推荐等等。
如果能够识别出这样的搜索请求,其实更应该交给推荐系统来响应,这类是看似搜索请求,实际上则是漫无目的。
推荐系统总体上滞后于用户的即时需求,再强大的推荐系统,也要有搜索引擎来与之配合。
一方面,搜索因为能够满足用户的主动寻找需求,所以能够化解一些推荐不力不及时的尴尬。
另一方面,搜索可以积累用户兴趣数据;当二者结合起来考虑时,可以避免“搜什么推什么”的窘境,整个系统能够综合考虑哪些是即时快速需求,哪些是长期兴趣。
广告系统,在技术上和搜索跟推荐并无本质差异,差异在意图不同,功能不同。对用户的信息需求满足,搜索和推荐离真正得到满足之间总是有一定的鸿沟,要么是信息不足,要么是信息过载,这些鸿沟可以利用经济手段进行调配,这就是广告系统。
## 总结
总结一下,今天我们提到了推荐架构和搜索、广告的关系,并将三者分别作了对比。最后,我还分别抽象了三者的架构。
以上分析只是基于纯粹技术和业务角度作的简单分析,不过几乎所有人都觉得这个提法是意料之中,大家承认三者有统一的概念基础,对此亦有共识,但是我们在实现时还需要考虑一些困难,毕竟仅有少数公司有统一架构的成功案例。
实际上这三者有统一的可能性而且不低。如果要统一从0就应该开始这其实更适合创业公司或中小公司。
由于人的因素很重,所以从一开始就应该把三者划归一个团队来统一规划,在人员配置上做到技术上统一,业务上分开。并且还要知道必须用数据去证明:统一之后比统一之前好,而不是工程师自己“感觉不错”,这个“好”可以体现在实际上的业务指标提升,也可以体现在开发效率提升。
最后,说一个很有意思的现象,搜索和推荐的信息对象理论上可以共用的,也就是说可以允许用户设置条件检索一堆候选对象,也可以把这些候选对象主动推荐到可能感兴趣的用户面前。
但是广告的信息对象却是另一个隔离的存在,为什么不能让用户直接设置条件检索我们的广告库存呢,就像是一个通常的搜索引擎一样,也许是可能的。这个问题你怎么看?你可以给我留言,我们一起讨论。
感谢你的收听,我们下期再见。