23 KiB
关于这个分享
第一次AI分享交流会的时候,大家建议首次的分享可以先从经典开始。所以我先制个经典:把过去十余年推荐技术发展脉络跟大家梳理下,介绍下主要工作、技术发展思想和规律。本次抛砖引玉,以思想的穿针引线为主。后续算法团队会分享一些具体方向方法的更多细节。
排序整体架构上分为:召回、粗排、精排/排序、重排几个阶段。本次分享聚焦在排序和召回两个方向。
业内推荐系统发展阶段
从大的技术变革的角度看,目前主要分成三个大阶段:
• **传统机器学习技术(Before 2013年):**算法上采取LR和GBDT为主要算法,交叉信息主要通过特征交叉实现;工程框架较为简单,模型训练依赖自定义的分布式训练框架。
• **大规模离散DNN技术(2014~2025年?):**精彩的十年,自从14年业界突破了大规模离散DNN的训练(如何稳定收敛),离散DNN以百分位AUC巨大提升很快成为业界主流技术框架。特征交叉方面,人工交叉和模型交叉技术层出不穷;自定义训练框架出现了homura、mio、abucus,并在2016年到19年影响了一众互联网公司,各家或多或少能看到上述框架的影子;从16年阿里开始研究XDL开始,以tensorflow+自定义的parameter server逐步成为主流解决方案,各大公司纷纷拥有内部自定义的解决方案。携程在20年开始建设分布式大规模离散DNN训练和serving框架,也属于tensorflow+自定义ps的技术路线。
• **生成式推荐技术(2025年~?):**受大模型技术思想的影响,开始出现的技术趋势。得益于硬件发展和推理效率的提升,可以依赖模型强大的交叉能力来做模型交叉;并以端到端的解决方案,在挑战传统的级联式推荐架构。发展中的技术,方案还存在探索和发展。
为啥DNN比LR和GBDT在推荐里面有发展前途?
在本小节中,我们详细介绍对比下这三种模型设计。分类模型在推荐场景下最常见(比如点击率、转化率模型),分类模型要做的是找到决策边界来区分正负样本,如下图所示:
Figure 1: LR,GBDT和DNN的决策边界
LR(Logistic Regression,逻辑回归)
在LR里,决策边界函数是线性的,线性也决定了LR的白盒属性。在Figure 1公式中,权重矩阵w和w(0)定义了决策边界的线性函数。模型的优点是:我们可以通过模型的权重大小,解释特征的重要性;同时LR也支持离散特征和增量更新。模型的缺点是:线性决策边界这个假设太强,会让模型的精度变小;另外,模型的可扩展性程度低。
GBDT(Gradient Boosting Decision Tree,梯度提升决策树)
在GBDT中,决策边界是非线性的;模型通过将样本空间分而治之的方式,来提高模型精度。在Figure 1的GBDT图中,tree_i(∙)表示其中一棵树,α(i)是树的权重。这个模型的优点是:树模型可以计算每个特征的重要性程度,来获得一些可解释性;同时模型比LR有更高的精度。模型的缺点是:不支持大规模的离散模型,不支持增量更新;模型可扩展性程度低。
DNN(Deep Neural Network,深度神经网络)
在DNN中,决策边界是高度非线性的。在Figure 1的DNN图中,g(i)表示模型的其中一层非线性层。我们知道:计算机通过与或非这种简单的逻辑,可以表达各种复杂的对象:音频,视频,网页等。而DNN每一层网络比与或非逻辑更加复杂,DNN通过多层神经元叠加,成为一个万能函数逼近器:在理想情况下,只要有足够的数据量,不论我们实际的决策边界如何复杂,我们都可以通过DNN来表达。同时DNN支持大规模离散DNN,支持增量更新,支持根据业务场景进行灵活定制各种网络结构。这个模型的缺点是:1)特征经过不同层交叉,交互耦合关系过于复杂,而导致可解释性不好,且MLP的交叉效率不高;2)在样本量比较稀疏的小场景存在过拟合的风险,模型过于复杂反而导致此时不通用,这时一般需要加入规则来进行约束和矫正;3)工程复杂度在我们用不同结构的时候所有不同。我们真实物理世界很多问题的决策边界,应该是高度非线性的,所以采取更符合物理世界的模型理论上限更高;再加上互联网世界海量的用户行为数据,促成了DNN模型在业界的地位。
如下表格简单总结了各类酒店排序模型的特点:白盒模型虽然具有高可解释性,但精度较低,且精度到达一定程度时进一步提升的空间较小;黑盒模型精度提升明显,但可解释性难度也高。
点击图片可查看完整电子表格
推荐系统解决方案
虽然GBDT后来在xgboost、lightgbm这些经典算法出来后,在很多中小推荐场景成为涨点的好帮手,但在业内大规模推荐场景,好景不长:好不容易做上线,很快就被连续DNN以及后续的离散DNN(10年经典)解决方案颠覆。但在这之前,大规模离散LR在业内属于主流解决方案(比如百度的ctr、阿里妈妈的广告模型)。但不可否认,gbdt是个好模型。
经典方法**-大规模离散LR**
特征分为连续特征和离散特征。连续特征属于统计特征,典型例子:身高、用户过去30天的点击率等。离散特征的例子:userid、点击序列(itemid list)、itemid。这两个特征各有特点:
• **连续特征:**可以直接作为模型输入使用,具备良好的泛化性。
• **离散特征:**要通过embedding映射(embedding size可以是1;早期离散LR的weight可以看作embedding size=1)才能给模型使用。离散特征命中就有,没命中就没有,具备良好的记忆型:用户点击了酒店A、B和C,在统计特征里面,是点击3次;在离散特征里面是记住了哪3次;对连续特征用户点击【A、B、C】和点击【B、C、D】是一样的,但是对离散特征而言,用户点不同酒店列表结果是不一样的。
通过连续模型的泛化性叠加离散特征的记忆型,是业界推荐算法常见设计,在2014年的离散DNN落地的时候就有了。所以,很难说google 2016年的wide & deep model创造了泛化性+记忆性模型范式。
正则和模型训练
LR模型容易过拟合,在离散LR的场景下,L1正则是常规手段。这样做有两个好处:模型不过拟合了;L1正则导致的稀疏性,大幅度节省线上的存储和计算成本。但L1是不可导的,只有subgradient,这对依赖梯度下降法的算法是个问题。为了提升L1约束下的离散LR快速收敛,业界主要采取的方法包括OWL-QN和Coordinate descent(李沐老师在2012年百度的工作,取名Darlin。该方法上线也是经过了一番折腾,AUC提升2个千分点,委实不容易;后来李沐去CMU读PhD,开启了开挂人生)。
线性模型的非线性努力
线性模型交叉能力为0,线性决策边界的假定影响了模型精度上限。所以业界也出现了一些增加线性模型非线性能力的解决方案:比如百度的Pegasus(无paper)、阿里的LS-PML(Large-Scale Picece-wise Linear Model,又称为Mixed LR),Facebook的LR+GBDT,广义线性模型Factorization Machine。前三个方法本质上都可以看作通过聚类的方法来对模型引入非线性;而FM通过模型显式交叉的方式来引入非线性。
这些方法都在努力突破线性模型的局限性,然而线性模型表达能力毕竟有限,况且他们一些方法是分为两阶段的,不是**端到端(算法发展追求端到端设计来减少信息折损,后面还有很多例子)**的学习方案。
大规模离散****DNN
连续DNN在业内存在时间也非常短,我们直接进入2014年开启的全新解决方案。既然离散特征有很好的记忆型,表达精准;非线性DNN模型表达能力强,那为啥不上来就整大规模离散DNN呢?原因简单而复杂,下面两个方面都未准备好:
• 算法层面:在2014年前,业界LR还没有玩明白呢,训练模式还是batch模式,online learning这种streaming训练方法还在孕育。说到非线性模型,连续版本的ANN、DNN也在摸索,还在为落地实践踩坑,好不容易模型收敛了取得了离线效果,结果放到线上又被A/B效果怼回来分析原因。回头看,坑真的非常多:从参数初始化、学习方法、数据处理任何细节不到位都会导致最终失败。
• 工程层面:大规模离散DNN这套技术栈回头看,对工程要求也更高。首先工程需要提升线上线下一致性的工艺,不然离散DNN会放大不一致让线上效果变差;然后相比LR和GBDT,DNN结构可改动的地方非常多,所以在模型训练框架层面既要能支持万亿离散特征的扩展性,又要能支持各类DNN结构的灵活性。Tensorflow是2015年开源,pytorch是2017年才出稳定版;即使到了18年这两个最大的开源训练框架,对大规模离散DNN也支持的不好。
百度重视AI技术,其实早在2012年的时候内部就有了paddle(一个可扩展性的DNN训练框架),并在13年开始逐步承接了凤巢广告模型的model inference。Paddle一直到16年才宣布开源,不过这个闭源系统在14年的时候,代码保密工作做的相当不错,哪怕是对核心的凤巢算法团队也是一视同仁:丝毫没有主动接入当时国内最大的业务场景(只有少部分同学可以用Paddle调研连续DNN),做大做强的打算。推荐团队不能使用Paddle定制训练框架,商业价值驱动下,业务探索到了这个地步又有相关诉求,又当如何呢?
工欲善其事必先利其器
没办法的情况下,一开始离散DNN训练框架在之前离散LR的框架上改了改,先做个POC。不过这种显然不是长久之策,离散LR框架要硬编码的地方比较多,DNN网络结构变来变去又灵活:总不能每次调个模型结构要动代码吧。于是有同学开始思考把不同类型的神经网络layer抽象出来,把网络结构定义给配置化。
适度内卷是有价值的,从结果看,当时一个凤巢团队2年内搓出来好几个DNN训练框架:算法同学开发了homura、mio、elf三个框架;后来工程团队在算法的mio的基础上改出来abacus。同一时间,能配置驱动的DNN训练框架Caffe,在2014年发布,让大佬Yangqing Jia一战封神;当然caffe不是为推荐场景设计的,不支持当时还非常冷门的大规模离散DNN模型。
目前说到的几个训练框架都是c++写的,要定制化得动c++,不是太灵活。Tensorflow在2015年已经开源了,于是在2016年就有人想,是不是可以把目前c++框架里面的Parameter Server单独拆出来,集成到Tensorflow里面去:这样不就又有了parameter server支持万亿离散特征的能力,又有tensorflow的灵活性么。于是诞生了XDL项目。关于parameter server的核心思想,大家可以参考下沐神的成名作:Scaling distributed machine learning with the parameter server。后面业界基本上各大公司都采取了定制化的tensorflow方案。Pytorch没有抢到这个风头,是因为tensorflow稳定、可靠的tf serving更适合做线上服务。
我司技术栈主要是java的,所以在2020年的时候,我基于miniconda+cmake搭建了c++ toolchain,经历过一番踩坑和折腾后,在这个基础上构建了离散DNN训练框架,并陆续开发了tensorflow 1.14和tensorflow 2.0定制版,并和董锐团队一起构建了eagle推荐系统。目前线上公司全量的版本是tensorflow 1.14版本,不过动态图是未来趋势,实际使用也会更加方便,后续技术中心会推进tensorflow 2.0+版本的适配和落地。算法这边,酒店排序是在21年后逐步切换到大规模离散DNN技术栈上去的(第一个版本相对当时核心技术栈XGBOOST大幅度提升3个百分点)。
简单说下大规模离散DNN训练框架的设计想法。其实简单说来就要解决一个问题,推荐里面离散ID特征很大且不断自增和tensorflow looking up table是静态的设计之间的矛盾:
• 量大:那就做分布式存储。
• 自增:那就做分布式查询,然后把每次batch用到的所有ID特征查询出来,把结果包装成静态的looking up table给tensorflow用。
在这种思想下,tensorflow本质上就是一个定义计算图和计算梯度的工具;parameter server本质上是一个带梯度更新策略的“redis”。如果能把开发中_跟模型收敛碰到的各种坑给解决掉_,就可以做出离散DNN模型训练框架了。如下面的简图:
推荐算法的发展
经典的开端
经典的paper都在这个图上,有兴趣的可以读下:
基本上大家核心都要解决一个问题:信息交叉的问题。我们上面提到MLP网络的交叉效率不是很高,所以比较依赖显式的交叉设计来提升效果。当然在交叉这块,业界主要是两个大的流派:特征交叉和模型交叉:
• 特征交叉:依赖人工经验和设计,可解释性强,拿业务指标直接。缺点是过细的人工交叉会让系统特征数目爆炸(比如item跟item的交叉),提升了线上存储的代价。
• 模型交叉:依赖模型结构设计,写paper容易(上面的经典paper都是模型方面的),能够让交叉存储代价很低,但会提升线上计算代价。好在现在算力越来越便宜了。
目前酒店推荐特征交叉和模型交叉在提升模型精度上面的贡献大概是7:3开。PDD这种业务指标PK环境下,也比较注重业务理解和特征设计。现在随着算法技术的发展,类似transformer这种信息交叉结构也普遍应用在推荐系统中(我们在酒店V8模型中,就用到transformer来提升行为序列编码效果)。在解决清楚信息交叉之后,就可以针对具体业务场景的目标,定义损失函数,来训练模型了。
算法持续优化**-**案例一
用户行为序列包含用户所有的个性化信息,如何更好的做序列建模,是推荐算法重点研究方向。我们也可以通过这个案例看到算法迭代的一些规律:
• DIN(2018年):是模型交叉方案的经典之作。用户历史上会有很多行为,不是每个行为对当前物品推荐具备相同的权重。比如“鼠标”这个历史商品对预测“键盘”这个商品点击率的作用肯定大于T-shirt或者洗面奶。从模型角度来说,在建模过程中给不同历史行为应该给予不同的“注意力”权重:跟当前物品相似大的物品,权重更大。
• DIEN(2019年):当然上述建模忽略了行为的时间信息,原则上,离当前时间越近的历史行为应该更能表达出用户的兴趣迁移。用户行为兴趣迁移太常见了,可能上周还想买衣服,但是本周就想买电子产品了。所以DIEN在DIN的基础上,引入了GRU这种网络来学习用户的行为偏好迁移。
• SIM(2020年):上面的方法解决了部分问题,实际上因为线上Serving性能的考虑,我们的行为序列是做了长度截断的。然而离线调研会发现,如果完全不考虑Serving性能,尽可能多的用到用户行为序列,对线上指标提升会有好处。但是历史行为又不是所有的行为都同等重要,那么是不是就可以先根据当前商品,来快速的找到相关的历史行为(称为GSU-General Search Unit,比如可以根据商品品类来快速筛选),然后再在更小的集合上做DIEN的建模(称为ESU-Exact Search Unit)。是不是像极了现在的RAG-通过找到相关的信息,来减少算法的代价。
• ETA(2021年)和SDIM(2022年):虽然前面的方法解决了部分问题,但是GSU和ESU比毕竟是个两阶段的方法(不是end-2-end的),难以保障两个阶段的一致性,所以研究更加端到端的方案就成了继续涨点的思路。如果能解决GSU阶段的性能问题,不就可以让GSU和ESU保持端到端学习了么。所以快速根据向量计算相似度选Top-K的方法,就可以考虑进来。于是在GSU阶段引入了LSH这种快速索引方法。
• TWIN-1(2023年)和TWIN-2(2024年):虽然ETA和SDIM是end-2-end的,但是GSU阶段采取了LSH,毕竟跟ESU阶段要的attention还是不太一样。所以索性想办法让GSU采取跟ESU一样的结构,并提升attention的计算效率。TWIN-2等后面分享召回的时候,会看到一些思想端倪,先别急。
从上面例子可以看到,端到端建模一直是算法提升效果的一个思路。之所以拆成多个阶段,受限于线上性能约束和技术发展阶段限制。
既然一个小小的序列建模,都要端到端;那整个推荐系统分成召回、粗排、精排和重排,是不是也可以端到端?这就有了目前生成式推荐的一些尝试OneRec(2025年)、UniROM(2025年)、EGA-V2 (2025年)。当然end-2-end取代传统推荐架构代价比较高,生成式推荐也不都是一上来就以这个为目标的,有些设计是为了减少人工特征工程负担和利用最新的Transformer架构的强大交叉能力,比如HSTU(2024年)、MTGR (2025年)、RankGPT(2025年)。
浅谈个性化召回**-**案例二
跟大家分享其中一个召回技术分支的发展历程,给相关方向算法研究思路提供参考。Embedding目前已经为大家熟知了,基于embedding的ANN(Approximate Nearest Neighborhood)检索算法(LSH、Annoy、HNSW等)也是家喻户晓。业界这块发展也是几经折腾:
• Word2Vec(2013年):这是NLP里面,从语言序列里面学习每个word的经典方法。该方法可以把每个离散的词表达成Dense embedding向量,使得相似语义的向量欧式距离更近。于是有人想,用户行为序列其实也是一个序列,丢进去是不是也可以得到每个行为Item的embedding表达,线上通过embedding索引的方式来进行召回呢?于是Item2Vec(2016年)有了Word2Vec在推荐场景的应用。KDD 2018年还有一篇airbnb的best paper基于这个传统方法,做了细致的业务定制化(Real-time Personalization using Embeddings for Search Ranking at Airbnb)。
• DeepWalk(2014年):Word2vec这种方法是建立在序列样本上的,互联网的用户和物品之间的关系其实是图结构。采取一个更符合物理规律的模型会有更好的效果,于是有了DeepWalk在推荐领域的应用。可以参考Billion-scale Commodity Embedding for E-coimmerce Recommender in Alibaba这片文章。
• Node2Vec(2016年):虽然DeepWalk解决图结构数据适配的问题,但是不够灵活。图的遍历有两种方法,DFS(深度优先搜索)和BFS(广度优先搜索)。通过DFS,我们可以有机会游走到更远的节点,让Embedding学习更加具备探索性(专业术语是结构性);通过BFS,我们更多的在当前节点邻居进行游走,可以让附近节点的embedding更加近似,让推荐更准(专业术语同质性)。推荐系统对embedding的两个能力都想要,最好有一个办法可以来取这个tradeoff,于是有了Node2Vec。
• EGES(2018年):当然前面的方法还是存在缺陷的,在推荐场景下,每个商品是有很多side information的。比如酒店有距离、星级、点评分数等等信息。如何DeepWalk的基础上引入这些side information,就诞生了Enhanced Graph Embedding with Side Information这篇文章。
• DSSM双塔模型(2016年):Word2vec这些方法虽然好用,但是模型结构还是过于简单。Word2vec模型主要做法是(以CBOW为例),是把上下文序列Embedding求和,计算跟当前Item的Embedding计算cosine相似度。如果把上下文Embedding和Item Embedding分别经过一个DNN网络,然后再做cosine相似度,不就可以增加模型的表达能力了么?于是就有了DSSM。这个召回方法,在2016年百度凤巢就上线并取得效果了。当然这里我们还要解决一个问题,就是如何减少热门Item对embedding学习造成干扰,不然每个item都会跟热门的item有相似的embedding表达:Word2vec里面发明的针对hot word打压的采样策略都可以借鉴,本质上是一样的。Facebook还有一篇文章专门来研究召回模型里面的负例采样问题。
• TDM(2018年):双塔模型的用户侧和item测信息交叉,只在最后一次层进行,交叉的太晚了,效果有折损,且跟排序产生不一致了。但是召回模型为了提升线上服务效率,又不能让用户侧和item侧在DNN底层交叉,这样就没办法单独对Item的建立索引。于是有人思考,能否想办法把索引的学习和主网络学习(不是双塔结构了,是一个DIN attention结构,DNN底层做了模型交叉)来一个co-training:这便有了Tree-based Deep Model。线上Serving的时候,通过索引树采取beam search的方法,找到最相关的top-K个节点,遍历到最后的叶子节点的Item即为召回集合。相关工作还包括字节的Deep Retrieval(2020年)和美团的Dual Augmented Two-tower(2021年)都可以值得研究下。
当然TDM复现的难度和线上落地的复杂度会比较高,通常可以建议把DSSM双塔改成三塔:增加一个浅层网络把重要的交叉特征放进来,以提升效果。这是个比较实际的思路。
算法小结
当然实际业务会比上面经典方法面临的情况要复杂:我们的问题通常是多任务和多场景的,不同场景数据放在一起如何更高效的学习和表达;在推荐里面,很难避免长尾问题和冷启动问题,这部分数据不充分,很容易混在整体分布中让主流的偏好数据带偏,除了特征个性化之外,我们如何让模型本身具备一定的个性化;我们现在的学习方法是否已经足够稳定,在数值优化层面,有没有更多的技术细节突破,以带来更多效果的提升。上面的这些问题,业界都有同学在持续不断的探索。
从业务应用层面讲,我们会面临不同的业务场景:广告推荐、游戏推荐、短视频推荐、社区内容推荐、电商推荐。因为不存在万能****“银弹”,不同业务场景需要我们算法同学根据实际业务特点,因地制宜的制定模型方案,并设计合适的产品机制,让算法发挥更大作用。



