数智方法论.png


数智物语出品

策划、编写:卷毛雅各布


「我们相信,在垃圾泛滥的互联网海洋中,真正有价值的信息是绝对的稀缺品。」知乎CTO李大海曾在全球移动互联网大会提到知乎诞生的初心,而这位CTO也在各种场合不遗余力的提到知乎对于AI投入和应用。


微信图片_20190123133913.png

知乎合伙人、CTO李大海


对于一个的坐拥1.4亿多用户,平均日活跃用户量超过 3400 万,人均日访问时长 1 小时,月累计页面访问量达到 230 亿的大厂来说(数据截止2018年 3 月),知乎的AI都到底应用在了哪些领域,这中间应用到了哪些技术和模型,又产生了哪些作用?今日第1期数智方法论将从内容生产、内容消费与分发、内容连接、内容治理这四大应用场景带你一窥知乎AI。


image.png



目录:


1 内容生产

   1.1 问题提出

   1.2 问题路由

2 内容分发和消费

   2.1 首页「水晶球」推荐系统

   2.2 知乎首页信息流算法进化史

   2.3 首页架构改进

   2.4 知乎搜索系统

3 用户连接

   3.1 基于用户行为的 Embeeding 表示

   3.2 基于用户社交关系的 Embeeding 表示

4. 内容治理

   4.1 瓦力治杠精

   4.2 悟空反作弊


1. 内容生产


为了让用户快速看到自己感兴趣的提问并且激发用户的创作欲望,知乎在内容生产上从两个方向进行了布局:问题提出与问题路由。


1.1 问题提出


问题提出是一个从用户的查询中识别出意图,发现知乎现在还无法满足的意图,引导用户进行提问,并根据用户的意图生成合理的问题的过程,得到提问和描述后,后台的卷积神经网络模型会从知乎超过二十五万个话题中选择出最匹配的话题,进行话题的推荐和绑定。


1.2 问题路由


问题路由是如何分发问题以让合适的用户看到问题、激发他们的创作欲望。这是一个典型的机器学习排序(learning to rank)问题:先在众多用户中通过召回定位合适的范围,然后通过 pointwise/pairwise/listwise 等排序方法,找出最有可能接受邀请以及最有可能产生优质回答的用户,进行推荐,或让用户选择委托系统进行邀请。问题路由在其中起到的就是提升匹配精准度和效率的作用。


image.png


2. 内容分发和消费


内容的分发和消费部分,知乎从首页信息流、搜索和相关推荐、首页架构等进行了不断地优化和升级,力图让每个用户能快速、便捷地获得更多感兴趣、有用的内容。


2.1 首页「水晶球」推荐系统


知乎的「水晶球」信息流推荐框架是一个基于多策略融合的多源内容推荐系统,关于「水晶球」的来源知乎首页负责人张瑞提到:『我们把系统命名为「水晶球」,是希望能够通过这个系统得以一窥用户想要看到什么内容,然后推荐给他』。


如下图所示,在这个系统中,首页上出现的内容会经历两次排序: 第一次是从数十个推荐队列里被「召回」,第二次是在合并后经过深层神经网络(DNN)的「排序」


image.png

「水晶球」信息流推荐框架


对于如何「召回」和「排序」,知乎团队也做过详细介绍:

「召回」的第一个步骤是,召回模块根据用户的历史行为表现(用户画像),确定数十个推荐队列,或者说数十个「召回源」的召回比例和召回数量。推荐队列是一个个含有特定标签的内容合集。有些队列里内容性质相似,比如热点新闻队列、视频队列。还有的队列与用户行为紧密相关,比如关注的人队列、搜索关键词队列。


「召回」过程的第二个步骤是各召回源根据用户的需求分别将自己的队列中的内容做排序后,按召回数量返回内容。


「召回」过程会选出数百条候选内容进入「排序」过程,最后,DNN 可以在一百毫秒内对这数百条完成打分和排序过程,决定推送给用户的内容。


2.2 知乎首页信息流算法进化史


2.2.1 Edge Rank 算法


知乎从 2013 年就上线了信息流产品。当时的主逻辑是一套叫做 Edge Rank 的算法。把用户关注的所有人和话题所产生的所有新内容,当成候选池,候选池里的每个内容的权重与三个因素相关,分别是表示用户对关注对象的关注度的权重,内容的类型,以及时效性权重。


image.png


2.2.2 GBDT 算法


随着知乎体量的增长,Edge Rank 已经不能满足分发效率的需要。知乎从 2016 年开始升级首页产品。首先使用 GBDT 来进行 CTR 预估,并以 CTR 预估值作为排序的主要考虑因素。GBDT 算法的引入,对知乎首页的分发效率提升是非常可观的。GBDT 的算法首次上线,用户停留时长就有了 12% 的提升,后续不断改进算法,一年时间里面,累积获得了 70% 的用户在线时长的增长。GBDT 的优势是可解释,并且需要的训练数据量级不算太大,GBDT 的研发、调试和训练成本都较低,从 0 开始构建的时间成本也比较可控,特别适合研发及计算资源比较受限、但又亟需使用机器学习改进业务的团队尝试。


image.png


2.2.3 深度学习技术


