深入浅出排序学习:写给程序员的算法系统开发实践

对于那些由系统开发工程师负责在线排序架构的团队来说,本文会采用通俗的例子和类比方式来阐述算法部分,希望能够帮助大家更好地理解和掌握排序学习的核心概念。如果是算法工程师团队的同学,可以忽略算法部分的内容。本文的架构部分阐述了美团点评到店餐饮业务线上运行的系统,可以作为在线排序系统架构设计的参考原型直接使用。该架构在服务治理、分层设计的理念,对于保障在线排序架构的高性能、高可用性、易维护性也具有一定的参考价值。包括很多具体环节的实施方案也可以直接进行借鉴,例如流量分桶、流量分级、特征模型、级联模型等等。

总之,让开发工程师能够理解排序学习算法方面的核心概念,并为在线架构实施提供细颗粒度的参考架构,是本文的重要目标。

机器学习涉及优化理论、统计学、数值计算等多个领域。这给那些希望学习机器学习核心概念的系统开发工程师带来了很大的障碍。不过,复杂的概念背后往往蕴藏着朴素的道理。本节将尝试采用通俗的例子和类比方式,来对机器学习和排序学习的一些核心概念进行揭秘。

典型的机器学习问题,如下图所示:

机器学习模型或算法(Model/Algorithm)会根据观察到的特征值(Feature)进行预测,给出预测结果或者目标(Prediction/Target)。这就像是一个函数计算过程,对于特定X值(Feature),算法模型就像是函数,最终的预测结果是Y值。不难理解,机器学习的核心问题就是如何得到预测函数。

Wikipedia的对机器学习定义如下:

“Machinelearningisasubsetofartificialintelligenceinthefieldofcomputersciencethatoftenusesstatisticaltechniquestogivecomputerstheabilitytolearnwithdata,withoutbeingexplicitlyprogrammed.”

机器学习的最重要本质是从数据中学习,得到预测函数。人类的思考过程以及判断能力本质上也是一种函数处理。从数据或者经验中学习,对于人类来说是一件再平常不过的事情了。例如人们通过观察太阳照射物体影子的长短而发明了日晷,从而具备了计时和制定节气的能力。古埃及人通过尼罗河水的涨落发明了古埃及历法。

又比如人们通过观察月亮形状的变化而发明了阴历。

如果机器能够像人一样具备从数据中学习的能力,从某种意义上讲,就具备了一定的“智能”。现在需要回答的两个问题就是:

在回答这个问题之前,我们先看看传统的编程模式为什么不能称之为“智能”。传统的编程模式如下图所示,它一般要经历如下几个阶段:

在这种编程模式下,如果一个问题被规则覆盖,那么计算机程序就能处理。对于规则不能覆盖的问题,只能由人类来重新思考,制定新规则来解决。所以在这里“智能”角色主要由人类来承担。人类负责解决新问题,所以传统的程序本身不能称之为“智能”。

所以,“智能”的一个核心要素就是“举一反三”。

在讨论这个问题之前,可以先回顾一下人类是怎么掌握“举一反三”的能力的?基本流程如下:

机器学习专家从人类的学习过程中获得灵感,通过三个阶段让机器具备“举一反三”的能力。这三个阶段是:训练阶段(Training)、测试阶段(Testing)、推导阶段(Inference)。下面逐一进行介绍。

训练阶段如下图所示:

测试阶段如下图所示:

推导阶段如下图所示:

Wikipedia的对排序学习的定义如下:

“Learningtorankistheapplicationofmachinelearning,typicallysupervised,semi-supervisedorreinforcementlearning,intheconstructionofrankingmodelsforinformationretrievalsystems.Trainingdataconsistsoflistsofitemswithsomepartialorderspecifiedbetweenitemsineachlist.Thisorderistypicallyinducedbygivinganumericalorordinalscoreorabinaryjudgment(e.g.“relevant”or“notrelevant”)foreachitem.Therankingmodel’spurposeistorank,i.e.produceapermutationofitemsinnew,unseenlistsinawaywhichis“similar”torankingsinthetrainingdatainsomesense.”

