目录
主要是包含搜推广系统的基本模块简单介绍,另有一些流程、设计思想的分析。
- 搜索引擎
- 基本模块
- 检索流程
- 查询分析
- 查询纠错
- 广告引擎
- 基于标签倒排索引召回
- 基于向量ANN检索召回
- 打分机制:非精确打分+精准深度学习模型打分
- 索引精简:必要的数据构建索引
- 推荐引擎
- 基本模块
- 基于内容的召回
- 基于协同过滤的召回
- 基于用户的协同过滤
- 基于物品的协同过滤
- 混合召回+分层打分
搜索引擎
搜索引擎的任务是从万亿级别的网页快速查找需要信息,搜索引擎的检索技术是所有基于文本和关键词的检索系统都是可以学习和参考的。
整个检索系统会设计很多技术,比较重要的有网页抓取、文本分析、检索模型、索引技术、链接分析、反作弊、云存储和云计算等,非常复杂。
基本模块
整个检索系统可以按照功能结构分为3部分,分别是爬虫系统、索引系统、检索系统。
- 爬虫系统:要求能高效爬取数据,并选用高效的存储,如基于LSM的HBase高效的进行写入和读取。
- 索引系统:为相关文档建立索引,主要包含3个阶段,
- 1是文档的预处理,包括相似网页去重、网页质量分析、分词处理这些工作。
- 2是对文档进行反作弊的处理,来避免一些作弊网页干扰搜索结果。
- 3是生成索引,生成过程包含三个步骤:索引拆分、索引构建、索引更新
- 索引拆分:文档数据量很大,全部生成索引不太现实,可以根据离线阶段的文档预处理,区分文档质量,比如高质量和低质量,采用分层思想建立索引,另外尽管区分高低质量数据量比较还是比较大需要索引分片。
- 索引构建:确认了索引的分片机制之后,可以使用Map Reduce服务,为每个索引分片生成对应的任务,然后生成相应的倒排索引文件,每个倒排索引代表一个分片,支持加载到线上服务器。
- 索引更新:全量索引结合增量索引的机制完成索引更新,一般使用滚动合并法更新。
- 检索系统:查询分析、查询纠错、查询推荐、召回、打分选取TopK。
检索流程
查询分析
查询词是搜索引擎进行检索的最核心的信息,但是有时候关键词会有错别字,或者是含糊的不精准的,或者查询的关键词不在建立的索引中,如何保证能较准确的检索?
查询分析就是通过输入的查询词理解用户意图,进行查询词纠正,以及对查询意图不明的查询词进行查询推荐,可以分为三个粒度的分析
- 分词粒度分析:最基础的查询分析,根据查询词按照不同的粒度分词,影响跟索引key匹配的效果,中文搜索中特有的一个环节。一般采用混合粒度分词,也就是标准的分词 + 整个查询词短语 来取匹配索引中的key,比如疾风亦有归途,会被分词 [疾风、归途、疾风亦有归途]
- 属性分析:数据的某些属性、权重
- 需求分析:语意级别的意图分析等
关键词位置信息关联性窗口
思考:中文短语是如何检索的?比如查询 “疾风亦有归途”,在构建倒排索引的时候并没有把这个词当作key,直接搜索倒排索引的时候就会找不到,按照混合分词粒度,会接着按照 [疾风,归途] 检索,如果只是简单地将这两个关键词检索出来的文档列表求交集合并,那我们最终得到的结果并不一定会包含带有"疾风亦有归途"的文档,比如搜索到了"xxxx疾风来了,xxxx很多字xxxx,归途",这种并不是期望的结果。
一种解决方案就是记录 关键词出现在文档中的位置,取交集的时候判断一下两个关键词在同一个文档中的距离,距离越小相关性就越小。比如就像包含两个关键词的内容划进去一个窗口,窗口越小,那么证明越相关。
思考:如果是一个查询词被分为了三个关键词?多个关键词,使用查询窗口如何保证顺序?
一种解决方案是两两进行多次计算,最后累加得到一个值。
查询纠错
查询词有错别字,使用查询纠错以及查询推荐优化搜索结果集,查询纠错一般分为三个步骤
- 错误判断,主要有下面两种方式
- 基于规则的错误判断:一般根据人工打标的或者搜索日志进行数据挖掘,得到常见的字典和混淆字典,字典的结构可以是哈希表、前缀树等结构保证高效率检索。按照分词结果,如果无法在字典查到,或者出现在混淆字典里面,那么就认为这个查询词是错误的,需要进行下面的步骤。
- 基于机器学习和语言模型的错误判断,给查询的词一个上下文置信度,置信度低的话判断为错误,需要进行下面的步骤。
- 候选召回:得到纠错集合,中文的错误一般两种,同音、形近,根据多个同音、形近字典找出多个匹配的key,查询返回候选集合。还有方式是根据编辑距离、根据机器学习等找出候选集的。
- 打分排序
广告引擎
广告系统是一个典型的高并发低延迟系统,请求量大,对工程和算法有着强烈的依赖,需要做到千人千面。广告系统中负责检索功能的广告引擎架构。
广告引擎处理一个广告请求的过程,本质上就是根据用户的广告请求信息,找出标签匹配的广告设置,并将广告进行排序返回的过程。
广告基本可以分为两类,搜索类广告、展示类广告
- 搜索类广告:和搜索词关联性比较紧密,类似上面的搜索
- 展示类广告:请求主要包含手机用户标签,标签和广告匹配,然后投放推送广告。
以展示类广告为例,用户访问网页的时候,这个时候期望在网页推送广告,从用户访问的请求信息能拿到用户ID、网站地址、广告位置ID等,接着广告系统服务端利用之前收集的用户信息标签(喜好、年龄等),从提前分析构建好的标签-具体广告信息设置key-value索引查出相应的广告,然后排序返回,之后就是监测广告的效果如展示、点击等埋点。
基本的流程和上面搜素引擎流程类似,包含构建索引、召回候选集、排序返回TopK,不同的是广告(展示类)没有关键词限制,因此在构建倒排索引上,更加灵活。
基于标签倒排索引召回
按照标签-广告文档构建倒排索引,如某个广告设置的标签是 “地区:开封”,“年龄:25-30”,“性别:男” 这些,那么key就可以为每个标签项设置一个32为ID,前xxx位表示标签名称(定向类型),后xxx为表示标签具体值,这样上面的三个标签以及值分别对应3个32位的ID,可以用作倒排索引的key。
思考:所有的标签(定向类型)都作为key放入倒排索引吗?
这样做会有个问题,就是对于那些区分度不高的标签,往往倒排索引挂的posting list都是很长的,这样多个posting list取交集的时候效率会比较低。
因此一种解决方案是使用TF-IDF(词频逆文档频率)中计算IDF的方式,找出区分度比较低的标签,不将他们加入到倒排索引,而是将这些标签以及下面的广告单独列表存储,在倒排索引求完差集之后,在使用这个 “过滤列表” 对检索结果进行结果过滤。
思考:标签太多归并的效率低?
按照上面的策略,当前倒排索引key是区分度比较大的标签,比如需要推送 “媒体类型:APP” 和 “媒体类型:PC” 两种标签下的广告,并且这两种标签下的广告基本占了全部广告,此时如果想要推送两种标签的广告,归并的效率不是很高。
因此考虑到方案做一个标签树的结构,将树的子节点是哪些具有少量广告的标签,进一步划分父节点标签的广告集,从而进行倒排索引分片。
下面就是 树 + 倒排索引 的结构,我们根据广告请求上的标签,就能快速定位要找的索引分片,之后,再查分片中的倒排索引就能缩小候选集。
思考:如果使用"媒体类型"作为树形检索的节点,"PC网站"和"APP"作为两个分叉,并且允许广告主选择 “既在PC网站投放,又在APP上投放”,如果少量的广告主使用这种投放,索引分片应该如何调整?
不变的策略,每次都需要归并排序求交集。
或者是单独创建一个分片,把归并的数据存起来,不用每次时时归并。
基于向量ANN检索召回
使用广告引擎摆脱传统的标签模式,可以将广告标识转为向量,同时把用户兴趣也转化为一个向量,这样使用ANN紧邻搜索找到最近的点当作结果返回就可以了。
对于传统标签模式,是不具有语义上下文的,比如 标签为 “喜欢篮球的人” 时,如果一个用户身上的标签只有 “喜欢运动” ,那这个广告不会投放给这个用户,会漏掉一些数据,对于向量的ANN,能弥补这个问题。
向量检索同时也会带来性能的压力,可以使用聚类(用于缩小候选集合,减少计算量) + 倒排索引 + 乘积量化(用于压缩存储空间) 的实现方案优化向量检索的效率
参考往期博客:ElasticSearch学习篇17_《检索技术核心20讲》最邻近检索-局部敏感哈希、乘积量化PQ思路-CSDN博客
打分机制:非精准打分 + 精准的深度学习模型打分
相比于搜索引擎期望最后的TopK结果,区别就是广告引擎期望最后的结果一条最相关的即可,因此对于广告引擎的打分机制,我们会使用复杂的深度学习模型来打分。
往往深度学习模型的任务会比较耗时,而广告引擎又要求很高的性能,因此打分之前的候选集不能太大,为了解决这个问题,使用非精准打分 + 深度学习模型精确打分机制进行打分,合理的使用资源。
具体来说,可以基于简单的机器学习模型(如逻辑回归LR,梯度提升决策树GBDT,因子分解机FM等)配合少量的特征,完成这个非精准打分环节,将候选广告的数量限制在几十的量级,然后在使用深度学习模型来进行精准打分,最后选出分数最高的广告。
索引精简:必要的数据构建索引
一般某个广告的生命周期变化非常快,比如广告会设置限定投放的时间段,所以相比于搜索引擎的数据,往往变化更快。
因此除了在线的召回、打分环节的检索效率之外,广告业务的特点使得我们可以在离线的索引构建环节,通过精简索引来优化效率,比如将所有的广告(不考虑时效性)全部都加载到系统中进行检索,然后后面再来一遍遍历过滤判断,就会带来大量的判断开销。
因此一种解决思路就是把在线的开销挪到离线的索引构建环节,这些过滤条件和广告定向类型(标签)并没有联系,完全可以先把不相关的广告不构建索引,这样在线召回、打分的候选集就会减少。
比如下面的经过一系列过滤条件,最下层的索引是需要当前用到的,这个过程是在离线环节完成的。
这种机制的前提是广告引擎需要提供实时高效的索引更新能力,广告投放的数量不想搜索引擎网页数量那个量级,一般可以全部加载到内存,一般使用全量索引结合增量索引的更新机制,就可以对线上的索引进行实时的更新了。
推荐引擎
不同于搜索、广告系统,可以依靠关键词、广告主创建检索约束条件,推荐系统的外界约束条件非常少,比如只有一个下拉刷新的动作,因此搜索引擎的灵活程度更高。
基本模块
- 用户画像:离线挖掘用户的兴趣标签,生成完整的用户画像,不通的标签有不同的权重,所有的权重会随着时间的变化衰减,比如用户长时间没有这个行为,标签就会逐渐弱化。
- 文章画像:给文章打标签,除了提取文章的关键词,还需要对文章的语义内容做分析,比如文章分类、主题提取等
- 推荐算法:主要的算法基本为两类,分别是基于统计的静态召回算法和个性化召回算法。
- 基于统计的静态召回算法:比如热文推荐,根据离线对文章的统计数据来进行推荐,比如点击两、评论、收藏、收藏率等,然后在线环节推给用户,比较适合个性化召回算法结果不足时候的补充数据。
- 个性化召回算法:分为基于内容的召回、基于协同过滤的召回。
基于内容的召回
判断文章内容是否符合用户画像,主要就是对比标签了,参考广告引擎的基于标签倒排索引召回。
另外就是使用向量ANN将标签匹配改为高纬向量空间的最近邻检索,弥补标签匹配检索可能漏掉数据的问题。
优缺点
基于协同过滤的召回
协同过滤是推荐系统中代表性方法,协同过滤和基于内容的召回方法最大的区别就是不依赖内容本身来进行推荐,而是基于大众用户和这篇文章的互动关系来推荐。
分为两大类
- 传统的基于数据统计的“Memory-based 的协同过滤算法”,也叫做基于邻域的算法,代表算法有基于用户的、基于物品的协同过滤。
- 基于模型的 “Model-based的协同过滤算法”
基于用户的协同过滤
简单来说就是给用户A推送相似用户B的内容。
举个例子比如将用户A画像相似的用户B看过的文章也推荐给用户A,主要操作是找到和用户A 画像相似的B、C、D、E等,找出他们阅读的文章集合TopK推送给用户A。
具体的流程
- 对于寻找画像相似的用户集合,可以将画像的各个标签值转为向量,然后ANN搜索,或者计算余弦相似度。
- 然后从相似画像用户集合找出具体的文章,然后按照用户喜欢的程度(点赞、收藏、评论等)加权计算找出TopK然后在推送。
问题:计算找出画像相似用户会非常耗时,如何解决?
推荐系统有两种方案
- 相似计算放在离线环节:离线为每个用户计算出一个推荐文章列表,然后使用key-value数据库快速查询,优点是比较简单效率比较高,缺点是更新不够及时。
- 实时阶段使用向量检索来近似地完成更新:第一步寻找相似用户的时候先非精确检索,借助 聚类 + 倒排 + 乘积量化 方案快速检索TopK,然后将这些用户对应的文章列表加权打分排序等。优点:时时性比较好,缺点是检索过程比较复杂,结果不够准确。
基于物品的协同过滤
简单来说就是给用户推送物品的A的相似物品B。
具体的流程
- 离线寻找相似物品:根据上面矩阵将物品专为向量,纬度按照用户,各纬度值按照用户喜欢的数量作为值转为向量,然后ANN搜索,根据ItemID为key,相似物品列表为posting list。
- 在线推送:只要是用户看过的key,就查倒排列表,然后归并计算TopK。
混合召回+分层打分
采用多种方式
首先,每一个召回通路都会使用自己的非精准打分算法,截取千级别之内的候选集。然后,推荐引擎会合并这多个召回通路截取的几千个结果,也就是使用简单的机器学习模型进行非精准打分,选出最好的上百个结果。最后,推荐引擎会使用精准的深度学习模型,选出最好的几十个结果返回给用户。这就是用户看到的最终的推荐结果了。