从 2017 年开始,知乎将深度学习技术引入了首页推荐产品之中。原有GBDT 模型的容量和表示能力有很大的限制,当模型的训练样本量达到千万数量级时,再增加训练样本的规模,模型精确度已经得不到明显的改善。所以知乎转向了深度学习技术。


知乎用户的兴趣比较广泛,一个用户在知乎上往往会对几十、上百个话题感兴趣。在这种情况下,用传统的 content based 算法,会有大量的分发策略需要人工设计,例如兴趣的衰减、交叉、去重等。而要是用 ALS 之类的协同过滤算法,又会面临数据过于稀疏的问题,知乎到了一个用户和内容都达到了上亿量级规模的推荐场景。


所以,他们参考了 word2vec 的设计思路,设计了一个 DNN 网络,希望把每个用户和每一篇内容都表示成同一个空间的向量。任意两个向量的距离越小,表示它们越相关,如果这两个向量一个是用户,一个是内容,那就代表该用户对该内容感兴趣的概率越高。有了这个表示之后,对于每个用户,都可以利用 ANN 算法(Approximate Nearest Neighbor,近似最近邻搜索)召回它可能喜欢的内容。


image.png


这个 DNN 网络结构比较简单,但作为召回系统的效益是非常明显的。知乎衡量推荐系统的召回模块有效性时,主要看一个关键的指标,从几万条数据中挑出的 100 个结果的准确度有多少,这 100 个结果里有多少准确预测到用户下次点击的数据。在这个指标上, DNN 比起 ALS 来讲提升了 10 倍的量级。当然,这个 DNN 网络也有一个问题,那就是新内容的表示不会在老的网络中自动被学习到。


为了保证新内容能够比较快地被感兴趣的用户看到,知乎采用一个离线流水线来解决这个问题。这条流水线使用 spark streaming 来实现了内容 embedding 的批量更新。这个 spark streaming 应用会采集线上的数据,根据线上内容的分发状况,以及用户对这些内容的行为反馈情况,通过一个简单的、两层神经网络的梯度下降,快速更新内容库中内容的 embedding 表示。


image.png


随后知乎也把 DNN 用在了排序中。最初上线的 DNN 是一个比较简单的全连接版本。


image.png


在上线后知乎持续地对这个模型进行了各种优化,包括引入 FM 层作特征之间的自动交叉、利用卷积神经网络处理文本输入、利用 LSTM 处理时序序列数据等,都取得了较好的效果。采用 DNN 模型的召回和排序上线后,再结合这些持续不断地优化,Feed 流的人均阅读量和人均使用时长均增长了 50% 以上。


image.png


2.2.4 多目标学习


在知乎上,除了「阅读」这种行为非常重要外,其他的一些交互动作,例如点赞、评论、分享、收藏等,也都是反映用户体验的重要的行为指征。


对于首页的优化,除了上面介绍的方法之外,知乎也进行了多种方向的尝试。其中一个方向是多目标学习。从 GBDT 开始到现在的 DNN 网络,本质上都是 CTR 预估。所以知乎设计了一个机制来进行多目标学习,抛弃只看点击率的局限性。


具体来说,是使用丰富的阅读数据来训练一个基准网络,然后利用这个基准网络的前面一些层做参数共享,在后两层,分别对于不同的学习目标,进行参数的微调。


这是一种迁移学习的思路,可以大大节省离线模型训练和线上多目标推断时的计算量。多目标排序目前在知乎的实际应用中已经有一些初步的结果,通过小流量对比发现,使用多目标模型来排序,除阅读之外的行为量都能有 10% 左右的增长。


另外,知乎也在探索如何在排序学习中体现推荐列表的多样性。CTR 预估实际上是一种 pointwise 的排序方法,可能造成的后果是,如果用户对很多内容感兴趣,在内容质量相当的情况下,这种排序会将「最喜欢的一类内容」全都排到最前面,造成用户阅读时的疲惫感和单调感。


一般来说,线上都会使用一些 Rerank 的方法,例如打散、隔离等规则,来保证多样性。但人工规则既不精确,设计起来也非常容易出 badcase。所以,知乎正在尝试利用 seq2seq 的方法,来为用户直接生成推荐内容的列表。在 seq2seq 模型中,会将用户已经看到的内容考虑进去做为模型的输入,来体现用户推荐列表的多样性。


image.png


2.2.5 人机结合


知乎CTO李大海毫不避讳地提到知乎目前的机器学习算法并不完美,尤其是在 NLP 领域,在语义理解方向上,AI 技术还有很大的提升空间。为了让用户得到更好的体验,知乎的 AI 应用自始至终都伴随着人的高度参与,人机结合是避免「算法偏见」出现的有效方法之一。


所以知乎在今年启动了一项名为「泰戈尔」的计划,从标签定义、标签生产、质量审核、标签应用等方面,建立了一套对内容进行识别和应用的闭环,并明确了算法、运营、业务团队在这个闭环中的角色。


这个计划启动以后,在机器识别方面,接入了领域识别、内容质量判定、内容时效性识别等多个维度的识别算法,同时,知乎内容运营的同事会在机器识别的基础上,每天都会对健康、影视、法律等多个领域的,成千上万篇内容进行标注和算法结果的纠正。


image.png


2.3 首页架构改进


除了算法方面的改进之外,首页推荐团队在架构上从两个方面进行了改进:


2.3.1 已读服务的升级