列表排序的目标是对多个条目进行排序,这就意味着它的目标值是有结构的。与单值回归和单值分类相比,结构化目标要求解决两个被广泛提起的概念:

列表排序的评价指标体系总来的来说经历了三个阶段,分别是PrecisionandRecall、DiscountedCumulativeGain(DCG)和ExpectedReciprocalRank(ERR)。我们逐一进行讲解。

Precision的定义如下:

Recall的定义如下:

P-R的有两个明显缺点:

对于排序引擎而言,不同请求的结果列表长度往往不相同。当比较不同排序引擎的综合排序性能时,不同长度请求之间的DCG指标的可比性不高。目前在工业界常用的是NormalizedDCG(nDCG),它假定能够获取到某个请求的前p个位置的完美排序列表,这个完美列表的分值称为IdealDCG(IDCG),nDCG等于DCG与IDCG比值。所以nDCG是一个在0到1之间的值。

nDCG的定义如下:

IDCG的定义如下:

ERR的定义如下:

做列表排序的工程师们经常听到诸如Pointwise、Pairwise和Listwise的概念。这些是什么东西呢,背后的原理又是什么呢?这里将逐一解密。

首先我们要告诉学者每个学生的各种属性,这就像我们要告诉排序算法文档特征。对于目标值,我们却有三种方式来告诉学者:

典型的信息检索包含两个阶段:索引阶段和查询阶段。这两个阶段的流程以及相互关系可以用下图来表示:

索引阶段的工作是由索引器(Indexer)读取文档(Documents)构建索引(Index)。

查询阶段读取索引做为召回,然后交给TopnRetriever进行粗排,在粗排后的结果里面将前n个文档传给Reranker进行精排。这样一个召回、粗排、精排的架构最初是由Google提出来的,也被称为“Two-PhaseScheme”。

索引部分属于离线阶段,这里重点讲述在线排序阶段,即查询阶段。

在线排序架构主要面临三方面的挑战:特征、模型和召回。

三大挑战内部包含了非常多更细粒度的挑战,孤立地解决每个挑战显然不是好思路。在线排序作为一个被广泛使用的架构值得采用领域模型进行统一解决。Domain-drivendesign(DDD)的三个原则分别是:领域聚焦、边界清晰、持续集成。

基于以上分析,我们构建了三个在线排序领域模型:召回治理、特征服务治理和在线排序分层模型。

经典的Two-PhaseScheme架构如下图所示,查询阶段应该包含:召回、粗排和精排。但从领域架构设计的角度来讲,粗排对于精排而言也是一种召回。和基于传统的文本搜索不同,美团点评这样的O2O公司需要考虑地理位置和距离等因素,所以基于LBS的召回也是一种召回。与搜索不同,推荐召回往往基于协同过滤来完成的,例如User-BasedCF和Item-BasedCF。

综上所述,召回总体而言分成四大类:

传统的视角认为特征服务应该分为用户特征(User)、查询特征(Query)和文档特征(Doc),如下图:

这是比较纯粹的业务视角,并不满足DDD的领域架构设计思路。由于特征数量巨大,我们没有办法为每个特征设计一套方案,但是我们可以把特征进行归类,为几类特征分别设计解决方案。每类技术方案需要统一考虑性能、可用性、存储等因素。从领域视角,特征服务包含四大类:

如下图所示,典型的排序流程包含六个步骤:场景分发(SceneDispatch)、流量分配(TrafficDistribution)、召回(Recall)、特征抽取(FeatureRetrieval)、预测(Prediction)、排序(Ranking)等等。

按照DDD的设计原则,我们设计了如下在线排序分层模型,包括:场景分发(SceneDispatch)、模型分发(ModelDistribution)、排序(Ranking)、特征管道(FeaturePipeline)、预测管道(PredictionPipeline)。我们将逐一进行介绍。

