KDD Cup 2019 AutoML Track冠军深兰科技DeepBlueAI团队技术分享 | 开源代码
作者丨羅志鵬
單位丨深蘭北京AI研發(fā)中心
近日,KDD Cup 2019 AutoML Track 比賽結(jié)果出爐,本次賽題是第五次 AutoML 挑戰(zhàn)賽,由第四范式、ChaLearn 和微軟聯(lián)合舉辦,專注于時(shí)序相關(guān)數(shù)據(jù)的自動(dòng)機(jī)器學(xué)習(xí)。
這次競(jìng)賽注冊(cè)隊(duì)伍達(dá)到近 800 支,是近幾次 AutoML 競(jìng)賽中參賽隊(duì)伍最多的一次。由來(lái)自深蘭科技北京 AI 研發(fā)中心的 DeepBlueAI 團(tuán)隊(duì)斬獲冠軍,團(tuán)隊(duì)成員均畢業(yè)或就讀于北大。新加坡國(guó)立大學(xué)的 NUS-Xtra-Lab 團(tuán)隊(duì)獲得第二名,阿里巴巴集團(tuán)和佐治亞理工學(xué)院組成的 admin 團(tuán)隊(duì)則獲得第三名。排名前十的隊(duì)伍中還包括清華大學(xué)、南京大學(xué)、微軟亞洲研究院、海康威視、美團(tuán)點(diǎn)評(píng)等高校或機(jī)構(gòu)。
本文帶來(lái)該團(tuán)隊(duì)在競(jìng)賽中技術(shù)細(xì)節(jié)分享,文末附開源代碼 Github 鏈接。
背景介紹
ACM SIGKDD 由美國(guó)計(jì)算機(jī)協(xié)會(huì)數(shù)據(jù)挖掘與知識(shí)專業(yè)委員會(huì)發(fā)起,是數(shù)據(jù)挖掘領(lǐng)域公認(rèn)的具有最高學(xué)術(shù)地位的國(guó)際性學(xué)術(shù)會(huì)議。KDD Cup 是由 ACM 的數(shù)據(jù)挖掘及知識(shí)發(fā)現(xiàn)專委會(huì)(SIGKDD)主辦的數(shù)據(jù)挖掘研究領(lǐng)域的國(guó)際頂級(jí)賽事,從 1997 年至今已有 22 年的歷史。
作為目前數(shù)據(jù)挖掘領(lǐng)域最有影響力、最高水平的國(guó)際頂級(jí)賽事,KDD Cup 每年都會(huì)吸引來(lái)自世界各地?cái)?shù)據(jù)挖掘領(lǐng)域的頂尖專家、學(xué)者和工程師參賽,因此也有“大數(shù)據(jù)奧運(yùn)會(huì)”之名。今年, 第 25 屆 ACM SIGKDD 會(huì)議于 2019 年 8 月 4 日至 8 日在美國(guó)阿拉斯加舉行。
團(tuán)隊(duì)成績(jī)
在 KDD Cup 2019 AutoML Track 當(dāng)中,DeepBlueAI 團(tuán)隊(duì)在 Feed-back 階段以 4 項(xiàng)第一,1 項(xiàng)第二平均成績(jī)排名第一;AutoML 階段以 3 項(xiàng)第一,平均指標(biāo)領(lǐng)先第二名 0.3 的成績(jī)以絕對(duì)優(yōu)勢(shì)獲得冠軍,具體排名如下:
▲?圖1.?KDD Cup 2019 AutoML Track終榜及開源地址
?
▲?圖3.?KDD Cup 2019 AutoML Track Feed-back Phase排行榜
?
團(tuán)隊(duì)成員獲獎(jiǎng)記錄
賽題介紹
參賽者將利用時(shí)序關(guān)系數(shù)據(jù),設(shè)計(jì)一個(gè)能夠自主(無(wú)人為干預(yù))實(shí)現(xiàn)監(jiān)督學(xué)習(xí)的AutoML計(jì)算機(jī)程序。該比賽聚焦在二分類問(wèn)題,且時(shí)序關(guān)系數(shù)據(jù)均來(lái)自實(shí)際業(yè)務(wù)場(chǎng)景。根據(jù)大多數(shù)實(shí)際應(yīng)用的時(shí)間屬性,數(shù)據(jù)集按時(shí)間順序劃分為訓(xùn)練集和測(cè)試集。訓(xùn)練集和測(cè)試集都由一個(gè)主表、一組相關(guān)表和一個(gè)關(guān)系圖組成:?
參賽者需要提交通過(guò)主表、相關(guān)表和關(guān)系圖自動(dòng)構(gòu)建機(jī)器學(xué)習(xí)模型的 AutoML 方案。一旦經(jīng)過(guò)訓(xùn)練,模型將以測(cè)試主表(不包括樣本標(biāo)記)、相關(guān)表和關(guān)系圖作為輸入,并預(yù)測(cè)測(cè)試集的樣本標(biāo)記。參賽者提交的方案將在受限制的計(jì)算資源和時(shí)間內(nèi)進(jìn)行測(cè)試。?
為了讓參賽者能夠更好的開發(fā)并評(píng)估方案,主辦方提供了 10 個(gè)時(shí)序關(guān)系數(shù)據(jù)集,其中 5 個(gè)公共數(shù)據(jù)集,5 個(gè)私有數(shù)據(jù)集。
比賽階段
Feedback 階段?
即反饋階段。在此階段,參賽者可以在五個(gè)公共數(shù)據(jù)集上進(jìn)行訓(xùn)練,開發(fā) AutoML 方案。參賽者可以進(jìn)行有限數(shù)量的提交,并獲得作為反饋的所有五個(gè)公共數(shù)據(jù)集的測(cè)試數(shù)據(jù)的性能。參賽者可以下載有標(biāo)記的訓(xùn)練數(shù)據(jù)集和未標(biāo)記的測(cè)試數(shù)據(jù)集。因此,參賽者可以在線下準(zhǔn)備他們的代碼并提交。該階段最后的代碼提交將最終作為下一階段進(jìn)行盲測(cè)的代碼。?
Check 階段?
即校驗(yàn)階段。該階段將在五個(gè)私有數(shù)據(jù)集上對(duì)第一階段的最后一次提交的代碼進(jìn)行盲測(cè),確保提交的方案順利運(yùn)行,不會(huì)出現(xiàn)例如超時(shí)或者內(nèi)存溢出等問(wèn)題,但參賽者無(wú)法看到具體的結(jié)果,所有參賽隊(duì)伍具備一次更新代碼的機(jī)會(huì),以保證在最終階段正確的運(yùn)行自己的代碼。?
AutoML 階段?
即盲試階段。該階段將測(cè)試方案在私有數(shù)據(jù)集上的性能。參賽者的代碼將在無(wú)需人為干預(yù)情況下完成訓(xùn)練和預(yù)測(cè)。AUC 作為評(píng)價(jià)指標(biāo),最終將根據(jù)五個(gè)私有數(shù)據(jù)集的平均排名進(jìn)行評(píng)分。若最終比分相同,則優(yōu)先考慮可解釋性更好的方案,可解釋性將由專家團(tuán)隊(duì)評(píng)審。
以上三個(gè)階段的計(jì)算及內(nèi)存資源均有所限制,因此方案應(yīng)兼顧效果及效率。
競(jìng)賽時(shí)間
2019 年 4 月 1 日:比賽開始,發(fā)布公共數(shù)據(jù)集。參與者可以開始提交代碼并在排行榜上獲得即時(shí)反饋信息。?
2019 年 6 月 27 日:Feedback 階段結(jié)束,Feedback 階段的代碼自動(dòng)遷移到 Test 階段。?
2019 年 7 月 7 日:Check 階段結(jié)束,主辦方開始代碼驗(yàn)證。?
2019 年 7 月 11 日:提交報(bào)告的截止日期。?
2019 年 7 月 16 日:AutoML 階段結(jié)束,開始評(píng)審流程。?
2019 年 7 月 20 日:宣布 KDD Cup 冠軍。?
2019 年 8 月 4 日:在 KDD 上舉辦頒獎(jiǎng)儀式。
評(píng)測(cè)指標(biāo)
本次比賽采用 AUC 作為評(píng)分指標(biāo),排名規(guī)則以官方給出的 baseline 得分 auc_base 為 0 分基準(zhǔn),以所有選手最高成績(jī) auc_max 為滿分 1 分基準(zhǔn),按照公式得出相對(duì)分?jǐn)?shù),最后算出 5 個(gè)數(shù)據(jù)集的平均分為最終得分,得分越高代表模型性能越好。得分計(jì)算公式如下:
題目特點(diǎn)
在這次比賽中,主要有以下難點(diǎn):
1. 挖掘有效的特征
與傳統(tǒng)數(shù)據(jù)挖掘競(jìng)賽不同的是,AutoML 競(jìng)賽中,參賽選手只知道數(shù)據(jù)的類型(數(shù)值變量、分類變量、時(shí)間變量、多值分類變量等),而不知道數(shù)據(jù)的含義,這毫無(wú)疑問(wèn)會(huì)增加特征工程的難度,如何挖掘到有效的通用特征成為一個(gè)難點(diǎn)。
2. 賽題數(shù)據(jù)和時(shí)序相關(guān)
時(shí)序相關(guān)數(shù)據(jù)的數(shù)據(jù)挖掘難度較大,在傳統(tǒng)的機(jī)器學(xué)習(xí)應(yīng)用中,需要經(jīng)驗(yàn)豐富的專家才能從時(shí)序關(guān)系型數(shù)據(jù)中挖掘出有效的時(shí)序信息,并加以利用提升機(jī)器學(xué)習(xí)模型的效果。即使具備較深的知識(shí)儲(chǔ)備,專家也需要通過(guò)不斷的嘗試和試錯(cuò),才能構(gòu)建出有價(jià)值的時(shí)序特征,并且利用好多個(gè)相關(guān)聯(lián)表來(lái)提升機(jī)器學(xué)習(xí)模型的性能。
3. 賽題數(shù)據(jù)按照多表給出
賽題的數(shù)據(jù)是按照多表給出的,這就要求參賽選手能夠構(gòu)建一個(gè)處理多表之間多樣的連接關(guān)系的自動(dòng)化機(jī)器學(xué)習(xí)系統(tǒng)。多表數(shù)據(jù)無(wú)疑提升了對(duì)系統(tǒng)的穩(wěn)定性的要求,稍有不慎,有可能合并出來(lái)的數(shù)據(jù)過(guò)于龐大就直接超時(shí)或者超內(nèi)存而導(dǎo)致沒(méi)有最終成績(jī)。
4. 時(shí)間內(nèi)存限制嚴(yán)格
比賽代碼運(yùn)行環(huán)境是一個(gè) 4 核 CPU,16G 內(nèi)存的 docker 環(huán)境,對(duì)于未知大小的數(shù)據(jù)集,在代碼執(zhí)行過(guò)程中的某些操作很容易使得內(nèi)存峰值超過(guò) 16G,導(dǎo)致程序崩潰。因此選手要嚴(yán)格優(yōu)化某些操作,或使用采樣等方式完成任務(wù)。此外,比賽方對(duì)于每個(gè)數(shù)據(jù)集嚴(yán)格限制了代碼的執(zhí)行時(shí)間,稍有不慎就會(huì)使得運(yùn)行時(shí)間超時(shí)而崩潰。
解決方案
我們團(tuán)隊(duì)基于所給數(shù)據(jù)實(shí)現(xiàn)了一套支持多表的 AutoML 框架,包括自動(dòng)多表合并、自動(dòng)特征工程、自動(dòng)特征選擇、自動(dòng)模型調(diào)參、自動(dòng)模型融合等步驟,在時(shí)間和內(nèi)存的控制上我們也做了很多優(yōu)化工作。
數(shù)據(jù)預(yù)處理
我們通過(guò)對(duì)表結(jié)構(gòu)及其屬性的分析,針對(duì)不同類型的數(shù)據(jù)制定不同的數(shù)據(jù)預(yù)處理方案。首先,在多表間的多個(gè)連接 key 中,我們?cè)谥鞅碇蟹N類最多的一個(gè) key 識(shí)別為 user。基于識(shí)別出的 user,可以嘗試在主表的 category 中識(shí)別出 session。
另外,我們嘗試在 category 數(shù)據(jù)中識(shí)別出只有兩類有效值的 binary 數(shù)據(jù)。我們對(duì) category、user、session、key 進(jìn)行重新編碼,對(duì) numerical 數(shù)據(jù)嘗試將其轉(zhuǎn)換為占用內(nèi)存更少的類型,將 time 數(shù)據(jù)轉(zhuǎn)換為容易操作的 datetime 類型。
def?recognize_user_col(self,data,key_cols):
????user_col?=?None
????nunique?=?-1
????for?col?in?key_cols:
????????nnum?=?data[col].nunique()
????????if?nnum?>?nunique:
????????????user_col?=?col
????????????nunique?=?nnum
????return?user_col
def?recognize_session_col(self,data,cat_cols,user_col):
????if?user_col?is?None:
????????return?[]
????user_nunique?=?data[user_col].nunique()
????session_cols?=?[]
????def?func(df,user_nunique):
????????cat_col?=?df.columns[0]
????????user_col?=?df.columns[1]
????????cat_nunique?=?df[cat_col].nunique()
????????if?(cat_nunique?<=?user_nunique)?or?(cat_nunique?>=?df.shape[0]-10):
????????????return?False
????????if?(df.groupby(cat_col)[user_col].nunique()>1).sum()>10:
????????????return?False
????????return?True
????res?=?Parallel(n_jobs=CONSTANT.JOBS,require='sharedmem')(delayed(func)(data[[col,user_col]],user_nunique)?for?col?in?cat_cols)
????for?col,is_session?in?zip(cat_cols,res):
????????if?is_session:
????????????session_cols.append(col)
????return?session_cols
多表連接
比賽給的數(shù)據(jù)結(jié)構(gòu)如上圖所示,表和表之間的連接關(guān)系可以分為四種,分別是 1-1、1-M、M-1、M-M。因?yàn)闀r(shí)間和內(nèi)存的限制,所以我們需要在盡可能保留信息的同時(shí),讓最后生成的表的數(shù)據(jù)規(guī)模不至于過(guò)大。而處理多表連接的方式,直接影響到后面的結(jié)果。我們針對(duì)不同的連接方式采用了不同的方法。
首先將四種連接方式分成了兩種類型:類型 1 包含了 1-1、M-1,類型 2 包含了 1-M、M-M。對(duì)于類型 1,我們可以直接將副表的數(shù)據(jù)通過(guò) key 合并到主表上。對(duì)于類型 2,我們首先對(duì)副表做一些聚集操作,生成聚集的結(jié)果,而這些聚集的結(jié)果可以理解為和主表是類型1的關(guān)系。
接下來(lái),我們只要對(duì)生成聚集的結(jié)果做類型 1 的操作,直接將其合并到主表上即可。并且,對(duì)于主表和副表都有時(shí)間戳的情況下,我們?yōu)榱吮M可能保留信息,將副表上離主表當(dāng)前數(shù)據(jù)早且最近并且為相同 key 值的數(shù)據(jù)合并到主表上。
其具體操作可以見圖示,key 為 147714011 的數(shù)據(jù)項(xiàng)的 n_1 列的數(shù)據(jù)為 3.6,連接到 Main Table 對(duì)應(yīng)的 147714011 的所有數(shù)據(jù)項(xiàng)之上。
該圖表示了類型 2 的連接方式,這個(gè)例子為對(duì) n_1 列做了均值聚集操作,key 為 147714011 的數(shù)據(jù)項(xiàng)在 n_1 列上的均值為 2.3,之后就是將該數(shù)據(jù)對(duì)應(yīng)合并到主表上。
采樣
因?yàn)?AutoML 比賽方給定的數(shù)據(jù)集大小未知,在對(duì)其進(jìn)行操作處理之前首先要判斷當(dāng)前環(huán)境是否能夠支持整個(gè)數(shù)據(jù)集共同參與特征工程及模型訓(xùn)練過(guò)程。我們?cè)谧x入數(shù)據(jù)進(jìn)入預(yù)處理之前做了一次判斷,即要求訓(xùn)練集與測(cè)試集的總樣本數(shù)不超過(guò)某一個(gè)可以接受的閾值。如訓(xùn)練集與測(cè)試集的總樣本數(shù)過(guò)多,我們就考慮對(duì)其進(jìn)行采樣,在當(dāng)前給定的 16G 內(nèi)存的條件下,我們經(jīng)過(guò)估算,得到 400 萬(wàn)條數(shù)據(jù)是一個(gè)比較好的閾值。
此外,在特征工程的組合特征模塊中,同樣用到了采樣的思想。組合特征的特點(diǎn)是產(chǎn)生的特征數(shù)量多,特征工程的時(shí)間長(zhǎng),內(nèi)存峰值高,起作用的特征數(shù)量少。因此,為了避免內(nèi)存溢出,我們?cè)谧鼋M合特征之前,在小數(shù)據(jù)集上進(jìn)行特征工程,經(jīng)過(guò)篩選后得到真正有效的特征,再在整個(gè)數(shù)據(jù)集上僅做出這些有效的特征這樣不僅可以減少系統(tǒng)運(yùn)行時(shí)間也能避免爆內(nèi)存的風(fēng)險(xiǎn)。
自動(dòng)特征工程
def?main_init(self):????self.order1s?=?[????????????????PreMcToNumpy,McCatRank,????????????????OriginSession,????????????????ApartCatRecognize,\????????????????KeysCountDIY,UserKeyCntDIY,SessionKeyCntDIY,\????????????????KeysTimeDiffAndFuture,????????????????KeysNuniqueDIY,?KeysCntDivNuniqueDIY,????????????????KeysCumCntRateAndReverse,UserKeyCumCntRateAndReverse,????????????????KeyTimeDate,KeyTimeBin,KeysBinCntDIY,????????????????CatCountDIY,????????????????LGBFeatureSelection,????????????]????self.keys_order2s?=?[????????????????KeysNumMeanOrder2MinusSelfNew,????????????????KeysNumMaxMinOrder2MinusSelfNew,????????????????KeysNumStd,????????????????KeysCatCntOrder2New,????????????????LGBFeatureSelectionWait,????????????]????????self.all_order2s?=?[????????????????BinsCatCntOrder2DIYNew,????????????????BinsNumMeanOrder2DIYNew,????????????????CatNumMeanOrder2DIYNew,????????????????CatCntOrder2DIYNew,????????????????LGBFeatureSelectionWait????????????]????????self.post_order1s?=?[????????????????TimeNum,????????????]????????self.merge_order1s?=?[????????????????CatSegCtrOrigin,????????????????CatMeanEncoding,????????????????LGBFeatureSelectionLast,????????????]
????self.order1s?=?[
????????????????PreMcToNumpy,McCatRank,
????????????????OriginSession,
????????????????ApartCatRecognize,\
????????????????KeysCountDIY,UserKeyCntDIY,SessionKeyCntDIY,\
????????????????KeysTimeDiffAndFuture,
????????????????KeysNuniqueDIY,?KeysCntDivNuniqueDIY,
????????????????KeysCumCntRateAndReverse,UserKeyCumCntRateAndReverse,
????????????????KeyTimeDate,KeyTimeBin,KeysBinCntDIY,
????????????????CatCountDIY,
????????????????LGBFeatureSelection,
????????????]
????self.keys_order2s?=?[
????????????????KeysNumMeanOrder2MinusSelfNew,
????????????????KeysNumMaxMinOrder2MinusSelfNew,
????????????????KeysNumStd,
????????????????KeysCatCntOrder2New,
????????????????LGBFeatureSelectionWait,
????????????]
????????self.all_order2s?=?[
????????????????BinsCatCntOrder2DIYNew,
????????????????BinsNumMeanOrder2DIYNew,
????????????????CatNumMeanOrder2DIYNew,
????????????????CatCntOrder2DIYNew,
????????????????LGBFeatureSelectionWait
????????????]
????????self.post_order1s?=?[
????????????????TimeNum,
????????????]
????????self.merge_order1s?=?[
????????????????CatSegCtrOrigin,
????????????????CatMeanEncoding,
????????????????LGBFeatureSelectionLast,
????????????]
特征工程部分往往是數(shù)據(jù)挖掘競(jìng)賽的關(guān)鍵核心內(nèi)容,也是我們團(tuán)隊(duì)在競(jìng)賽中取得顯著優(yōu)勢(shì)的重要因素。我們通過(guò) LightGBM 模型來(lái)驗(yàn)證特征效果。我們將特征工程分成幾個(gè)模塊。
第一個(gè)模塊是基礎(chǔ)特征部分,這一部分主要是針對(duì) user、key、session 的統(tǒng)計(jì)特征,產(chǎn)生新特征的數(shù)目較少卻有很好的效果,因此放在最先。
第二模塊是一階組合特征部分,我們嘗試將主表中較為重要的 user、key、session 與其余的 numerical 或 categorical 挑選出的數(shù)據(jù)進(jìn)行組合,對(duì)某些數(shù)據(jù)集有非常好的效果。
第三個(gè)是大量組合特征部分,我們對(duì)時(shí)間分桶,嘗試使用時(shí)間桶對(duì) categorical 和 numerical 數(shù)據(jù)進(jìn)行組合,此外我們還根據(jù)不同數(shù)據(jù)集的數(shù)據(jù)量大小,篩選出適量的 categorical 或 numerical 數(shù)據(jù)兩兩組合形成新的特征,在希望挖掘到有用的特征的同時(shí),盡量減小內(nèi)存溢出的風(fēng)險(xiǎn)。
最后的部分是有監(jiān)督學(xué)習(xí)的 CTR 和均值編碼特征,將其放在最后的原因是一方面在這一階段會(huì)產(chǎn)生很多特征,容易造成生成過(guò)多的特征而導(dǎo)致爆內(nèi)存;另一方面是我們認(rèn)為這些特征和其他特征組合沒(méi)有什么實(shí)際意義,因此將其放在最后不參與組合。
同時(shí),因?yàn)楸敬胃?jìng)賽的時(shí)間和內(nèi)存的控制比較嚴(yán)格,在面對(duì)百萬(wàn)級(jí)的數(shù)據(jù)量上,每個(gè)特征生成幾乎都要控制在幾秒內(nèi)生成,為了滿足這一要求,我們的代碼加入了許多優(yōu)化。比如對(duì)于類別數(shù)據(jù)在多類別數(shù)據(jù)中的位置這一特征,如果用傳統(tǒng)的 Pandas 實(shí)現(xiàn),時(shí)間會(huì)達(dá)到幾個(gè)小時(shí),而加入多線程之后,情況會(huì)有所改善,但是仍舊要消耗大量的時(shí)間。
我們退而求其次,使用 numpy 來(lái)實(shí)現(xiàn)該特征,特征的生成時(shí)間直接到達(dá)了幾十秒的級(jí)別,但是這仍舊不能滿足我們的要求。最后我們對(duì)這塊代碼使用 cython 去優(yōu)化,并且對(duì) cython 代碼進(jìn)行精雕細(xì)琢,最后該特征的生成只需要幾秒。
▲?圖4.?經(jīng)過(guò)篩選后較為重要的特征
?自動(dòng)特征選擇
?在自動(dòng)特征工程階段,我們將特征工程分為多個(gè)階段。在每一個(gè)模塊結(jié)束后,我們都會(huì)做一次特征選擇來(lái)篩掉那些在這一階段做出的無(wú)效的特征,來(lái)避免內(nèi)存溢出并且加速最終的模型訓(xùn)練。
我們通過(guò)結(jié)合特征重要性及序列后向選擇算法,設(shè)置一個(gè)閾值,將在參與模型訓(xùn)練中,篩出重要性較低的特征而盡可能小地?fù)p失模型精度。我們還嘗試了基于特征的信息增益來(lái)對(duì)特征進(jìn)行篩選,亦或是對(duì)兩種篩選方法進(jìn)行結(jié)合,但因?yàn)闆](méi)能找到更好的切分點(diǎn),最終還是使用了基于特征重要性的方法。
▲?圖5.?特征選擇機(jī)制
類別不平衡問(wèn)題處理
我們對(duì)類別不平衡的數(shù)據(jù)在訓(xùn)練時(shí)做了處理。正負(fù)樣本比例超過(guò) 1:3 時(shí),我們采用欠采樣的方式,緩和正負(fù)樣本不平衡。此外,我們還嘗試通過(guò)增加正樣本的權(quán)重等方式來(lái)優(yōu)化類別不平衡帶來(lái)的問(wèn)題。在模型融合的部分,我們?cè)诒A粼驾^少的正樣本的同時(shí),換一批負(fù)樣本來(lái)進(jìn)行訓(xùn)練,這樣能夠盡可能保留更多的原始數(shù)據(jù)的信息,同時(shí)緩解類別不平衡的問(wèn)題。
模型融合
由于比賽環(huán)境對(duì)時(shí)間和內(nèi)存做了嚴(yán)格的限制,我們?cè)谀P腿诤戏矫婵紤]了 bagging、blending、stacking 等方案,最終選用了使用 bagging 的方法。我們通過(guò)計(jì)算一個(gè) demo 模擬真實(shí)數(shù)據(jù)集訓(xùn)練和預(yù)測(cè)來(lái)預(yù)估真實(shí)數(shù)據(jù)集所需要的時(shí)間,如時(shí)間不足則選擇在訓(xùn)練時(shí) early-stop,允許精度上的損失來(lái)保證代碼能夠在規(guī)定時(shí)間內(nèi)運(yùn)行完畢。
如時(shí)間充裕,則通過(guò)當(dāng)前剩余時(shí)間計(jì)算允許多少個(gè)模型進(jìn)行融合。為了保證代碼通過(guò),我們采用了保守估計(jì)的方式,即在計(jì)算出模型融合數(shù)量的基礎(chǔ)上,選擇少融合一個(gè)模型。
temp?=?temp.astype(np.float32)
gc.collect()
temp?=?temp.values
gc.collect()
model.predict(temp)
end_time?=?time.time()
model_test_use_time?=?(end_time-start_time)
#?估算預(yù)測(cè)10萬(wàn)條數(shù)據(jù)所需的時(shí)間
model_test_use_time?=?len_test/temp.shape[0]?*?model_test_use_time
#?得到預(yù)測(cè)測(cè)試集數(shù)據(jù)所需的時(shí)間
model_use_time?=?model_use_time?+?model_test_use_time
#?總時(shí)間?=?訓(xùn)練時(shí)間?+?測(cè)試時(shí)間
del?temp,model
rest_time?=?config.budget/10*9-(end_time-config.start_time)
#?使用給定時(shí)間的90%做保守估計(jì),計(jì)算剩余可用時(shí)間
if?rest_time?<=?0:
????rest_model_num?=?0
else:
????rest_model_num?=?int(rest_time?/?model_use_time)
if?rest_model_num?>=?50:
????rest_model_num?=?50?
if?rest_model_num?>=?1:
????rest_model_num?-=?1
#?根據(jù)剩余時(shí)間計(jì)算出可融合模型的數(shù)量,在此基礎(chǔ)上少融合一個(gè)模型
運(yùn)行時(shí)間優(yōu)化
我們的時(shí)間控制在各個(gè)過(guò)程中都有體現(xiàn)。?
在自動(dòng)化數(shù)據(jù)處理和自動(dòng)化特征工程的過(guò)程中,我們使用 Cython 對(duì)編碼以及一些生成效率較慢的特征進(jìn)行加速。這里舉一個(gè)特征為例,對(duì)于兩列數(shù)據(jù),一列為 category 類型的數(shù)據(jù),一列為 multi-category 類型的數(shù)據(jù),我們提前判斷了兩列數(shù)據(jù)的數(shù)據(jù)項(xiàng)集具有交集,我們要計(jì)算這一 category 列中的數(shù)據(jù)項(xiàng)在 multi-category 列對(duì)應(yīng)的數(shù)據(jù)項(xiàng)集中的位置信息。
比如說(shuō)有有一條數(shù)據(jù)。data : [ 2137 , (134,2137,576,816) ] ,前者 2137 在后者的第 2 個(gè)位置上。所以這條數(shù)據(jù)該特征為 2。如果沒(méi)有出現(xiàn)的話,規(guī)定為 0。對(duì)于這一特征,如果我們使用 pandas 提供的 apply 接口來(lái)實(shí)現(xiàn),在本次競(jìng)賽的環(huán)境下,該類特征的生成需要大約幾個(gè)小時(shí)的時(shí)間。
考慮到 DataFrame 不適合做遍歷,以及接口泛化性帶來(lái)的性能上的損失。我們使用 Numpy,做遍歷來(lái)實(shí)現(xiàn)該特征,能夠讓特征的生成達(dá)到分鐘級(jí)。而本次競(jìng)賽的時(shí)間和內(nèi)存有嚴(yán)格的控制,像那些需要超過(guò) 10 秒才能生成的一類特征就算非常耗時(shí)的了。
之后我們采用 Cython,應(yīng)用 Cython 提前編譯,靜態(tài)類型等機(jī)制我們將該特征的生成時(shí)間控制在了 10 秒內(nèi)。其中生成該特征的過(guò)程中有一些細(xì)節(jié)。比如如果在 Cython 中繼續(xù)使用 Python 原生類型,那么遍歷的效率還是比較緩慢。但是 multi-category 類型的數(shù)據(jù)存儲(chǔ)又不好離開 Python 原生類型的支持。
考慮我們?cè)谏商卣鞯倪^(guò)程中,主要是對(duì) multi-category 類型做遍歷操作,所以可以使用一個(gè)數(shù)組去存儲(chǔ) multi-category 的每個(gè)數(shù)據(jù)項(xiàng)。并且用額外一個(gè)數(shù)組去保存每個(gè) multi-category 的數(shù)據(jù)項(xiàng)集的長(zhǎng)度。這樣根據(jù)其長(zhǎng)度數(shù)組和數(shù)據(jù)數(shù)組,我們就能做一個(gè)高效的遍歷。
在測(cè)試這段優(yōu)化的過(guò)程中,純粹的 Python 代碼經(jīng)過(guò) Cython 優(yōu)化,效率大概能到 60 秒。而經(jīng)過(guò)這段優(yōu)化,很輕松就能到達(dá) 10 秒內(nèi)(測(cè)試環(huán)境就是以我們的本次計(jì)算機(jī)為主,線上環(huán)境會(huì)多一些時(shí)間)。?
在模型集成部分,我們會(huì)做提前計(jì)算,記錄到當(dāng)前用時(shí),通過(guò)訓(xùn)練模型幾個(gè)輪次來(lái)計(jì)算出模型啟動(dòng)的時(shí)間以及模型訓(xùn)練每一輪數(shù)據(jù)所消耗的時(shí)間,通過(guò)這兩個(gè)時(shí)間,我們能夠預(yù)估出后續(xù)的參數(shù)調(diào)優(yōu),模型訓(xùn)練的時(shí)間。從而決定最后模型融合的數(shù)量。
▲?時(shí)間優(yōu)化前后對(duì)比
運(yùn)行內(nèi)存優(yōu)化
在內(nèi)存控制方面,我們首先實(shí)現(xiàn)了一個(gè)內(nèi)存的監(jiān)聽器。我們首先完整運(yùn)行一輪我們的系統(tǒng),記錄下內(nèi)存情況,對(duì)不同數(shù)據(jù)集的內(nèi)存峰值進(jìn)行分析。可以發(fā)現(xiàn)的是,內(nèi)存峰值往往就出現(xiàn)在幾個(gè)典型的地方。比如:數(shù)據(jù)合成時(shí)、在模型開始訓(xùn)練時(shí)、某些特征生成時(shí)。
經(jīng)過(guò)分析,可以概括為幾個(gè)點(diǎn),其中比較典型的是數(shù)據(jù)合成時(shí),如果使用 pandas 的接口 pandas.concat 進(jìn)行數(shù)據(jù)合并,其合并過(guò)程中,會(huì)生成大約兩倍當(dāng)前數(shù)據(jù)內(nèi)存的量。這個(gè)是顯然的,因?yàn)槠浜喜⒎祷氐慕Y(jié)果不是就地的,而是創(chuàng)建出第三塊內(nèi)存。因此,我們將合成的過(guò)程改為按列賦值,這樣合并時(shí)就幾乎不存在內(nèi)存峰值了。但是這么做,同時(shí)會(huì)帶來(lái)較差的時(shí)間效率。所以在系統(tǒng)的早期,內(nèi)存比較寬松的情況下,我們?nèi)耘f采用 pandas 的接口來(lái)進(jìn)行對(duì)數(shù)據(jù)的合并。
另外,我們同樣對(duì)訓(xùn)練預(yù)測(cè)時(shí)內(nèi)存的情況進(jìn)行了提前計(jì)算,在最后的特征篩選的過(guò)程中,我們會(huì)計(jì)算模擬出在生成多大的數(shù)據(jù)量下,能夠完整進(jìn)行系統(tǒng)后續(xù)的過(guò)程。從而來(lái)控制最后篩選出來(lái)的數(shù)據(jù)量。并且在最后一次特征篩選前,生成特征時(shí),我們也會(huì)先時(shí)候小數(shù)據(jù)集進(jìn)行一個(gè)模擬過(guò)程,來(lái)計(jì)算出整個(gè)過(guò)程中的內(nèi)存情況,來(lái)對(duì)生成期生成的特征數(shù)量進(jìn)行一個(gè)控制。
最后,我們會(huì)做一些比較精細(xì)的內(nèi)存管理,在變量生命周期結(jié)束的時(shí)候,我們都會(huì)對(duì)其進(jìn)行內(nèi)存回收。以下是我們內(nèi)存優(yōu)化前后的一個(gè)對(duì)比。里面包含了比賽中給的 5 個(gè)數(shù)據(jù)集的運(yùn)行過(guò)程中的內(nèi)存情況。
▲?圖6.?內(nèi)存優(yōu)化前后對(duì)比
?系統(tǒng)測(cè)試
對(duì)于系統(tǒng)的測(cè)試,我們分為了兩個(gè)方面進(jìn)行。第一個(gè)方面是測(cè)試系統(tǒng)的擴(kuò)展性,第二個(gè)方面是測(cè)試系統(tǒng)的性能。?
對(duì)于系統(tǒng)的擴(kuò)展性,我們測(cè)試過(guò)如下:?
以及其他一系列的極限狀態(tài)。
而對(duì)于系統(tǒng)的性能方面,我們測(cè)試過(guò)如下:?
總結(jié)
本次 KDD Cup AutoML 競(jìng)賽在賽制上得到進(jìn)一步完善。相對(duì)于 NeurIPS 2018 AutoML 競(jìng)賽增加了一次 AutoML 階段的提交次數(shù),這樣能夠盡量保障參賽選手順利跑通 B 榜數(shù)據(jù)。相對(duì)于 PAKDD 2019 AutoML 競(jìng)賽改進(jìn)評(píng)分機(jī)制,最終得分只受各任務(wù)最高分的影響。完善后的競(jìng)賽機(jī)制讓參賽選手得到更好的競(jìng)賽體驗(yàn)和技術(shù)發(fā)揮,感謝主辦方的辛勤付出。?
在這次競(jìng)賽中我們的工作圍繞著競(jìng)賽的挑戰(zhàn)而進(jìn)行,主要有幾個(gè)比較重要的過(guò)程:自動(dòng)化多表數(shù)據(jù)處理、自動(dòng)多表連接、自動(dòng)化特征工程、自動(dòng)化模型構(gòu)建、選擇和融合。同時(shí)為了滿足競(jìng)賽的時(shí)間和內(nèi)存的需求,我們?cè)诖a上做了相當(dāng)多的優(yōu)化,比如使用了多線程、Cython、預(yù)處理、提前估算等方法。最后我們的成績(jī)相當(dāng)不錯(cuò),A,B 榜單上均在多個(gè)任務(wù)集上有比較大的優(yōu)勢(shì)。?
時(shí)序關(guān)系型數(shù)據(jù)在在線廣告、推薦系統(tǒng)、金融市場(chǎng)分析等應(yīng)用場(chǎng)景中十分常見。本次 AutoML 聚焦時(shí)序關(guān)系型數(shù)據(jù),為參賽者提出了挑戰(zhàn),同時(shí)也為 AutoML 的發(fā)展提供了新的思路。近年來(lái) AutoML 因?yàn)槠涓哌m應(yīng)性、高效性、可擴(kuò)展性、高可用性,在工業(yè)應(yīng)用中可以大大降低應(yīng)用門檻,在不同的場(chǎng)景中均可以發(fā)揮出用武之地,大大縮短項(xiàng)目開發(fā)周期。最后祝賀所有的 Top 隊(duì)伍,愿大家在未來(lái)都能取得自己滿意的成績(jī)!
作者介紹
羅志鵬,深蘭北京 AI 研發(fā)中心負(fù)責(zé)人,深蘭科技機(jī)器學(xué)習(xí)科學(xué)家。
碩士畢業(yè)于北大,獲得過(guò) PAKDD,KDD,NeurIPS,CIKM,CVPR,SIGIR 等頂級(jí)會(huì)議競(jìng)賽冠軍,以一作發(fā)表 KDD Oral 一篇,共同一作 WWW 一篇,多年機(jī)器學(xué)習(xí)實(shí)戰(zhàn)經(jīng)驗(yàn)。
開源鏈接
https://github.com/DeepBlueAI/AutoSmart
點(diǎn)擊以下標(biāo)題查看更多往期內(nèi)容:?
圖神經(jīng)網(wǎng)絡(luò)綜述:模型與應(yīng)用
ACL 2019 | 基于知識(shí)增強(qiáng)的語(yǔ)言表示模型
ACL 2019 | 基于上下文感知的向量?jī)?yōu)化
基于小樣本學(xué)習(xí)的意圖識(shí)別冷啟動(dòng)
復(fù)旦大學(xué)邱錫鵬:詞法、句法分析研究進(jìn)展綜述
ACL 2019?| 句對(duì)匹配的樣本選擇偏差與去偏方法
深度長(zhǎng)文:NLP的巨人肩膀(上)
NLP 的巨人肩膀(下):從 CoVe 到 BERT
#投 稿 通 道#
?讓你的論文被更多人看到?
如何才能讓更多的優(yōu)質(zhì)內(nèi)容以更短路徑到達(dá)讀者群體,縮短讀者尋找優(yōu)質(zhì)內(nèi)容的成本呢?答案就是:你不認(rèn)識(shí)的人。
總有一些你不認(rèn)識(shí)的人,知道你想知道的東西。PaperWeekly 或許可以成為一座橋梁,促使不同背景、不同方向的學(xué)者和學(xué)術(shù)靈感相互碰撞,迸發(fā)出更多的可能性。
PaperWeekly 鼓勵(lì)高校實(shí)驗(yàn)室或個(gè)人,在我們的平臺(tái)上分享各類優(yōu)質(zhì)內(nèi)容,可以是最新論文解讀,也可以是學(xué)習(xí)心得或技術(shù)干貨。我們的目的只有一個(gè),讓知識(shí)真正流動(dòng)起來(lái)。
??來(lái)稿標(biāo)準(zhǔn):
? 稿件確系個(gè)人原創(chuàng)作品,來(lái)稿需注明作者個(gè)人信息(姓名+學(xué)校/工作單位+學(xué)歷/職位+研究方向)?
? 如果文章并非首發(fā),請(qǐng)?jiān)谕陡鍟r(shí)提醒并附上所有已發(fā)布鏈接?
? PaperWeekly 默認(rèn)每篇文章都是首發(fā),均會(huì)添加“原創(chuàng)”標(biāo)志
? 投稿郵箱:
? 投稿郵箱:hr@paperweekly.site?
? 所有文章配圖,請(qǐng)單獨(dú)在附件中發(fā)送?
? 請(qǐng)留下即時(shí)聯(lián)系方式(微信或手機(jī)),以便我們?cè)诰庉嫲l(fā)布時(shí)和作者溝通
?
現(xiàn)在,在「知乎」也能找到我們了
進(jìn)入知乎首頁(yè)搜索「PaperWeekly」
點(diǎn)擊「關(guān)注」訂閱我們的專欄吧
關(guān)于PaperWeekly
PaperWeekly 是一個(gè)推薦、解讀、討論、報(bào)道人工智能前沿論文成果的學(xué)術(shù)平臺(tái)。如果你研究或從事 AI 領(lǐng)域,歡迎在公眾號(hào)后臺(tái)點(diǎn)擊「交流群」,小助手將把你帶入 PaperWeekly 的交流群里。
▽ 點(diǎn)擊 |?閱讀原文?| 獲取最新論文推薦
總結(jié)
以上是生活随笔為你收集整理的KDD Cup 2019 AutoML Track冠军深兰科技DeepBlueAI团队技术分享 | 开源代码的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 文末福利 | 国际前沿算法峰会报名进行中
- 下一篇: 抢票 | AI未来说学术论坛第八期 深度