为了避免把用户已经看过的内容再次推荐给他,信息流产品通常需要记录下来哪些内容已经推荐给用户过,这个信息是一个 N X N 的大表,数据量非常大且稀疏,另一方面,这个服务在读写上都有很高的访问量,hbase 这样的服务在响应时间的稳定性上,不能达到知乎的要求,所以知乎实现了一个叫 Rbase 的系统,这个系统综合利用了 MySQL 的存储能力和可靠性以及 Redis 的低时延和高吞吐。


在缓存失效的情况下对同一个热键值的并发读取不会产生惊群效应。利用写通缓存的更新策略再加上变更下推来维护缓存的一致性,所以不需要对缓存数据设定过期时间。知乎使用分层缓存来从空间维度和时间维度提高命中率。利用分层缓存还可以更有效的应对跨数据中心部署时带宽受限的问题。最重要的是 Rbase 提供了 BigTable 一样的数据模型,并且和 Hbase 的 API 在功能和用法上非常接近,方便迁移。


image.png


2.3.2 推荐架构的改造


知乎早期广泛采用 python 语言来进行开发,包括首页推荐的业务框架也不例外。在经过长时间的功能叠加之后,老系统在响应时间优化以及可维护性等方面,已经很难提出比较高的要求。所以知乎在 18 年使用 java 进行了系统的重写,不仅大幅度优化了响应时间,节约了比较多的机器资源,还引入了多队列召回的能力,允许从不同维度召回与用户相关的内容,进一步提高多样性。


image.png


2.4 知乎搜索系统


搜索是知乎在壮大过程中逐步优化的一个功能。知乎希望通过个性化推荐和搜索系统,尽可能缩短用户和内容之间的距离,让用户在知乎摆脱信息过载带来的负担和压力。


2.4.1 搜索算法改进与应用


以深度学习为代表的搜索相关性语义特征,知乎的搜索算法近几年获得了长足的发展:从最早的以 DSSM 为代表的 Query/Doc 分别提取深度表征的方法,到近期的以MatchPyramid, KNRM 等为代表的 Query/Doc 相互交叉为相关度图再做计算的方法,再到这两类方法相互融合的方法,以及最近的 BERT 模型。知乎在实践过程中发现 MatchPyramid, KNRM 等第二类方法的效果,普遍优于 DSSM 等第一类方法。深度语义特征上线之后,知乎在头部、腰部、长尾的搜索点击比普遍提升了约 2% - 3% 不等。


image.png


2.4.2 搜索架构优化


除了算法方面的改进,知乎也投入了不少人力在搜索的架构优化上。早年采用 ES 作为索引引擎,随着数据量的增加,知乎遇到了 ES 集群的服务稳定性问题,以及 ES 对排序算法支持不友好等问题。所以在 17 年,知乎自己开发了一套在索引格式上完全兼容 ES 的引擎系统,逐步替换了在线上服务的 ES 集群。这个系统使用 Rust 开发,Rust 语言是一种类似于 C/C++ 的无 GC 语言,李大海曾提到虽然 Rust 语言的学习曲线非常陡峭,但是在团队熟悉语言后,由于 Rust 能在编译器层面避免内存安全问题和并发安全问题,所以整体获得的收益是非常显著的。目前知乎全部的搜索请求都由新的索引服务支撑,在可用性达到了 5 个 9 的同时性能上也不输于 C++ 编写的类似系统所能达到的水平。


image.png


3. 用户连接


知乎为了加强社区内用户与用户的联系,通过Graph Embedding 模型对用户进行隐式表示的学习,计算出两个用户之间的亲密度、兴趣相似度,以此进行更精准的推荐,让用户更多地在社区里发生连接。


3.1 基于用户行为的 Embeeding 表示


基于用户行为的 Embeeding 表示,主要使用用户搜索内容、关注、收藏、点赞、阅读的回答、文章等对应的话题,作为用户的特征,整理成 0-1 的向量。使用变分自编码器(Variational Auto-Encoder,VAE) ,使样本对应到正态分布,计算此正态分布和标准正态分布的 KL 散度距离作为额外的 loss,最终为得到用户的 Embedding 表示。


image.png


3.2 基于用户社交关系的 Embeeding 表示


基于用户社交关系的 Embeeding 表示,主要使用 skip-gram 模型,得到用户的特征表示,从用户关注优秀回答者的关注关系网络中抽取数据集,采用 Randomwalk 方法抽样有序的节点,从而将社交网络转化为有序节点进行学习。


image.png


Embedding 模型主要应用在了知乎的以下场景:


1. 用户聚类:使用用户聚类来在推荐中做召回,使用用户 Embedding 表示,经过聚类计算后,得到用户的人群,可以把这个群体的高互动内容作为 feed 候选,放入到推荐系统当中。


2. 用户亲密度:使用用户 Embedding 表示 + 用户对用户的互动行为特征,可以预测用户的关注关系,得到用户亲密度值。这个值用在很多和社交相关的策略之中。


3. 基于种子用户和 user representation 的人群扩展:人工给定或者策略圈定种子用户,使用用户 Embedding 表示计算得到和种子用户最相近的 top n 用户进行目标人群扩展,这个能力目前主要应用于商业化产品中。


4. 内容治理