场景分发一般是指业务类型的分发。对于美团点评而言包括:分平台、分列表、分使用场景等。如下图所示:

模型分发的目标是把在线流量分配给不同的实验模型,具体而言要实现三个功能:

流量的定义是模型分发的一个基础问题。典型的流量包括:访问、用户和设备。

如何让一个流量稳定地映射到特定模型上面,流量之间是否有级别?这些是模型分发需要重点解决的问题。

采用如下步骤将流量分配到具体模型上面去:

举个例子来说,如上图所示,所有流量分为32个桶,A、B、C三个模型分别拥有37.5%、25%和37.5%的配额。对应的,A、B、C应该占据12、8和12个桶。

为了确保模型和流量的正交性,模型和流量的HashKey采用不同的前缀。

每个团队的模型分级策略并不相同,这里只给出一个建议模型流量分级:

做实验的过程中,需要避免新实验流量对老模型流量的冲击。流量群体对于新模型会有一定的适应期,而适应期相对于稳定期的效果一般会差一点。如果因为新实验的上线而导致整个流量群体的模型都更改了,从统计学的角度讲,模型之间的对比关系没有变化。但这可能会影响整个大盘的效果,成本很高。

为了解决这个问题,我们的流量分桶模型优先为模型列表前面的模型分配流量,实验模型尽量放在列表尾端。这样实验模型的频繁上下线不影响主力和潜力流量的用户群体。当然当发生模型流量升级的时候,很多流量用户的服务模型都会更改。这种情况并不是问题,因为一方面我们在尝试让更多用户使用更好的模型,另一方面固定让一部分用户长期使用实验流量也是不公平的事情。

排序模块是特征模块和预测模块的容器,它的主要职责如下:

特征管道包含特征模型(FeatureModel)、表达式(Expression)、原子特征(AtomicFeature)、特征服务代理(FeatureProxy)、特征服务(FeatureService)。如下图所示:

特征管道要解决两个核心问题:

完整的特征获取流程如下图所示,具体的流程如下:

//包含特征获取和特征算子计算所需的meta信息publicclassFeatureModel{//这是真正用在Prediction里面的特征名privateStringfeatureName;//通过表达式将多种原子特征组合成复合特征。privateIExpressionexpression;//这些特征名是真正交给特征服务代理(FeatureProxy)去从服务端获取特征值的特征名集合。privateSetoriginalFeatureNames;//用于指示特征是否需要被级联模型转换privatebooleanisTransformedFeature;//是否为one-hot特征privatebooleanisOneHotIdFeature;//不同one-hot特征之间往往共享相同的原始特征,这个变量>用于标识原始特征名。privateStringoneHotIdKey;//表明本特征是否需要归一化privatebooleanisNormalized;}表达式(Expression)表达式的目的是为了将多种原始特征转换成一个新特征,或者对单个原始特征进行运算符转换。我们采用前缀法表达式(PolishNotation)来表示特征算子运算。例如表达式(5-6)*7的前缀表达式为*-567。

复合特征需要指定如下分隔符:

例如:表达式v1+14.2+(2*(v2+v3))将被表示为$O+_O+_Vv1_C14.2_O*_C2_O+_Vv2_Vv3

原子特征(或者说原始特征)包含特征名和特征值两个部分。原子特征的读取需要由4种实体类共同完成:

一个典型的例子如下图所示:

复杂系统设计需要充分的利用语言特性和设计模式。建议的优化点有三个:

在特征读取里面,需求方是模型,模型仅仅提供一个特征名(FeatureName),不关心怎么读取对应的特征值。具体的ScoreEnum类是具体的提供方,具体的ScoreEnum从POJO里面读取特定的特征值,并转换成ScoringValue交给模型。

特征服务代理负责远程特征获取实施,具体的过程包括:

预测管道包含:预测(Prediction)、级联模型(CascadeModel)、表达式(Expression)、特征转换(Transform)、计分(Scoring)和原子模型(AtomicModel)。

预测本质上是对模型的封装。它负责将每个列表实体的特征转化成模型需要的输入格式,让模型进行预测。

