愛奇藝機器學(xué)習(xí)平臺的建設(shè)實踐
在建設(shè)機器學(xué)習(xí)平臺之前,愛奇藝已經(jīng)擁有比較成熟的深度學(xué)習(xí)平臺Javis,但是Javis面向的用戶比較高階、專業(yè)的算法工程師,需要通過提交代碼到專用計算集群上運行計算,使用門檻比較高。
另外,算法除了深度學(xué)習(xí)以外,機器學(xué)習(xí),數(shù)據(jù)挖掘、數(shù)據(jù)分析等領(lǐng)域。對于有很多規(guī)模較小的業(yè)務(wù),沒有相對應(yīng)的平臺支持這些非深度學(xué)習(xí),需要獨立開發(fā)算法和工程平臺來支撐落地。
這就是常說的造煙囪,每個業(yè)務(wù)要自己搭建算法平臺,這很容易出現(xiàn)兩個問題:一個是在算法方面,很多業(yè)務(wù)不是基于算法為核心打造業(yè)務(wù),使用機器學(xué)習(xí)或許僅僅是用于輔助或優(yōu)化業(yè)務(wù),所以可能并沒有很專業(yè)的算法人員對模型或者算法有比較深入的理解;另外一個問題,雖然有算法人員,但是對算法的落地其實還是要做一些工程方面的東西,對于不同業(yè)務(wù)來說屬于重復(fù)造輪子。
此外對于愛奇藝的數(shù)據(jù)中臺戰(zhàn)略來說,智能服務(wù)是數(shù)據(jù)中臺的必要功能。
從以上三點來看,建設(shè)機器學(xué)習(xí)平臺就有了比較清晰的定位。
機器學(xué)習(xí)平臺的服務(wù)的人群包括算法工程師、數(shù)據(jù)分析師,也包括業(yè)務(wù)研發(fā)工程師,我們希望通過構(gòu)建高效的離線、實時預(yù)測服務(wù),降低用戶使用機器學(xué)習(xí)的成本,提高接入算法的效率,利用數(shù)據(jù)中臺的優(yōu)勢促進數(shù)據(jù)和模型的規(guī)范和分享。
發(fā)展歷程
簡單介紹一下愛奇藝機器學(xué)習(xí)平臺的發(fā)展歷程。
截止目前主要是經(jīng)歷了三個大版本,第一版也是基于業(yè)務(wù)造煙囪的階段。這一版由于圍繞具體業(yè)務(wù)搭建服務(wù),所以整個架構(gòu)里面算法部分很少,但是在這一版本我們通過Spark ML調(diào)度算法的核心系統(tǒng),實現(xiàn)了算法的異步分布式調(diào)度。上線后對算法接入的效率提升非常明顯。
在第一版積累的技術(shù)經(jīng)驗基礎(chǔ)上,我們發(fā)現(xiàn)當前通用機器學(xué)習(xí)平臺的需求,于是迭代了第二版,實現(xiàn)面向通用需求的機器學(xué)習(xí)平臺。
第二版里最顯著的特征,是在用戶層增加了可視化前端,可以通過拖拉拽的方式讓用戶組建自己的機器學(xué)習(xí)流程。用戶通過自由拼搭算法組件,解決了通用化后百花齊放的流程需求。
另外一個重點是把調(diào)度服務(wù)獨立出來。其中,實驗調(diào)度子系統(tǒng)對任務(wù)狀態(tài)進行監(jiān)控,負責任務(wù)的調(diào)度,通過對任務(wù)心跳匯總,隨時能了解任務(wù)集群全局的狀態(tài),當任務(wù)執(zhí)行節(jié)點出現(xiàn)異常中斷時,能第一時間重試或重新分發(fā)到其他節(jié)點,極大保證了服務(wù)的穩(wěn)定性。
任務(wù)執(zhí)行引擎是任務(wù)運行的核心。任務(wù)執(zhí)行引擎接收實驗調(diào)度服務(wù)推送來的任務(wù),根據(jù)任務(wù)配置的內(nèi)容從模型池獲取模型資源、從數(shù)據(jù)管理子系統(tǒng)讀寫數(shù)據(jù)、執(zhí)行腳本。由于任務(wù)執(zhí)行引擎不綁定任何具體的算法框架,實現(xiàn)算法執(zhí)行能輕松跨越不同算法框架和平臺。
通過消息日志監(jiān)控,自動收集調(diào)度各個算法和平臺產(chǎn)生的日志信息和終端信息,并通過配置關(guān)鍵字的方式提取有用的信息和數(shù)據(jù),在前端聚合展示,或?qū)崿F(xiàn)某些功能的即時圖表功能。
算法模型池也作為獨立服務(wù)進行管理,專門負責離線和實時預(yù)測獲取模型和同步模型。
系統(tǒng)舍棄了v1中的通過Europa調(diào)度Spark集群任務(wù),以及自己維護的定時任務(wù),接入愛奇藝的大數(shù)據(jù)平臺Babel和定時任務(wù)調(diào)度服務(wù)平臺Gear。接入這兩個平臺以后一來實現(xiàn)了和數(shù)據(jù)中臺的打通,二來實現(xiàn)了離線服務(wù)。
在算法的框架上,由于把執(zhí)行引擎分離出來了,所以可以很輕松的加入更多的框架,在第二版里面除了SparkML里面常見的一些算法以外,還擴展了常用的像XGBoost和圖類的算法。
3.0的主要目標是完善功能版圖,主要實現(xiàn)了在線預(yù)測的服務(wù)。針對用戶提出的一些提高效率的需求,也提供了自動調(diào)參、增加參數(shù)服務(wù)器擴展了模型數(shù)據(jù)量的支持。另外由于用戶有需求通過別的平臺接入機器學(xué)習(xí)平臺,所以也提供了API服務(wù)。
到目前為止,已經(jīng)形成了一站式平臺,基本覆蓋了機器學(xué)習(xí)全流程。通過平臺操作,用戶可以從特征工程到模型訓(xùn)練、模型評估、在線和離線預(yù)測實現(xiàn)了整套機器學(xué)習(xí)的流程。通過把機器學(xué)習(xí)流程的數(shù)據(jù)源和數(shù)據(jù)目的接入整個大數(shù)據(jù)開發(fā)平臺,完成了一整套的閉環(huán)。
系統(tǒng)經(jīng)驗
分享在實際過程中的一些經(jīng)驗。
自動調(diào)參
當用戶在具體做一個模型調(diào)優(yōu)的時候,如果模型的參數(shù)設(shè)置不對的話,很影響模型的準確率。模型的參數(shù)也并不相同,像LR、線性回歸4個參數(shù),多的像XGBoost暴露出17個參數(shù),雖然不是每個參數(shù)都參與調(diào)參,但是總是會遇到一些排列組合。如果人工調(diào)參,參數(shù)組少則幾十,多則上百種組合。比如XGBoost,使用人力來調(diào)參基本不可想象。
目前的機器學(xué)習(xí)框架,普遍自帶調(diào)參功能,比如Spark ML,但是調(diào)參能力相當有限,因為只能做隨機和全組合(窮舉搜索)。使用Spark自帶的調(diào)參方法,如果用戶沒有一點直覺經(jīng)驗排除調(diào)參區(qū)間,那就需要拼計算資源或者人品。
算法框架自帶的調(diào)參系統(tǒng)還有另一個局限性,就是無法跨平臺復(fù)用調(diào)參算法。因此我們設(shè)計一個系統(tǒng)層面的調(diào)參框架,可以調(diào)用Spark、python等不同算法框架,也可以不局限在算法框架語言限制內(nèi)開發(fā)自己的調(diào)參算法。
我們的自動調(diào)參的系統(tǒng)從流程上來看比較簡單。系統(tǒng)把調(diào)參分為多輪次迭代進行。傳統(tǒng)調(diào)參算法比如隨機調(diào)參、網(wǎng)格搜索調(diào)參只有一輪,高級的算法會有多輪調(diào)參,通過前一輪調(diào)參的評估結(jié)果適當縮小調(diào)參區(qū)間,最終把參數(shù)收斂到一個最優(yōu)值。
系統(tǒng)讀取用戶設(shè)置的參數(shù)區(qū)間后,根據(jù)用戶的需求把區(qū)間劃分為多個子區(qū)間,并在每個子區(qū)間隨機采樣參數(shù)作為首次調(diào)參的組合,并通過任務(wù)分發(fā)服務(wù)下發(fā)給執(zhí)行引擎,調(diào)度對應(yīng)的算法框架訓(xùn)練和評估。訓(xùn)練任務(wù)結(jié)束后,執(zhí)行引擎把評估結(jié)果返回給調(diào)參服務(wù)。
收集到當前輪次所有評估結(jié)果后,調(diào)參服務(wù)調(diào)起算法計算下一輪的調(diào)參空間,并調(diào)整下一輪的取樣個數(shù),再次下發(fā)給執(zhí)行引擎測試,循環(huán)往復(fù),直到達到最大輪次限制或收斂程度。
我們可以把整個調(diào)參流程看做是一個大型的模型訓(xùn)練過程,通過結(jié)果反饋不斷找到極值的過程。從這種思路出發(fā),可以加入很多適用的算法作為調(diào)參算法。
目前機器學(xué)習(xí)平臺除了支持隨機算法和網(wǎng)格搜索的算法,也實現(xiàn)了貝葉斯優(yōu)化以及自研的遺傳算法。測試發(fā)現(xiàn)自研的算法調(diào)參效率遠優(yōu)于傳統(tǒng)默認的算法。
數(shù)據(jù)規(guī)模的支持
系統(tǒng)初期只支持SparkML框架,正常訓(xùn)練萬級別的數(shù)據(jù)集幾分鐘能訓(xùn)練完成,但是當用戶數(shù)據(jù)集只有幾十到幾百數(shù)量級時,任務(wù)也需要跑幾分鐘,相對于單機的python秒級訓(xùn)練完成的時間來說相當慢。其中一個原因是任務(wù)提交到Spark集群上需要等待資源分配。真正訓(xùn)練時間短,但其他的準備時間也讓用戶覺得很慢。所以我們在后續(xù)版本把python的單機的引擎也引用進來。當數(shù)據(jù)量小的時候用戶可以直接在單機上做這種操作。
另一方面,在訓(xùn)練億級以上的數(shù)據(jù)量時傳統(tǒng)的SparkML訓(xùn)練相當慢甚至崩潰失敗。這是因為Spark對超大規(guī)模的模型的訓(xùn)練并不擅長,Spark訓(xùn)練模型分多輪迭代,每一輪需要所有的執(zhí)行器的任務(wù)做完后才匯總參數(shù),根據(jù)木桶原理,整個Spark任務(wù)會受到最慢的worker運行時間影響。
另外,所有的執(zhí)行器會通過廣播的方式對參數(shù)進行共享,對于大規(guī)模參數(shù)量的模型來說相當占網(wǎng)絡(luò)帶寬,也會導(dǎo)致系統(tǒng)使用率效果非常低。
解決方案是通過參數(shù)服務(wù)器的方式解決,參數(shù)服務(wù)器本身原理上對分布式的訓(xùn)練進行了一些改良,并不是等所有的執(zhí)行器跑完,等一部分跑完超過一個預(yù)值強行終止了。為了提高整個集群的效率犧牲了一些部分的收斂的速度,另外取消了廣播機制來傳遞參數(shù),把參數(shù)放在獨立的叫做參數(shù)服務(wù)器里面,通過讀取,這樣子也節(jié)省了網(wǎng)絡(luò)的消耗。
愛奇藝的機器學(xué)習(xí)平臺在設(shè)計之初就支持跨算法框架調(diào)度。我們調(diào)研了多種開源的參數(shù)服務(wù)器,最終集成了騰訊的Angel參數(shù)服務(wù)器,并對一些典型模型做了測試。測試證明,在訓(xùn)練億級以上規(guī)模的模型時,參數(shù)服務(wù)器的訓(xùn)練效率相對Spark有明顯提升50%以上的速度。
模型的管理平臺和算法調(diào)度
不論是Sklearn,還是Spark ML的模型預(yù)測,從代碼角度來看,預(yù)測功能是不同模型內(nèi)部的方法。不存在通用的預(yù)測方法兼容所有的模型。對于開發(fā)人員自己寫代碼的時候沒問題,但如果做一個通用化的平臺,需要考慮統(tǒng)一的預(yù)測組件來處理所有的模型預(yù)測,并有一定的擴展性,通過一個預(yù)測組件兼容不同算法框架的模型。
和預(yù)測組件類似的另一個問題是,不同算法模型,甚至跨框架的模型,如何都能統(tǒng)一部署到在線預(yù)測的服務(wù)中去?
以上2個問題可以通過自定義模型文件解決。模型訓(xùn)練完后,在默認模型文件輸出的同時,也輸出自定義文件和PMML文件。PMML是一套有標準的模型定義語言,可用于跨平臺的讀取模型,適合用于離線訓(xùn)練+在線預(yù)測的場景。另外,在自定義文件里可以輸出更多平臺有用的信息,比如模型評估分數(shù)、模型類型、模型訓(xùn)練的相關(guān)表和字段名、模型參數(shù)、訓(xùn)練上下文等等。
在模型接入預(yù)測組件時,預(yù)測組件讀取自定義文件,獲取到模型的所在框架和模型類型,并通過對應(yīng)的模型框架加載模型文件即可。
在在線預(yù)測中,通過讀取到訓(xùn)練的上下文,可以把模型訓(xùn)練上游所需的預(yù)處理過程一并加載到在線預(yù)測過程中,減輕用戶單獨預(yù)處理過程的負擔。
在線預(yù)測系統(tǒng)搭建
在線預(yù)測系統(tǒng)對不同用戶的需求場景提供不同的調(diào)用方式。
本地模式是在線預(yù)測平臺把模型信息整體自動封裝在服務(wù)jar包中,提供給用戶輕量級調(diào)用;云模式是在線預(yù)測服務(wù)平臺結(jié)合Docker服務(wù),生成一組計算集群。云模式支持HTTP服務(wù)與RPC服務(wù)。在HTTP服務(wù)中,系統(tǒng)通過Consul服務(wù)申請動態(tài)域名,并通過自動發(fā)現(xiàn)服務(wù)關(guān)聯(lián)Docker服務(wù)。用戶僅需通過服務(wù)提供的域名訪問,無需了解后端部署流程。
RPC服務(wù)是基于Dubbo實現(xiàn)。模型預(yù)測服務(wù)被Dubbo封裝后通過Docker連接ZooKeeper實現(xiàn)服務(wù)發(fā)現(xiàn)。用戶端僅需通過客戶端連接指定的連接字即可訪問服務(wù)。
離線預(yù)測平臺是基于流程的發(fā)布,在線預(yù)測則是基于模型和模型上下文信息進行發(fā)布。模型管理平臺中使用推模式和拉模式兩種方式部署在線服務(wù)。拉模式為用戶主動更新服務(wù)的模式;而推模式為模型在模型管理平臺中更新后被動更新的方式。通過兩種方式的結(jié)合,在線服務(wù)覆蓋所有模型更新場景。
案例介紹
反作弊業(yè)務(wù)是一個獨立的業(yè)務(wù)系統(tǒng),管理反作弊相關(guān)業(yè)務(wù)邏輯和業(yè)務(wù)數(shù)據(jù)。反作弊平臺定義和構(gòu)建了不同反作弊識別過濾場景,并自動拆解成工作流在數(shù)據(jù)中臺中具體運維。涉及到算法相關(guān)的流程,通過數(shù)據(jù)中臺轉(zhuǎn)到機器學(xué)習(xí)平臺處理,處理后的結(jié)果也會回到數(shù)據(jù)中臺。
下圖中包括了流量反作弊所有的場景和相關(guān)算法,包括常見的監(jiān)督算法,監(jiān)督算法,黑白樣本,然后聚類算法,異常檢測算法,此外,還有基于團伙的同類的算法,和一些深度學(xué)習(xí)的算法。
每天大概能過濾大概千萬級以上的日志,在線預(yù)測峰值的時候是要超過能達到萬級的KPS,所有擁有這么一個平臺,效率提升大致在80%以上。