36氪报道过知乎一直把「稳定而高质量的知识内容」作为重要的护城河,但随着用户的不断增加,以及算法的普遍应用,甚至是竞争对手「挖墙脚」(2017年今日头条挖走300个知乎大V ,并且签约后禁止发知乎,今日头条后续推出了悟空问答,腾讯新闻客户端也推出过问答产品),似乎知乎的推送内容与头条并无太大区别,知乎社区的内容质量也有所下降。在内忧外患情况下知乎对于内容治理也进行了大刀阔斧的改革,「瓦力」、「悟空」等算法和系统不断出击,并且加大了人工质检的投入。


4.1 瓦力治杠精


image.png

瓦力:社区管理的「大脑」


所谓「杠精」是指抬杠成瘾的一类群体。不管别人说的是什么,先反驳挑刺,为了反对而反对,通过反驳别人来凸显自己的优越感,再加上「只有我一个人觉得……」句式的加持,基本上能成功惹翻他人。 2018年12月3日,词语「杠精」被《咬文嚼字》公布为2018十大流行语。而「杠精」在知乎具体体现为各种「阴阳怪气」的言论,「瓦力」就专门针对这类杠精言论而生。


微信图片_20190123133928.png


瓦力算法系统作为整个知乎社区管理的「大脑」,以知乎社区管理规范为标准,主要应用于不友善、答非所问、低质提问、×××低俗、违法违规等方面的治理。从18年4月自上线至今,瓦力已经过多次的迭代更新,被应用多个使用场景中。


目前,这个系统可以做到:实时筛查并处理社区新生产内容中的不友善因素;结合知友们的举报,在 0.3 秒内识别判断被举报内容是否包含不友善因素,并做出相应处理;每天清理约 5000 条新产生的「答非所问」内容,以及此前现存的近 120 万条「答非所问」内容,还能实时对社区内提问进行筛查,每天处理约 900 条封建迷信、求医问药类的低质提问;能够识别×××图文、违法违规、垃圾广告等内容。


下图比较完备地展示了知乎识别阴阳怪气评论的技术方案。知乎把评论和相应回答的文本特征、标点符、表情符统计特征、是否命中反讽词表等多维度 feature 作为模型的输入,采用 CNN 和 LSTM 相结合的网络拓朴结构训练二分类模型;


image.png


在训练数据获取方面,使用站内有大量一致用户行为的语料,来自动生成二元的标注;为了提高模型泛化能力,通过 active learning 方法选取站内评论,经过人工标注加入训练集。2018年 6 月,「瓦力」的阴阳怪气识别功能上线,在召回率 25% 的情况下,准确率达到了 95%。


具体来说,解决方案分为了以下三个步骤:


1. 进行数据增强,以提升模型的泛化能力


数据增强是为了提升模型在大量数据上的泛化能力。在这方面,知乎进行了两种尝试:提取阴阳怪气关键词做替换,比如同音异字变换,洗地党→洗涤党,真的很恶心 → 震得很恶心;此外,知乎也利用提取出的阴阳怪气关键样本,随机构造评论上文与评论。


2. 提取相关数据特征,利用卷积网络以及人工特征等来获得更多更详细的特征


特征构建层方面,知乎从文本特征、数值特征、阴阳怪气词以及表情词着手。文本特征即文本加入阴阳怪气关键词进行分词后,保留标点,表情等;数值特征即句子长度,句号数量,感叹号数据等;阴阳怪气词即提取社区内被踩过很多次的表示阴阳怪气关键词;表情特征:划分正负样本表情。


3. 将提取出的特征输入分类器


特征学习层方面,主要考虑了评论和上文的文本特征,包括字,词,标点,表情符号等,并利用知乎全量数据训练 word2vec 模型。知乎将评论上文与评论经过 embedding 层后分成两个金字塔型 CNN 网络,目的是训练各自独立的参数,知乎采取 CNN 网络是因为 CNN 卷积可以捕获字词的位置关系也可以比较有效的提取特征。


除上述文本特征外,知乎也充分考虑了其它特征,比如评论长度,评论中句号,问号等标点的个数,评论中是否包含阴阳怪气关键词等;这些特征离散化后,与评论的卷积提取特征进行拼接,最后与评论上文的卷积输出进行 dot-attention ,目的是获取评论上文与评论不同的权重。最后,知乎将特征数据全连接层以 softmax 方式进行了分类。


尽管瓦力在各个维度进行的社区治理准确度已超过 90%,但却是无法取代人工的,知乎也没有将内容和社区管理的任务全部集于算法一身,而是采用算法 + 人工的方式。对瓦力处理的内容,知乎会每天进行质检,同时也有专门的团队对于用户申诉进行复核和响应。


4.2 悟空反作弊


image.png


Wukong 是知乎的反作弊系统,主要负责 SPAM 的召回和处理。从 2015 年 4 月上线,随着知乎的不断发展壮大,悟空也进行着持续地优化升级。接下来分享下知乎「悟空」的架构演进和构建过程中积累的经验与教训。


4.2.1 知乎典型 Spam


在知乎长期存在,且比较典型的 Spam有这么几类:


1.内容作弊 Spam:这类 Spam 的核心获益点一方面是面向站内的传播,另一方面,面向搜索引擎,达到 SEO 的目的。内容类的 Spam 是社区内主流的 Spam 类型,目前主要包括四种形式:


导流内容:这类 Spam 大概能占到社区中 Spam 的 70% - 80%,比较典型的包括培训机构, 美容,保险,代购相关的 Spam。导流内容会涉及到 QQ,手机号,微信,url 甚至座机,在一些特殊时间节点还会出现各类的专项 Spam,比如说世界杯,双十一,双十二,都是黑产大赚一笔的好时机。


品牌内容:这类内容会具有比较典型的 SEO 特色,一般内容中不会有明显的导流标识,作弊形式以一问一答的方式出现,比如提问中问什么牌子怎么样?哪里的培训学校怎么样?然后在对应的回答里面进行推荐。


诈骗内容:一般以冒充名人,机构的方式出现,比如单车退款类 Spam,在内容中提供虚假的客服电话进行诈骗。


骚扰内容:比如一些诱导类,调查类的批量内容,非常严重影响知友体验。


2.行为作弊 spam:主要包括刷赞,刷粉,刷感谢,刷分享,刷浏览等等,一方面为了达到养号的目的,躲过反作弊系统的检测,另一方面通过刷量行为协助内容在站内的传播。


治理经验:治理上述问题的核心点在于如何敏捷、持续地发现和控制风险,并保证处理成本和收益动态平衡,从 Spam 的获益点入手,进行立体防御。所谓立体防御,就是通过多种控制手段和多个控制环节增强发现和控制风险的能力。


4.2.2 三种控制方式


策略反作弊:在反作弊的初期,Spam 特征比较简单的时候,策略是简单粗暴又有用的方式,能够快速的解决问题,所以策略在反作弊解决方案里是一个解决头部问题的利器。


产品反作弊:一方面通过改变产品形态来有效控制风险的发生,另一方面通过产品方案,对用户和 Spammer 痛点趋于一致的需求进行疏导,有时候面对 Spam 问题,对于误伤和准确会遇到一个瓶颈,发现很难去区分正常用户和 Spammer,这种情况下反而通过产品方案,可能会有比较好的解决方案。


模型反作弊:机器学习模型可以充分提高反作弊系统的泛化能力,降低策略定制的成本。模型应用需要酌情考虑加入人工审核来保证效果,直接处理内容或用户的模型算法,要注意模型的可解释性。初期一些无监督的聚类算法能够在比较短时间内达到较好的效果。而有监督的分类算法,在时间上和人力上的耗费会更多,样本的完整程度,特征工程做的好坏,都会影响算法的效果。


4.2.3 三个控制环节


事前:事前涉及到的几个环节包括风险教育、业务决策参与、监控报警以及同步拦截。反作弊需要提升业务的风险意识,明确告知反作弊可以提供的服务;并在早期参与到业务决策,避免产品方案上出现比较大的风险;业务接入后,针对业务新增量、处理量、举报量,误伤量进行监控,便于及时发现风险;在策略层面,在事前需要针对头部明显的作弊行为进行频率和资源黑名单的拦截,减轻事中检测的压力。


事中:面向长尾曲线的中部,主要针对那些频率较低,且规律没有那么明显的作弊行为,针对不同嫌疑程度的行为与帐号,进行不同层级的处理,要么送审,要么限制行为,要么对内容和帐号进行处罚。


事后:面向长尾曲线最尾部的行为,即那些非常低频,或者影响没那么大,但是计算量相对大的作弊行为。由一些离线的算法模型和策略负责检测与控制,另外事后部分还涉及到策略的效果跟踪和规则的优化,结合用户反馈与举报,形成一个检测闭环。


4.2.4 知乎「悟空」的架构演进


悟空 V1


初期 「悟空」主要由事前模块和事中模块构成。


image.png


事前模块与业务串行执行,适用于做一些耗时短的频率检测,关键词和黑白名单拦截。由于是同步接口,为了尽量少的减少对业务的影响,大部分复杂的检测逻辑由事中模块去处理。

事中模块在业务旁路进行检测,适合做一些相对复杂,耗时长的检测。事中主要由 Parser 和一系列 Checker 构成,Parser 负责将业务数据解析成固定格式落地到基础事件库,Checker 负责从基础事件库里取最近一段时间的行为进行策略检测。


事件接入

在反作弊的场景数据落地一般会涉及到这几个维度:谁,在什么时间,什么环境,对谁,做了什么事情。对应到具体的字段的话就是谁 (UserID) 在什么时间 (Created) 什么环境 (UserAgent UserIP DeviceID Referer) 对谁 (AcceptID) 做了什么事情 (ActionType ObjID Content)。有了这些信息之后,策略便可以基于维度进行筛选,另外也可以获取这些维度的扩展数据(e.g. 用户的获赞数)进行策略检测。


策略引擎

「悟空」的策略引擎设计,充分考虑了策略的可扩展性。一方面支持横向扩展,即支持从基础维度获取更多的业务数据作为扩展维度,例如用户相关的信息,设备相关的信息,IP 相关的信息等等。另一方面纵向扩展也被考虑在内,支持了时间维度上的回溯,通过检测最近一段时间内关联维度 (e.g. 同一个用户,同一个 IP) 上的行为,更高效地发现和打击 Spam。


下面是一条典型的 V1 的策略:


image.png


这条策略主要实现了这样的逻辑:

最近 10 分钟在同一话题下创建的回答,与当前用户,注册时间在一小时之内,同一 IP 下注册的用户数大于等于 3 个。

基本上这样的模式足够满足日常的 Spam 检测需求,但是知乎发现这种嵌套结构对于书写与阅读来说还是不太友好,这个部分的优化在 V2有作详细描述。

考虑到策略变更会远大于基础模块,在 V1 的架构中,知乎特别将策略维护的逻辑单独拆分成服务,一方面,可以实现平滑上下线,另一方面,减少策略变更对稳定性带来的影响。


存储选型

存储上,知乎选择了 MongoDB 作为基础事件存储,Redis 作为关键 RPC 的缓存。选择 MongoDB 的原因一方面是因为知乎基础事件库的业务场景比较简单,不需要事务的支持;另一方面,知乎面对的是读远大于写的场景,并且 90% 都是对最近一段时间热数据的查询,随机读写较少, 这种场景下 MongoDB 非常适合。另外,初期由于需求不稳定,schema-free 也是 MongoDB 吸引知乎的一个优点。由于策略检测需要调用非常多的业务接口,对于一些接口实时性要求相对没那么高的特征项,知乎使用了 Redis 作为函数缓存,相对减少业务方的调用压力。


悟空 V2


「悟空 V1」已经满足了日常的策略需求,但是在使用过程知乎也发现了不少的痛点:

1. 策略学习曲线陡峭, 书写成本高:上面提到的策略采用嵌套结构,一方面对于产品运营来说学习成本有点高,另一方面书写过程中也非常容易出现括号缺失的错误。

2. 策略制定周期长:在「悟空 V1」上线一条策略的流程大概会经过这几步, 产品制定策略 - 研发实现策略 - 研发上线策略召回 - 产品等待召回 - 产品确认策略效果 - 上线处理。整个环节涉及人力与环境复杂,策略验证麻烦,耗时长,因此策略试错的成本也会很高。


鉴于此,「悟空 V2」着重提升了策略自助配置和上线的体验,下面是「悟空 V2」的架构图:


image.png


策略结构优化

参考函数式语言,新的策略结构引入了类 spark 的算子:filter, mapper, reducer, flatMap, groupBy 等等,一般基础的策略需求通过前三者就能实现。

举个例子,上面提到的策略在优化之后,会变成下面这种格式:


image.png


结构上变得更清晰,可扩展性也更强,工程上只需要实现可复用的算子即可满足日常策略需求,不管是机器学习模型还是业务相关的数据,都可以作为一个算子进行使用。


策略自助配置

完成了策略结构的优化,下一步需要解决的,是策略上线流程研发和产品双重角色交替的问题,「悟空 V2」支持了策略自助配置,将研发彻底从策略配置中解放出去,进一步提升了策略上线的效率。


image.png


策略上线流程优化

为了使策略上线变得更敏捷,知乎在每一条上线的策略都在准确率和召回率之间权衡,在尽量高准确的情况下打击尽量多的 Spam,因此每条要上线的策略都需要经过长时间的召回测试,这是一个非常耗时并且亟待优化的流程。「悟空 V2」策略上线的流程优化成了:创建策略 - 策略测试 - 策略试运行 - 策略上线处理 - 策略监控。

策略测试主要用于对策略进行初步的验证,避免策略有明显的语法错误。

策略试运行可以理解成快照重放,通过跑过去几天的数据,快速验证策略效果,一切都可以在分钟级别完成。这部分的实现将策略运行依赖的资源复制了一份,与生产环境隔离,实现一个 coordinator 将历史的事件从 MongoDB 读出并打入队列。值得注意的是,入队速度需要控制,避免队列被瞬间打爆。

通过试运行的验证之后,策略就可以上线了。上线之后,策略监控模块提供了完善的指标,包括策略执行时间、策略错误数、策略命中及处理量等等。


悟空 V3


2016 年中旬,知乎主站各业务开始垂直拆分,相应的,「悟空」业务接入成本的简化开始提上日程。


Gateway

Gateway 负责与 Nginx 交互,作为通用组件对在线流量进行风险的阻断。目前 Gateway 承担了所有反作弊和帐号安全用户异常状态拦截、反作弊功能拦截和反爬虫拦截。这样一来,这部分逻辑就从业务剥离了出来,尤其是在业务独立拆分的情况下,可以大大减少业务的重复工作。作为通用组件,也可以提升拦截逻辑的稳定性。Gateway 当前的架构如下图所示:


image.png


由于是串行组件,所有请求要求必须在 10ms 内完成,因此所有的状态都缓存在 Redis。Gateway 对外暴露 RPC 接口(Robot),相关服务调用 Robot 更新用户,IP,设备等相关的状态到 Redis。 当用户请求到达时,Nginx 请求 Gateway,Gateway 获取请求中的 IP,用户 ID等信息, 查询 Redis 返回给 Nginx。当返回异常状态时 Nginx 会阻断请求,返回错误码给前端和客户端。


TSP - Trust & Safety Platform


image.png


TSP 主要为反爬虫和反作弊提供服务,一方面解析旁路镜像流量,通过 Spark 完成流量清洗和基础计数,再通过 Kafka 将计数数据打给反爬虫策略引擎,进行检测和处理,从而实现业务零成本接入。另一方面,由于反作弊依赖较多业务数据,难以从流量中获取,故以 kafka 接入替代 RPC 接入,实现与业务进一步解耦,减少对业务的影响。