我们构建级联模型主要是基于两方面的观察:

举例如下图所示,我们自上而下进行讲解:

在这里原子模型指的是一种原子计算拓扑结构,比如线性模型、树模型和网络模型。

常用的模型像LogisticRegression和LinearRegression都是线性模型。GBDT、RandomForest都是树模型。MLP、CNN、RNN都是网络模型。

这里定义的原子模型主要的目的是为了工程实施的便利。一个模型被认定为原子模型有如下两个原因:

根据我们所掌握的知识,特征治理和召回治理的思路是一种全新的视角,这对于架构排序系统设计有很大的帮助。这种思考方式同样也适用于其他领域模型的构建。与Google提供的经典Two-PhaseScheme架构相比,在线排序分层模型提供了更细颗粒度的抽象原型。该原型细致的阐述了包括分流、A/B测试、特征获取、特征算子、级联模型等一系列经典排序架构问题。同时该原型模型由于采用了分层和层内功能聚焦的思路,所以它比较完美地体现了DDD的三大设计原则,即领域聚焦、边界清晰、持续集成。

THE END
1.在线编程——排序算法总结有哪些算法是在线排序算法在线编程——排序算法总结 找实习,阿里一面遇到手写快排,写出来感觉没错(VS2013能通过),但在阿里的测试平台上运行未通过。细思极恐,赶紧总结一波。有幸看到SteveWang的两篇博客:排序算法总结(1)与排序算法总结(2)以及基数排序、计数排序与桶排序,总结的相当详细,我这里算是重新拜读一遍,结合自己的理解写下来。 https://blog.csdn.net/zichen_ziqi/article/details/80419920
2.12VB排序算法双向选择排序视频在线观看超清720P高清 540P 2.0x1.5x1.25x1.0x0.8x 50 跳过片头片尾是|否 恢复默认设置 首页>原创> 12、VB排序算法_双向选择排序 笑口常开 订阅0 分享: 直播热点 下载APP领会员 直播中 小言儿~ 直播中 丽丽感谢家人宠爱 直播中 悠然~https://www.56.com/u85/v_MTY1MDg1NjEw.html
3.MLK机器学习常见算法优缺点了解一下腾讯云开发者社区决策树算法 分类算法 聚类算法 集成算法(AdaBoost算法) 人工神经网络算法 排序算法 关联规则算法(Apriori算法) 01 决策树算法 决策树优点 1、决策树易于理解和解释,可以可视化分析,容易提取出规则。 2、可以同时处理标称型和数值型数据。 3、测试数据集时,运行速度比较快。 https://cloud.tencent.com/developer/article/1485883
4.由浅入深玩转快速排序算法在线工具 首页 话题 文库 我的 更多 商店 码库 Wiki 软件 网址 文章 文稿 书库 图册由浅入深玩转快速排序算法 出处:mp.weixin.qq.com 摘要本文带你了解被誉为20世纪科学和工程领域的十大算法之一的“快速排序”算法。阅读原文 xiaozi 于2024-04-26 分享https://tool.lu/index.php/article/69v/detail
5.如何准备算法面试?算法面试不是高考。 把这个过程看作是和面试官一起探讨一个问题的解决方案。 对于问题的细节和应用环境,可以和面试官沟通。 这种沟通本身很重要,它暗示着你思考问题的方式。 例子 我们需要对一组数据进行排序 设计排序接口,标准库的设计,业务中排序算法。 排序是基础操作,很重要。 解决 快速排序算法:O(nlogn)https://www.imooc.com/article/36452
6.Python3实现对列表按元组指定列进行排序的方法分析python这篇文章主要介绍了Python3实现对列表按元组指定列进行排序的方法,结合实例形式分析了Python3针对列表排序的常见操作技巧与注意事项,需要的朋友可以参考下本文实例讲述了Python3实现对列表按元组指定列进行排序的方法。分享给大家供大家参考,具体如下:Python版本: python3.+ 运行环境: Mac OS IDE: pycharmhttps://www.jb51.net/article/153239.htm
7.快速排序算法算法原理 快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为两个子序列(sub-lists)。 步骤为: 从数列中挑出一个元素,称为“基准”(pivot), 重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(相同的数可以到任何一边)。在这个分割结束之后,该基准就处于数列https://tool.dreamlikes.cn/algorithm/quicksort
8.MySQL性能优化51CTO博客从数据库处理的查询复杂度来看,第一种为两类很简单的查询,第二种有一条SQL语句有GROUP BY 操作,比第一种解决方案增加了排序分组操作; 从应用程序结果集处理来看,第一种11次结果集的处理,第二种2次结果集的处理,但是第二种解决方案中第二次结果处理数量是第一次的10倍; https://blog.51cto.com/u_13661275/3223259
9.2020届计算机科学方向毕业设计(论文)阶段性汇报图排序的硬件加速器设计 Gorder图排序算法的简单介绍,硬件加速Gorder的基本思路,模拟实验结果。 蒋泽天 多图的批量协同匹配与在线增量式匹配方法第一阶段工作汇报 多图的批量协同匹配与在线增量式匹配方法第一阶段工作汇报,主要包括研究内容回顾,先前方法复原情况,以及理论分析内容进展。 https://zhiyuan.sjtu.edu.cn/html/zhiyuan/announcement_view.php?id=3709
10.快速排序在线编程k6k4在线编程:现在给定一个整数数组,请用快速排序算法对该数组进行排序。https://k6k4.com/code/sshow/aaoxpweyb1597887379356
11.排序算法总结菜鸟教程排序算法 平均时间复杂度 冒泡排序 O(n2) 选择排序 O(n2) 插入排序 O(n2) 希尔排序 O(n1.5) 快速排序 O(N*logN) 归并排序 O(N*logN) 堆排序 O(N*logN) 基数排序 O(d(n+r)) 一. 冒泡排序(BubbleSort) 基本思想:两个数比较大小,较大的数下沉,较小https://www.runoob.com/w3cnote/sort-algorithm-summary.html
12.重现当年AlphaGo神来之笔,DeepMind新AI发现提速70%排序算法因为,无论是排序还是哈希,它们的应用场景从在线购物、云计算到供应链管理等各个场景都能用到,每天会被调用上亿次! 不过,如DeepMind所说: 大家千万不要太兴奋了,AI的力量用于代码效率提升才刚刚开始。 Alpha家族“新贵”发现更快排序算法 这个AI名叫AlphaDev,属于Alpha家族“新贵”,并且基于AlphaZero打造(就是2017年https://m.thepaper.cn/wap/v3/jsp/newsDetail_forward_23406067
13.在线数字排序器对数字进行排序 我们的在线数字排序器使用快速排序算法,其时间复杂度在平均情况下为 O(n log n),在最坏情况下为O(n2),尽管这种行为很少见。快速排序通常被认为是最快的排序算法,并且有许多应用。 Search 数学 ? 最小二乘线性回归计算器? 四分位数间距计算器? 卡方计算器? Z分数计算器? https://www.bchrt.com/tools/number-sorter/
14.智能开放搜索OpenSearch智能搜索搜索引擎大数据基于阿里巴巴自主研发的大规模分布式搜索引擎搭建的一站式智能搜索业务开发平台,目前为包括淘宝、天猫在内的阿里集团核心业务提供搜索服务支持。通过内置各行业的查询语义理解、机器学习排序算法等能力,以及充分开放的文本向量检索引擎能力,助力开发者快速搭建智能搜索服务。 https://www.aliyun.com/product/opensearch
15.快速排序(quicksort)JasonDamon快速排序是由东尼·霍尔所发展的一种排序算法。在平均状况下,排序n个项目要Ο(nlogn)次比较。在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见。事实上,快速排序通常明显比其他Ο(nlogn) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来。(出自维基百科) https://www.cnblogs.com/Jason-Damon/archive/2013/06/15/3138137.html