雷锋网 AI 开发者按:素有数据挖掘“奥运会”之称的 KDD CUP ,其颁奖仪式于 2019 年 8 月 7 号在美国安克雷奇市落下帷幕。今年的 KDD CUP 共设有三个赛道,分别为 Regular ML、AutoML 与 Humanity RL ,最终结果显示,三个赛道的冠军皆由华人队伍夺得。作为 AutoML 赛道的冠军队伍,深兰科技在仪式结束后接受了 AI 开发者专访,不啬分享其在赛事中夺魁的点滴。
赛事奖状
问:今年 KDD 的 AutoML 赛道题目与“binary classification problems for temporal relational data”相关(题目详情请戳:https://www.4paradigm.com/competition/kddcup2019),能否请你们谈一谈相关工作的意义和挑战?
答:时序关系型数据在在线广告、推荐系统、金融市场分析、医疗等应用场景中非常常见,人们往往需要利用这样的数据去构建机器学习模型,并应用机器学习模型提升对应业务的效果。以在线广告点击率预测问题为例,每个样本就是向用户展示广告,样本标记为用户是否点击广告。因为是实际的服务系统,所有样本都是时序产生。
在传统的机器学习应用中,需要经验丰富的专家才能从时序关系型数据中挖掘出有效的时序信息,并加以利用来提升机器学习模型的效果。即使具备较深的知识储备,专家也需要通过不断的尝试和试错,才能构建出有价值的时序特征,并且利用好多个相关联表来提升机器学习模型的性能。此外,选择合适的机器学习模型和超参数也需要强大的机器学习专业知识作为支撑。
此次竞赛针对时序关系型数据的 AutoML 挑战赛,希望让更多的数据科学家和开发者加入其中,集思广益,从而让 AutoML 更好地利用时序关系型数据,提升模型的预测性能,让 AutoML 解决方案能够更加符合实际应用的需求。
赛题的难点主要有5个方面:
赛题数据来自于多个实际业务场景,参赛者设计的自动化机器学习算法将会在未知的五个数据集中进行学习和评估,根据五个数据集的评估结果进行综合排名。
比赛中每个数据集只给出数据类型不给出数据含义,自动根据特征类型挖掘出有效特征是一个难点。
赛题数据是时序相关的,相比较无时序的数据需要模型具备更好的泛化能力。
赛题的数据由多表给出,这就要求参赛选手能够构建一个处理多表之间多样的连接关系的自动化机器学习系统。多表数据无疑提升了对系统的稳定性的要求。
时间和内存限制严格。
本次AutoML竞赛一方面展示出了我们团队在这个领域的充分积累,另一方面我们自研的AutoML系统可以在工程项目中完美落地,为客户提供顶级的机器学习解决方案。
问:能否向我们详尽解读你们的解决方案?
答:如上图所示,我们团队基于所给数据实现了一套支持多表的AutoML框架,包括自动表连接、自动特征工程、自动特征选择、自动模型调参、自动模型融合等步骤,在时间和内存的控制上我们也做了很多优化工作。
注:深兰科技已开源相关解决方案,感兴趣者可访问 https://github.com/DeepBlueAI/AutoSmart 进行查看
数据预处理
我们通过对表结构及其属性的分析,针对不同类型的数据制定不同的数据预处理方案。如上图所示,我们去除了方差极小的数值特征,也去除了所有值都不同的类别特征。同时,在多表间的多个连接key中,我们在主表中种类最多的一个key识别为user。基于识别出的user,可以尝试在主表的category中识别出session。另外,我们尝试在category数据中识别出只有两类有效值的binary数据。我们对category、user、session、key进行重新编码,对numerical数据尝试将其转换为占用内存更少的类型,将time数据转换为容易操作的datetime类型。
多表连接
比赛给的数据结构如上图所示,表和表之间的连接关系可以分为四种,分别是1-1、1-M、M-1、M-M。因为时间和内存的限制,所以我们需要在尽可能保留信息的同时,让最后生成的表的数据规模不至于过大。而处理多表连接的方式,直接影响到后面的结果。我们针对不同的连接方式采用了不同的方法。首先将四种连接方式分成了两种类型:类型1包含了1-1、M-1,类型2包含了1-M、M-M。对于类型1,我们可以直接将副表的数据通过key合并到主表上。对于类型2,我们首先对副表做一些聚集操作,生成聚集的结果,而这些聚集的结果可以理解为和主表是类型1的关系。接下来,我们只要对生成聚集的结果做类型1的操作,直接将其合并到主表上即可。并且,对于主表和副表都有时间戳的情况下,我们将副表上离主表当前数据早且最近并且为相同key值的数据合并到主表上。
采样
因为AutoML比赛方给定的数据集大小未知,在对其进行操作处理之前首先要判断当前环境是否能够支持整个数据集共同参与特征工程及模型训练过程。我们在读入数据进入预处理之前做了一次判断,即要求训练集与测试集的总样本数不超过某一个可以接受的阈值。如训练集与测试集的总样本数过多,我们就考虑对其进行采样。
此外,在特征工程的组合特征模块中,同样用到了采样的思想。组合特征的特点是产生的特征数量多、特征工程的时间长、内存峰值高、起作用的特征数量少。因此,为了避免内存溢出,我们在做组合特征之前,在小数据集上进行特征工程,经过筛选后得到真正起作用的特征,再在整个数据集上仅做出这些有效的特征这样不仅可以减少系统运行时间也能避免内存溢出的风险。
自动特征工程
特征工程部分往往是数据挖掘竞赛的关键核心内容,也是我们团队在比赛中取得显著优势的重要因素。我们通过LightGBM模型来验证特征效果和进行自动化特征选择,如上图所示,在自动特征工程阶段,我们将特征工程根据特征组合的阶段分为多个阶段,在每一个阶段结束后,我们都会做一次特征选择来筛掉那些在这一阶段做出而不起作用的特征,来避免内存溢出并且加速最终的模型训练。为了在更短的时间内得到更有效的组合,我们先进行数据的采样,根据不同数据集的数据量大小以及特征重要性筛选出适量的不同类型的特征两两组合形成新的特征,然后在全量数据上重现有用的特征 ,在希望挖掘到有用的特征的同时,尽量减小内存溢出的风险。我们通过结合特征重要性及序列后向选择算法,设置一个阈值,将在参与模型训练中,筛出重要性较低的特征而尽可能小地损失模型精度。我们还尝试了基于特征的信息增益来对特征进行筛选,亦或是对两种筛选方法进行结合,但因为没能找到更好的切分点,最终还是使用了基于特征重要性的方法。
我们将特征分成几个模块。第一个模块是分类特征,我们对分类特征进行了均值编码,频率编码等,更充分地提取类别信息。第二个模块是实体特征,我们对每个表中的主键进行识别,将其区分出user、key、session等时序场景常见的实体(key是某种未知的实体),我们通过特征工程对这些实体进行建模,对实体的历史信息(数值特征、分类特征、时间特征等)进行不同方式的聚合。第三个模块是时序特征,我们根据时间将数据划分为多块,将上一个时间块的特征通过实体联结到下一个时间块的相同实体作为特征,这样使得模型可以有更好的时序预测能力以及泛化能力。第四个模块是组合特征,我们基于前面模块所产生的一阶特征(包括时间、类别、数值、多值类别等特征)进行多种不同组合。
同时,因为本次竞赛的时间和内存的控制比较严格,在面对百万级的数据量上,每个特征生成几乎都要控制在几秒内生成,为了满足这一要求,我们的代码加入了许多优化。比如对于类别数据在多类别数据中的位置这一特征,如果用传统的Pandas实现,时间会达到几个小时,而加入多线程之后,情况会有所改善,但是仍旧要消耗大量的时间。我们退而求其次,使用numpy来实现该特征,特征的生成时间直接到达了几十秒的级别,但是这仍旧不能满足我们的要求。最后我们对这块代码使用cython去优化,并且对cython代码进行精雕细琢,最后该特征的生成只需要几秒。
类别不平衡问题处理
我们对类别不平衡的数据在训练时做了处理。正负样本比例超过1:3时,我们采用欠采样的方式,缓和正负样本不平衡。此外,我们还尝试通过增加正样本的权重等方式来优化类别不平衡带来的问题。在模型融合的部分,我们在保留原始较少的正样本的同时,换一批负样本来进行训练,这样能够尽可能保留更多的原始数据的信息,同时缓解类别不平衡的问题。
建模
由于LightGBM在训练速度和性能都表现得很不错,我们使用LightGBM作为我们的模型。
对于参数调优,我们加入了先验知识,设置了多组不同的学习率,通过early-stopping来选择合适的学习率保证模型能训练一定的轮数,并且通过验证集选择最好的学习率。如上图所示,我们通过学习率衰减来使得LightGBM更快地收敛。由于时间的限制,我们对数据进行采样,通过对采样后的数据进行参数搜索,加快了参数调优速度,对性能只有很小的损失。
由于比赛环境对时间和内存做了严格的限制,我们在模型融合方面考虑了bagging、blending、stacking等方案,最终选用了使用bagging的方法。如上图所示,我们模拟一次简单的训练来预估真实数据集所需要的训练和预测时间,如时间不足则选择在训练时early-stopping,允许精度上的损失来保证代码能够在规定时间内运行完毕。如时间充裕,则通过当前剩余时间计算允许多少个模型进行融合。
运行时间优化
我们的时间控制在各个过程中都有体现。在自动化数据处理和自动化特征工程的过程中,我们使用Cython对编码以及一些生成效率较慢的特征进行加速。这里举一个特征为例,对于两列数据,一列为category类型的数据,一列为multi-category类型的数据,我们提前判断了两列数据的数据项集具有交集,我们要计算这一category列中的数据项在multi-category列对应的数据项集中的位置信息。比如说有有一条数据。data : [ 2137 , (134,2137,576,816) ] ,前者2137在后者的第2个位置上。所以这条数据该特征为2。如果没有出现的话,规定为0。对于这一特征,如果我们使用pandas提供的apply接口来实现,在本次竞赛的环境下,该类特征的生成需要大约几个小时的时间。考虑到DataFrame不适合做遍历,以及接口泛化性带来的性能上的损失。我们使用Numpy,做遍历来实现该特征,能够让特征的生成达到分钟级。而本次竞赛的时间和内存有严格的控制,像那些需要超过10秒才能生成的一类特征就算非常耗时的了。之后我们采用Cython,应用Cython提前编译,静态类型等机制我们将该特征的生成时间控制在了10秒内。其中生成该特征的过程中有一些细节。比如如果在Cython中继续使用Python原生类型,那么遍历的效率还是比较缓慢。但是multi-category类型的数据存储又不好离开Python原生类型的支持。考虑我们在生成特征的过程中,主要是对multi-category类型做遍历操作,所以可以使用一个数组去存储multi-category的每个数据项,并且用额外一个数组去保存每个multi-category的数据项集的长度。这样根据其长度数组和数据数组,我们就能做一个高效的遍历。在测试这段优化的过程中,纯粹的Python代码经过Cython优化,效率大概能到60秒。而经过这段优化,很轻松就能到达10秒内(测试环境就是以我们的本地计算机为主,线上环境会多一些时间)。
在模型集成部分,我们会做提前计算,记录到当前用时,通过训练模型几个轮次来计算出模型启动的时间以及模型训练每一轮数据所消耗的时间,通过这两个时间,我们能够预估出后续的参数调优,模型训练的时间。从而决定最后模型融合的数量。
时间优化前后对比
运行内存优化
在内存控制方面,我们首先实现了一个内存的监听器。我们首先完整运行一轮我们的系统,记录下内存情况,对不同数据集的内存峰值进行分析。可以发现的是,内存峰值往往就出现在几个典型的地方。比如:数据合成时、在模型开始训练时、某些特征生成时。经过分析,可以概括为几个点,其中比较典型的是数据合成时,如果使用pandas的接口pandas.concat进行数据合并,其合并过程中,会生成大约两倍当前数据内存的量。这个是显然的,因为其合并返回的结果不是就地的,而是创建出第三块内存。因此,我们将合成的过程改为按列赋值,这样合并时就几乎不存在内存峰值了。但是这么做,同时会带来较差的时间效率。所以在系统的早期,内存比较宽松的情况下,我们仍旧采用pandas的接口来进行对数据的合并。
另外,我们同样对训练预测时内存的情况进行了提前计算,在最后的特征筛选的过程中,我们会计算模拟出在生成多大的数据量下,能够完整进行系统后续的过程。从而来控制最后筛选出来的数据量。并且在最后一次特征筛选前,生成特征时,我们也会先时候小数据集进行一个模拟过程,来计算出整个过程中的内存情况,来对生成期生成的特征数量进行一个控制。
最后,我们会做一些比较精细的内存管理,在变量生命周期结束的时候,我们都会对其进行内存回收。以下是我们内存优化前后的一个对比。里面包含了比赛中给的5个数据集的运行过程中的内存情况。
内存优化前后对比
系统测试
对于系统的测试,我们分为了两个方面进行。第一个方面是测试系统的扩展性,第二个方面是测试系统的性能。
对于系统的扩展性,我们测试过如下:
对于不同的数据类型缺失的情况。
对于不同数据类型数值全为空的情况。
对于表的结构为单表、复杂多表的情况。
以及其他一系列的极限状态。而对于系统的性能方面,我们测试过如下:
扩大数据的条目,就本次竞赛的5个数据集而言,我们扩展每个数据集数据条目2倍,3倍,6倍都能够在规定的时间和内存下顺利运行。
扩大数据的字段数量,同样,我们扩展5个数据集的字段数量2倍也能够顺利运行。
构造特定的数据集,观察是否会因为某些组合特征而系统崩溃。最后测试了大约数十个构造的极端数据集都能够运行成功。
限制数据集允许运行时间,我们通过调整数据集允许运行时间,观察我们的系统是否能够自适应调整自身的运行时间。我们调整本次竞赛中原本时间就比较紧张的A数据集以及数据量较大的B数据集,将其允许的运行时间变为原来的1/2,1/3,甚至是1/4。我们的系统都能够顺利运行。
问:您认为该模型得以夺魁的原因是什么?
答:在这次竞赛中我们的工作围绕着竞赛的挑战而进行,主要有几个比较重要的过程:自动化多表数据处理、自动多表连接、自动化特征工程、自动化模型构建、选择和融合。同时为了满足竞赛的时间和内存的需求,我们在代码上做了非常多的优化工作,比如使用了多线程、Cython、预处理、提前估算等方法。最后我们的成绩相当不错,A,B榜单上均在多个任务集上有比较大的优势。
问:AutoML竞赛和其他机器学习竞赛有哪些不同?
答:与传统数据挖掘竞赛不同的是,AutoML竞赛中,参赛选手只知道数据的类型(数值变量、分类变量、时间变量、多值分类变量等),而不知道数据的含义,这毫无疑问会增加特征工程的难度,如何挖掘到有效的通用特征成为一个难点。
AutoML竞赛主要包含两个阶段,Feedback阶段和AutoML阶段,这两个阶段所使用的任务数据集是不一样的,而传统数据挖掘竞赛的A/B榜阶段都是在同一个任务不同数据集上进行测试,因此AutoML竞赛更要求参赛选手构建一套通用的AutoML系统,在不同任务上都能够取得很好效果。
AutoML竞赛严格限制运行时间和内存,如果未能在规定时间和内存内完成系统建模则无法参与最终排名,因此在系统运行过程中需要精确预估时间和内存,对耗时耗内存的部分代码需要进行深入优化。
问:当初选择参加这个比赛的原因是什么?与深兰科技的业务有哪些结合之处?
答:传统机器学习极为耗费人力、技术门槛高,也让没有机器学习背景的人无法高效利用时序关系型数据。AutoML 近年来成为了机器学习重要的研究方向。该技术在模型选择、神经架构搜索、特征工程等方面取得了较大的成功,大幅降低了机器学习的应用门槛,让没有机器学习背景的人同样可以轻松使用。这次AutoML竞赛针对时序关系型数据的 AutoML 挑战赛,希望让更多的数据科学家和开发者加入其中,集思广益,从而让 AutoML 更好的利用时序关系型数据,提升模型的预测性能,让 AutoML 解决方案能够更加符合实际应用的需求。因此,我们认为这次AutoML竞赛对推动AutoML的发展具有重要意义。
深兰科技在自身产品的开发中也已使用了自研AutoML系统,以深兰科技应用于建青实验学校的AI教育“一手通”为例,通过这款系统设备采集的数据,再经过AutoML系统自动建模可以分析出学生的兴趣爱好,随后进行个性化教学。在坚持加强基础研究的道路上,深兰科技披荆斩棘、不忘初心,将继续把更多搭载先进技术的产品推向市场,真正实现服务民生。
问:据了解,除了 KDD CUP,深兰科技近期还斩获了多个比赛的冠军(如 IEEE ISI 、CVPR FGVC 等),能向我们介绍一下深兰科技在这方面的投入情况吗?
答:深兰科技成立之初即完整地规划了深兰科学院的架构,并陆续成立了五大研究院,致力于人工智能基础研究和应用开发。在核心技术的基础研究方面,包括计算机视觉、自动驾驶、生物识别和认知智能等四大领域。每次国际会议竞赛都是验证深兰科技基础算法和技术实力的机会,我们同时也希望这些方案能为更多行业提供借鉴。尤其本届KDD Cup AutoML竞赛开源了解决方案,其中有许多优秀的思路和方法在竞赛中得以验证,不但共同推进了AutoML的发展,也提供了交流学习的机会。深兰科技矢志不渝,不但为自身的商业化应用落地持续注入强劲能量,更希望赋能更多行业,将“人工智能,服务民生”的理念落实到底。
问:对于有兴趣参赛的青年 AI 开发人员,深兰科技有何建议给到他们?
答:有兴趣参加机器学习竞赛的AI开发人员主要分为两种,一种是在校学生,另一种是在职的。对于在校的同学来说,参加机器学习竞赛可以快速提升自己的专业技能,也能积累实战经验,对找实习和找工作都有很大帮助;对于在职的同学来说,希望在业余竞赛的同时能把竞赛中学习到的东西应用到当前工作中来,由于竞赛需要花费不少时间,也建议队伍中有时间相对比较多的在校学生,这样能够更好的平衡工作和竞赛的时间。
多学习一些竞赛的Top队伍的分享,从这些分享中多总结多思考,对于特定任务可以结合实际业务场景深入探索。
在机器学习竞赛中取得 top 的成绩不仅要实力也需要一定的运气,放松心态,带着学习的态度去玩比赛,在玩的过程中,不仅能接触各种AI应用场景,也能提升自己的能力并认识更多相同兴趣的朋友,这就是最大的收获。
雷锋网 AI 开发者雷锋网