随着「悟空」策略上线效率的提升,在线的策略逐渐增多,知乎开始着手优化「悟空」的检测性能与检测能力。


策略充分并行化

「悟空 V2」策略检测以行为为单位分发,带来的问题是策略增多之后,单行为检测时长会大大增强。在 V3优化了这部分逻辑,将策略检测分发缩小到以策略为粒度,进一步提升策略运行的并行度,并实现了业务级别的容器隔离。优化后,事中检测模块演化成了三级队列的架构。第一级是事件队列,下游的策略分发 worker 将数据落地,并按照事件的业务类型进行策略分发。策略执行 worker,从二级队列获取任务,进行策略检测,并将命中的事件分级处理,分发到对应的第三级队列。第三级队列即处理队列,负责对命中规则的内容或者用户进行处理。


image.png


缓存优化

因为每个策略检测都会涉及到历史数据的回溯,自然会带来较多的重复查询,存储的压力也会比较大,所以存储上又增加了多级存储,除了 MongoDB,在上层对于近期的业务数据,存储在 Redis 和 localcache。


图片识别能力增强

随着文本内容检测能力的增强,不少 spam 开始使用图片的方式进行作弊。在「悟空 V3」增强了图片相关的检测能力:图片 OCR,广告图片识别,×××图片识别,违法违规图片识别,政治敏感图片识别。针对图片类的广告 Spam 的检测一直是空缺,需要投入大量的人力进行模型训练,所以这一块知乎借助第三方快速提升这一块的空缺。接入之后,着实提升了解决站内广告和诈骗图片 Spam 的能力。


风险数据进一步积累

早期由于系统还未成熟,知乎很多的工作时间都花在 Spam 问题的应急响应上,很少去做各维度的风险数据累积。在「悟空 V3」知乎分别在内容、帐号、IP、设备维度开始累积相关的风险数据,供策略回溯和模型训练使用。 目前知乎有三个数据来源:策略、第三方接口和人工标注。鉴于离线人工标注效率低,并且抽取数据项繁杂的问题,知乎专门搭建了一个标注后台,提升运营标注数据的效率,使标注数据可复用,可追溯。以下是一些知乎比较常用的风险维度:

1. 内容维度:e.g. 导流类广告,品牌类广告,违反法律法规

2. 帐号维度:e.g. 批量行为(批量注册,刷赞,刷粉等),风险帐号(社工库泄露等), 垃圾手机号,风险号段

3. IP 维度: e.g. 风险 IP ,代理 IP

4. 设备维度:e.g. 模拟器,无头浏览器


回溯能力增强

在「悟空 V3」,知乎还增强了策略的回溯能力。一方面,搭建失信库覆盖新增内容中与失信内容相似的 Spam 内容,相似度的算法目前知乎使用的是 consine-similarity 和 jaccard。另一方面,基于 Redis,知乎支持了基于导流词、标签、社区的快速回溯。这样的话相关的行为更容易被聚集到一起,使得知乎可以突破时间的限制,对相似的 Spam 一网打尽。

此外,知乎工程和算法团队在算法模型引入做了诸多尝试。


结网 - ZNAP (Zhihu Network Analysis Platform)


image.png


过去做反作弊的很长一段时间,知乎花了很多功夫在行为和内容层面去解决 Spam 问题。但换个角度知乎发现,黑产团伙固然手上的资源巨多,但是也得考虑投入产出比,不管怎么样,资源都会存在被重复使用的情况,那用什么方式去表示这种资源的使用情况呢?知乎想到了图,也成为了知乎做「结网」这个项目的出发点。这个项目分成了几个阶段:


第一阶段,实现基于图的分析能力:这个阶段旨在提供一种通过网络图谱分析问题的渠道,提升运营和产品的效率,快速进行社区(设备,IP..)识别,团伙行为识别以及传播分析。图谱分析平台的数据基于用户的写行为,将用户,设备,IP, Objects (提问,回答..) 作为节点,具体行为作为边。当行为发生时,将用户与设备,用户与 IP, 用户与对应的 object 关联, 而每个节点的度就代表发生关联的数量。 图数据存储的部分知乎当时调研了 Titan, Neo4j 和 TinkerPop,三者之中最终选择了 TinkerPop 作为存储框架,底层用 HBase 作为存储。TinkerPop 是 Apache 的顶级项目之一,是面向 OLTP 及 OLAP 的图计算框架,其扩展性非常之强,只要实现了 TinkerPop 定义的 API,就能作为驱动让存储支持图查询,可以减少存储额外维护和迁移的成本。目前 Tinkerpop 支持 HBase, Neo4j, OrientDB 等等。另外也通过 GraphComputer 支持使用 Spark 进行查询和计算。Gremlin 是 TinkerPop 定义的 DSL,可以灵活的用于图数据的查询。


