[当当]推荐数据系统架构实践
2017-07-16 本文已影响96人
葡萄喃喃呓语
张相於:当当推荐数据系统架构实践-IT168 技术开发专区 http://tech.it168.com/a2016/0831/2890/000002890749.shtml
- Github项目: awesome-coder-resources:编程/学习/阅读资源---开源项目,面试题,网站,书,博客,教程等等...欢迎Star,欢迎围观...
优化的方向总结起来就是,先提炼问题,总结问题类型,抽象出来,扩展泛化,泛化问题解决方案。优化之后就会相应地解决一些问题,比如运行链条会缩短,并且趋于统一
现任58集团转转算法架构师,前当当网推荐&NLP开发经理。本科、硕士毕业于中国人民大学,曾任当当网个性化推荐&NLP算法开发经理。负责当当推荐系统以及NLP算法的相关工作,现任转转算法架构师,负责转转的推荐系统相关工作。具有多年推荐系统、机器学习、数据挖掘、大数据计算方面的实战经验,主导过多个推荐、广告系统项目和多次技术升级。同时关注互联网金融、反欺诈、风险控制等机器学习技术的新应用。
正文
大家好!我是来自当当网的张相於,我今天分享的主题是《当当推荐数据系统架构演变之路》。
现在网上流行这么一句话,套路,都是套路。我觉得任何行业或学科或工业,发展到成熟阶段,都会有一些套路。推荐系统作为大数据典型应用的成功场景,确实发展了很多年,所以也积累出了一定套路。今天,我们就来聊聊这个套路。我今天分享的主要是离线端应用,不包括在线实时API层面,以当当为例但不只针对当当,分享大纲如下所示:
张相於:当当推荐数据系统架构实践
首先看一下发展历程,我把它分为三个阶段:
张相於:当当推荐数据系统架构实践
起步期是算法时代,到成长期就属于野蛮生长时代,成熟期以架构为主,架构为王的时代。
先简单看下推荐系统的典型发展史。讲历史,我们按时间顺序讲,一开始是起步期,从零开始做推荐系统,推荐系统做成以后,会进入快速成长期,成长期可长可短,因为具体行业存在差异,野蛮生长过后会出现很多问题,这时就需要把控,需要做重构,这时就进入了架构为王的时代,如果架构相对成熟一点,可以称之为相对成熟时期。
先讲一下算法时代的两个特点:动机和业务特点。
张相於:当当推荐数据系统架构实践
讲动机实际上就是讲系统什么时候出现,什么时候可以上推荐系统。一般来说,移动互联网时代,很多APP一出来就想上猜你喜欢等功能,但这其实是有动机在里头的。
第一个动机是业务需要,业务需要含义比较丰富,比如流量利用,数据挖掘,用户体验升级等。但也不是说有业务需要,肯定可以做出推荐系统。想做推荐系统,数据是最重要的,必须有一定的数据积累才能做推荐。数据积累是多维度的,可以是行为推荐数据,也就是用户数据,也可以是本身的数据,比如电商行业,数据相对而言比较丰富,比较适合做推荐系统。某些行业比如互联网金融行业,可能没什么数据,这时就需要扒数据。总之没有数据肯定玩不转。
这个时期的业务有很多特点,第一个特点是从0-1的状态。这时,系统没有个性化,就像百货商场一样,千篇一律。从0-1需要做什么呢?有几个层面是不同的,比如不同页面看到的结果不同,不同的购物流程和阶段看到的不同,或者不同的人看到的东西不同。
其次是比较关注效果,比较关注效果侧面反映的是意图单纯,有过推荐系统经验的朋友会知道,推荐系统一开始是单纯的推荐,以算法为主,后期可能要顾虑业务和运营。还有一个特点是特殊逻辑比较少,初期主要关注效果,涉及的规则比较少。同时,人工干预也比较少,后期一般需要不同程度的人工干预。这时的算法有如下特点:
张相於:当当推荐数据系统架构实践
其实推荐算法,万变不离其宗就是一些基本算法,主要是基于相似度的,我们把它称之为memory base,其实都是在记东西。协同过滤算法其实是很经典的一种算法。说到算法,十有八九肯定是协同过滤算法及各种变种。然后是召回,推荐系统做到后来,一般会分两步,一是召回,二是排序。但初期只单独做召回,排序时根据相似度进行排序。无论是基于内容相似度还是文本相似度,说到底算法思想都是一样的,只是以不同的形式展现出来而已。一开始建议使用单一算法和模块,因为初期可能没有时间和精力做很多模块。
算法另一大特点就是干扰少,首先数据干扰比较少,我认为初期的推荐系统数据质量是最好的,首先量是足够的。同时,受到的作弊和异常流量的干扰相对来说比较少,是一个比较平衡的时期。随着业务的发展,数据量越来越大,受到的干扰数据会非常多,花式作弊数据可能会非常多,如果不花工夫清洗,数据将会出现问题。以下是算法时代的简单架构示例图:
张相於:当当推荐数据系统架构实践
在算法时代,最底层是用户数据和业务数据,往上是一些推荐算法和规则。推荐数据右边的箭头,表示需要不断地进行调优,一般来说从网上直接下一个算法,初始效果就非常棒的概率很低,这就需要不断地进行参数调优和数据调优等,最后用到API上,给大家提供推荐服务。推荐服务的形式取决于业务类型,可能是API的形式,也可能是提供数据的形式。
张相於:当当推荐数据系统架构实践
这个时期过去以后,起码说明你的业务是成功的。然后就会进入野蛮生长时期,这是一个非常狂野的时期。这个时期一般有两个因素,一个是正向因素,比如推荐效果得到认可,为什么会这么说呢?其实很多时候,推荐并不适用于所有场景,有时可能需要推荐的场景,有时可能就是卖场的情景,应该针对不同的场景采取不同的方法,如果此时的推荐算法效果不错,一般就会进行扩张。至于负向因素,推荐系统的效果可能还不够好,数据变复杂的同时,作弊数据、刷单数据、促销数据也随之进来了,至于这些数据该不该用到推荐里,是需要琢磨的,毕竟不是正常的用户行为,这时又会产生哪些诉求呢?我认为快速野蛮生长时期的诉求有两方面:
1、模块方面,一开始APP可能只有一个模块叫猜你喜欢,这里面就是所有能做的推荐。发展到后期,肯定会琢磨如何精细化推荐,对搜索意图进行推荐,让推荐可以在各个环节实现个性化,比如用户选择某类商品添加到购物车之后,猜测推荐用户可能还会选择哪类商品。
2、算法层面,我认为算法层面主要包括增加算法,细致调优和数据预处理三个方面。当然,这里并不涉及排名问题。可以上新的算法,但我建议把老算法调明白了,再上新算法。毕竟,经典算法能够横行商业这么多年不是没有道理的。
张相於:当当推荐数据系统架构实践
野蛮生长时期有什么特点和问题呢?特点是业务诉求一般能够得到快速满足,这也是码农的特长,码一个需求还是很快的。算法时代可能初步完成了用户行为,并且效果不错。业务逐渐上升到某个时期,可能需要主打某一款产品,这时你可能会硬着头皮推上去,满足需求其实是比较简单的,这时的系统已经开始呈现出定制化趋势,系统和业务有了紧密的相关性。这时的改进多发于算法程序本身,而不是独立处理。比如数据有点脏的时候,十有八九你会直接在协同过滤算法里加数据清洗阶段,而不是单独提供数据清洗流程,基于这些特点,又会带来哪些问题呢?
第一个问题就是代码开始膨胀,而且可能会膨胀得非常快,由于发展比较快,代码可能是单向生长的,只增不减,这是非常典型的一个问题。二是算法逻辑开始混乱,逻辑其实是需求的体现,如果不对逻辑进行抽象和层次整理的话,它就会像代码一样单向生长,或者在逻辑上面垒逻辑。这时如果业务给你反馈bad case的话,你可能很难搞定这件事情。因为你自己都不清楚,自己的逻辑是什么。三是业务逻辑和算法开始混杂,代码前一句可能还是在处理算法,后一句就开始做业务逻辑了,起初将二者写在一起可能没什么问题,但后来你就会发现,业务规则和算法还是要分开的,放在一起很难扩展。
最后一点也是比较常见的问题,不同算法各自为政。比如两个算法都需要做数据清洗,A做数据清洗的同时,B也做了,但互相不知情。由于没有事先协商,代码分布在不同人的代码里,这时就会造成一些问题。
以上这些问题都是逐步发展,潜濡默化,长期存在的。这个问题肯定不是一天出现的,是在不知不觉中逐渐演变出来的。当你在算法中混入第一条业务逻辑时,你可能觉得没什么问题,长此以往,问题就变得复杂了。并且,不要认为这些问题很快就会过去,如果是单向生长问题,不进行架构处理,是会长期存在的,至于存在多长时间,就取决于业务发展速度和架构的整体情况了。以野蛮生长为例的架构示例图如下所示:
张相於:当当推荐数据系统架构实践
这两个算法的流程是不一样的,右边的算法先进行数据清洗,然后是基于内容的推荐和优化,再往上是业务规则。左边的算法最开始可能发现数据不行,先做一个冷启动进行托底,之后是一些关联规则和优化,再往上是协同过滤和优化,之后是业务规则。其实这是非常普遍的一种场景,两个不同的业务模块并行。互不知情,各自为政,你做你的数据清洗,我做我的托底数据,然后就会生成两个不一样的数据,这两个数据一般对应不同的推荐模块,展现在页面的不同位置。
如果推荐系统是公司业务的战略性问题,在野蛮生长时期之后,一定要做架构方面的改变。
张相於:当当推荐数据系统架构实践
架构是本无所谓有,无所谓无的,踩得坑多了,也便有了架构。这其实还是有一定道理的,一定要踩坑,但不能总在同一个地方踩坑,或者往回踩坑。踩一步走一步,基本都是这么发展过来的。著名物理学家玻尔曾经说过,专家就是在一个非常窄的领域里,犯了他能所犯的所有错误,架构师的成长也是这样。
张相於:当当推荐数据系统架构实践
下面我们看一下野蛮生长带来了哪些血淋淋的代价!
张相於:当当推荐数据系统架构实践
一是运行链条会变得特别长,运行链条就是数据,可能是用户数据和商品数据,从进入系统开始,到最后变成推荐数据呈现在页面上,这个流程就叫做运行链条。野蛮生长时期,链条是单向的,单向生长的逻辑会变得特别长。
张相於:当当推荐数据系统架构实践
二是结构不统一,上面的例子也可以看出,两个算法本质上其实是一样的,结构是可以统一化的,比如在底层提供统一的供清洗用的数据,统一提供托底用的数据,是可以解决这个问题的。但如果不做架构,就会造成不同算法模块走的流程不一样,结构分杈会变得特别大,导致系统复杂度增加,这时的架构会变得非常复杂。
张相於:当当推荐数据系统架构实践
三是血统问题,血统是推荐系统非常重要的一个概念,就是指推荐结果通过哪类算法算出来的,比如扫描苹果上的二维码,可以追踪苹果的整个生产过程,运输过程,其实血统就是这个意思,从推荐数据诞生之日起,在哪个页面曝光,展示给了谁,用户是否进行了点击,有没有购买等问题。一套完整的血缘系统,包括上述整个流程,但如果架构比较混乱,这个血统是很难记下来的,这就会给后续的分析带来很大麻烦。
张相於:当当推荐数据系统架构实践
四是运行速度慢,这个比较好理解。如果不对架构进行梳理,代码就会越来越多,越来越复杂,相比之下,运行速度就会变慢。
张相於:当当推荐数据系统架构实践
五是僵尸逻辑,计算机里面有个概念叫僵尸代码,就是写了好多代码,然后突然觉得没用,全部注掉了,或者写完从来没调用过,这叫僵尸代码。僵尸逻辑与之意思相近,就是系统开始时,逻辑是有效的,但随着业务发展,发现该逻辑已经无效甚至起反作用。比如曾经重点加权的业务,现在可能需要降权,这个逻辑可能存在于代码链条的某一环节,可能非常难找,这个问题就叫做僵尸逻辑。
张相於:当当推荐数据系统架构实践
六是算法实验支持不足,最初,可能需要通过调参调优提升推荐系统的效果。但如果架构十分混乱,实验将很难流程化,配制化。这时,需要人工干预,而人工干预会影响迭代速度,进而影响整个推荐系统的效果提升。
张相於:当当推荐数据系统架构实践
上述提到的问题比较多,无法使用统一的方法解决。但我可以给出我在架构设计上的一些思考,其实就是架构的设计原则,我自己总结了一个哈希表原则。哈希表大家都学过,我认为它和架构设计过程非常相像。哈希表一般会有初始大小,初始大小其实很任性,就是随便设置的一个数,它对应着架构的初始结构。第一版代码其实不用考虑特别复杂的架构,也并没有特别多的内容进行填充,只是搭一个架子而已。
哈希表出来之后,在数据查询方面可能会遇到碰撞冲突。我觉得它对应架构设计中的特殊处理,也就是说,现在的架构无法把所有逻辑放到合适的位置上,这时就需要做特殊处理。抽象地讲,特殊处理和碰撞冲突非常相像,哈希表十有八九会发生碰撞,即使只插了两个数据也有可能发生碰撞,哈希表通过参数衡量碰撞程度,这个指标就是填充因子。填充因子小的话,哈希表会特别空,碰撞会特别小,但会浪费大量空间。在架构设计里,一开始就设计大而全的架构,实际上是没有意义的,因为你可能达不到那样的业务复杂度。所以不论大小,找到合适的填充因子才是最重要的。
确定好填充因子之后,可能就会涉及到扩容问题,这里有一个扩容策略,有一些简单的扩容原则,这时会对应所谓的升级策略。升级和扩容最主要还是针对各自的业务特点,所以我就介绍一下,以什么角度来思考这个问题。
张相於:当当推荐数据系统架构实践
用这张图来代表当当现在的架构,最底层是商品信息和用户行为信息,上层统一做一个预处理,不要在算法中单独做这件事情,再往上就到了算法层,也就是推荐系统层,用不同的逻辑计算推算结果,业务规则要单独拎出来,这样可以保证算法比较纯净。之后是算法融合层,其实对应的就是现在比较流行的召回运用,策略不同的算法对应不同的召回策略,在融合层进行合并。再往上就是推荐排序层,用一些方法对相关度进行排序,最后展示给用户。到这里还没有结束,还需要经过业务过滤层才能得到最终的推荐数据,因为随着业务复杂度的增加,肯定要有专门的形式化的入口留给业务,而不是拿出一串代码就去改,而是留出一个结构化系统化的入口,最终就可以得出推荐结果了。
同时,这一整套可以通过控制中心复制到多个推荐模块上,这样就不需要为每个模块单独写了。前一段时间看了一篇与架构设计有关的文章,这本书表达的观念是,第一个架构一定是under-designed ,就是没有设计,比较乱的。在这之后,你十有八九会设计出一个over- designed的系统,就是可能会设计过度,没有贴近自己的业务。
优化的方向总结起来就是,先提炼问题,总结问题类型,抽象出来,扩展泛化,泛化问题解决方案。优化之后就会相应地解决一些问题,比如运行链条会缩短,并且趋于统一;排序规则会变得比较透明,内部排序,融合排序和统一排序相结合,基于学习算法层次做统一排序,因为单独的算法排序会有很多问题,比如每个算法的考虑因素不一样等。同时,可以在融合层记录一些血统信息,留作日后分析,还可以做一些针对性的性能优化。一旦整个架构变得清晰,就可以很准确地进行测试,有针对性地优化,而不是很无脑地优化整个流程。其实我们的优化准则永远是找出第一大问题,再进行优化。下面谈一些我们的经验和教训。
张相於:当当推荐数据系统架构实践
推荐系统虽然变得很复杂,但总体就是对算法调优,然后变成好多算法,架构不行就换架构这样一个思路。而且架构是水到渠成的,不是杞人忧天,不要过度设计算法。避免拿来主义,还是要探索自身特点。互联网时代,技术发展相对较快,也比较前进,这就容易产生浮躁的氛围,不要看到好的技术,立马就拿来用,先审视是否符合自己的业务特点,毕竟我们真正的目的还是要提升业务。另外,不要怕混乱,混乱其实代表着存在发展空间。最后,快速生长,逐步重构,也是每一个推荐系统和软件工程系统需要遵循的特点。
今天的分享到此结束,谢谢大家!