第二阶段,基于图实现社区发现的能力:将相似的用户通过社区的形式化成一个圈子,便于日常分析和策略运用基于一个圈子去处理。知乎采用了 modularity + fast-unfolding 实现了社区发现的算法,拿设备社区为例,算法的输入是设备与用户的关联,输出是每个设备节点和每个用户节点以及他们的社区号。模块度(modularity)是衡量网络划分非常常用的维度,模块度越大,意味着比期望更多的边落在了一个社区内,划分效果越好。Fast-unfolding 则是一个迭代算法,主要目标就是提升划分社区效率,使得网络划分的模块度不断增大,每次迭代都会将同一社区的节点合并,所以随着迭代的增加,计算量也在不断减少。迭代停止的条件是社区趋于稳定或者达到迭代次数上限。


第三阶段,在社区的基础上,实现社区分类的能力:能够有效地识别可疑和非可疑的社区,帮助日常分析和策略更好地打击 Spam 团伙。知乎使用的是可解释性比较高的逻辑回归,使用了一系列社区相关的特征和用户相关的特征进行训练,作为运营辅助数据维度和线上策略使用,都有非常好的效果, 从 2017 年 6 月以来知乎已经积累了 4w 的可疑社区和 170w 的正常社区。


文本相似度聚类

知乎站内的 Spammer 为了快速取得收效,往往倾向于大批量地产生相似的 Spam 内容,或者密集地产生特定的行为。针对这种大量,相似,和相对聚集的特点,使用了 Spark 通过 jaccard 和 sim-hash 实现了文本聚类,通过把相似的文本聚类,实现对批量行为的一网打尽。


未登录热词发现


image.png


品牌类内容也是知乎站内占大头的 Spam 类型。目前站内大部分的恶意营销都是出于 SEO 的目的,利用知乎的 PageRank 来提升搜索引擎的关键词权重。因此这类内容的特点就是大量的关键词(品牌相关,品类属性相关的词汇)会被提及。由于都是一些小众品牌和新品牌,这类关键词一般都未被切词词库收录,就是所谓的未登录词 (Unknown Words), 于是知乎从词汇的左右信息熵和互信息入手,去挖掘未登录词, 并取得了比较好的效果。


导流词识别

针对站内的导流内容,最开始在识别导流信息上采用的是干扰转换+正则匹配+匹配项回溯的方式进行异常导流信息的识别与控制,取得了很好的效果。此外,随着整治加强,知乎发现站内导流变体的现象也在愈演愈烈,对此,也成功引入模型进行整治,通过 BILSTM-CRF 来识别导流变体,目前在提问和回答的识别准确率分别达到 97.1%、96.3%。


通用垃圾内容分类

对于垃圾内容的治理,虽然线上一直有策略在覆盖,但是策略的泛化能力有限,始终会有新型的 Spam 绕过策略。知乎尝试使用深度学习构建通用垃圾文本分类模型。模型使用字向量作为输入,多层 Dilated Convolution 提取文本特征,通过 Attention 对卷积后的表达重新加权得到高层特征,最后得到垃圾内容的概率。针对近期知乎遇到的批量 Spam 内容单条规则召回率可以达到 98% 以上,准确率达到95.6%。

至此,「悟空」整个体系的架构演进已经介绍完了,当前的整体架构如下图所示一共有这么几个部分:


image.png


1. Gateway: 负责异常用户状态拦截,业务同步拦截,反爬拦截。

2. 业务层:对接的各个业务方。

3. 数据接入层:数据接入层有两种方式,一种通过 RPC 透传,一种通过 kafka 消息,实现业务与反作弊系统的解耦。

4. 策略决策层:策略决策层,分为事前同步决策和事中事后异步决策,横向对应的还有策略管理服务,一系列风险分析和运营工具。根据决策结果的可疑程度不同,要么送审要么进行不同程度的处理,确认是 Spam 的行为会进入风险库,回馈到策略再次使用。

5. 数据存储层:数据存储层包括基础的基础的事件库,风险库,离线 HDFS 的数据落地等等, 这一块的数据不仅仅面向反作弊系统开放使用,并且会提供给外部进行模型训练使用和在线业务使用。

6. 数据计算层:这一层包括一些离线的机器学习模型,每日定时计算模型结果,并将数据落地。

7. 数据服务层:因为反作弊不仅仅要依赖自己内部的数据,还会涉及到从业务取相关的数据,所以这一层会涉及到与业务数据,环境数据以及模型算法服务的交互。




基于知乎四大场景的AI技术与应用就整理到这里,为了方便大家回顾,数智君对于文中所提到的部分技术、模型和算法做了简要脑图整理:


知乎AI应用11.png


从这篇能大致看出知乎做起AI来也真的是很「知乎」,一步步改进,一步步优化,并且基于场景和业务本身也做了许多符合自身情况的尝试。既然「稳定而高质量的知识内容」被誉为知乎的护城河,不知道知乎的AI能否持续加固这个护城河?欢迎在评论区发表你的看法,如果这篇方法论让你有所收获,也感谢你点击文末右下方的「好看」~


参考文献

(1)知乎技术专栏

(2)知乎产品专栏

(3)邱陆陆,《知乎:源自社区又服务于社区的 AI 技术》,机器之心公众号,2018年06月13日

(4)极客邦科技 InfoQ,《知乎 CTO 李大海:知识内容平台 AI 技术应用思考》,2019 年 1 月 16 日

(5)阿司匹林,《呵呵,你开心就好!——AI向杠精宣战》,AI科技大本营公众号,2018年07月02日

(6)王艺瑾,《融资2.7亿美元,知乎仍面临护城河焦虑》,36氪, 2018-08-11