利用已有的大數(shù)據(jù)技術(shù),如何構(gòu)建機(jī)器學(xué)習(xí)平臺(tái)
機(jī)器如何學(xué)習(xí)?
人腦具備不斷積累經(jīng)驗(yàn)的能力,依賴經(jīng)驗(yàn)我們便具備了分析處理的能力,比如我們要去菜場(chǎng)挑一個(gè)西瓜,別人或者自己的經(jīng)驗(yàn)告訴我們色澤青綠、根蒂蜷縮、紋路清晰、敲聲渾響的西瓜比較好吃。
我們具備這樣的能力,那么機(jī)器呢?機(jī)器不是只接收指令,處理指令嗎?和人腦類似,可以喂給機(jī)器歷史數(shù)據(jù),機(jī)器依賴建模算法生成模型,根據(jù)模型便可以處新的數(shù)據(jù)得到未知屬性。以下便是機(jī)器學(xué)習(xí)與人腦歸納經(jīng)驗(yàn)的類別圖:
平臺(tái)設(shè)想
在同程內(nèi)部,我們對(duì)應(yīng)用機(jī)器學(xué)習(xí)的一些團(tuán)隊(duì)做了了解,發(fā)現(xiàn)他們普遍的處理步驟如下:
這個(gè)過程中存在一些痛點(diǎn):
- 線上數(shù)據(jù)到線下搬運(yùn)耗時(shí)
- 訓(xùn)練數(shù)據(jù)量難均衡,如果訓(xùn)練數(shù)據(jù)量較大,用 R 或者 Python 做單機(jī)訓(xùn)練將會(huì)非常耗時(shí)。如果訓(xùn)練數(shù)據(jù)量較小,訓(xùn)練出來的模型容易過擬合。
- 對(duì)分析和挖掘人員的編碼能力有一定的要求。
因此我們覺得可以構(gòu)建一套平臺(tái)化的產(chǎn)品直接對(duì)線上數(shù)據(jù)進(jìn)行建模實(shí)驗(yàn),節(jié)省機(jī)器學(xué)習(xí)的開發(fā)成本,降低機(jī)器學(xué)習(xí)的應(yīng)用門檻。
平臺(tái)構(gòu)建
設(shè)計(jì)目標(biāo)
- 支持大數(shù)據(jù)量的建模實(shí)驗(yàn),通過并行計(jì)算縮短耗時(shí)
- 抽象出最小執(zhí)行單元,配置簡(jiǎn)單。通過拖拽以及連線的形式構(gòu)建建模流程
- 支持常用的機(jī)器學(xué)習(xí)學(xué)習(xí)算法處理回歸、分類、聚類等問題支持常用的特征工程組件,如標(biāo)準(zhǔn)化、歸一化、缺失值處理等
- 支持算法評(píng)估結(jié)果可視化
算法庫
在算法庫方面,我們選擇了 Spark,相比于 R 或者 Python,Spark 具備分布式計(jì)算的能力,更高效。
ml 和 mllib 都是 Spark 中的機(jī)器學(xué)習(xí)庫,目前常用的機(jī)器學(xué)習(xí)功能兩個(gè)個(gè)庫都能滿足需求。ml 主要操作的是 DataFrame,相比于 mllib 在 RDD 提供的基礎(chǔ)操作,ml 在 DataFrame 上的抽象級(jí)別更高,數(shù)據(jù)和操作耦合度更低。
ml 提供 pipeline,和 Python 的 sklearn 一樣,可以把很多操作 (算法 / 特征提取 / 特征轉(zhuǎn)換) 以管道的形式串起來,對(duì)于任務(wù)組合非常便利,如 StringToIndexer、IndexerToString、VectorAssembler 等。
組件化設(shè)計(jì)
從架構(gòu)設(shè)計(jì)上來說,不管是算法單元、特征工程單元、評(píng)估單元或者其他工具單元,我們認(rèn)為都可以以組件的形式來設(shè)計(jì)。借助通用的接口行為以及不同的實(shí)現(xiàn)可以達(dá)到松耦合、易擴(kuò)展的目的。
上圖是整個(gè)設(shè)計(jì)類圖的一部分,實(shí)際上我們做了較多層次的抽象以及公用代碼。下面看看核心類 BaseTask:
run 方法的實(shí)現(xiàn)是一套模板,步驟如下:
每個(gè)組件只要實(shí)現(xiàn)自己的核心邏輯 execute 方法就可以了。
平臺(tái)迭代
v1.0(平臺(tái)核心架構(gòu))
基于上述的設(shè)計(jì)目標(biāo),機(jī)器學(xué)習(xí)平臺(tái)***個(gè)版本的架構(gòu)如下:
用戶通過界面拖拽組件構(gòu)建建模流程,并將組件配置以及依賴關(guān)系保存到 DB 中
- 用戶可以在界面上觸發(fā)建模試驗(yàn)的運(yùn)行,實(shí)際上通過 spark-submit 提交一個(gè) spark 任務(wù)
- Ml Engine 負(fù)責(zé)這個(gè)任務(wù)的執(zhí)行,在 Driver 端會(huì)從 DB 中獲取當(dāng)前試驗(yàn)的依賴組件以及流程關(guān)系。這些組件將依次運(yùn)行,涉及 RDD 相關(guān)的操作時(shí)會(huì)提交到 Spark Executor 進(jìn)行并行計(jì)算
流程 & 評(píng)估視圖
***個(gè)版本我們并沒有提供太多的算法組件,只有線性回歸和邏輯回歸,但是基于組件化的思想,我們非常有信心在后期快速迭代。
除了算法較少外,結(jié)合業(yè)務(wù)反饋與自身思考。我們覺得機(jī)器學(xué)習(xí)平臺(tái)可以做更多的事:
- 平臺(tái)定位不僅僅是實(shí)驗(yàn)控制臺(tái),增加預(yù)測(cè)結(jié)果落地的功能(離線計(jì)算)
- 訓(xùn)練模型隨著歷史數(shù)據(jù)的不斷擴(kuò)充在大部分情況下都應(yīng)該是個(gè)周期性的事情。我們希望在平臺(tái)層面能夠幫助用戶托管這個(gè)過程。
v2.0(擴(kuò)充組件 & 離線計(jì)算 & 周期性調(diào)度)
第二個(gè)版本中,我們首先基于原有的設(shè)計(jì)框架擴(kuò)充完善了相關(guān)實(shí)用組件:
同時(shí)在第二個(gè)版本中,我們?cè)诩?xì)節(jié)上又做了一些完善:
- 建模實(shí)驗(yàn)運(yùn)行狀態(tài)流程展示,用戶可以觀察到每個(gè)組件的運(yùn)行時(shí)間,狀態(tài),日志等
- 依賴完整的組件可以進(jìn)行局部運(yùn)行,在一個(gè)較復(fù)雜的建模實(shí)驗(yàn)中,完全可以先進(jìn)行局部驗(yàn)證以及參數(shù)調(diào)整
- 建模實(shí)驗(yàn)支持克隆
離線計(jì)算
我們提供了‘字段落地’的工具組件,可以將預(yù)測(cè)結(jié)果以 csv 的格式落入 hdfs 中:
周期性調(diào)度 & 宏變量支持
我們的另一款產(chǎn)品:大數(shù)據(jù)開發(fā)套件(BDK),函蓋周期性調(diào)度的功能,機(jī)器學(xué)習(xí)平臺(tái)的建模實(shí)驗(yàn)可以以子任務(wù)的形式嵌入其中,結(jié)合宏變量(某種規(guī)則的語法替換,例如’/%Y/%m/%d’可以表示為當(dāng)前天等等)用戶可以在我們的平臺(tái)中托管他們的建模試驗(yàn),從而達(dá)到周期性離線計(jì)算的目的。
架構(gòu)
綜上,豐富組件及完善功能、離線計(jì)算結(jié)果落地、結(jié)合 BDK 進(jìn)行周期性離線計(jì)算是我們平臺(tái)第二個(gè)版本主要關(guān)注的,具體架構(gòu)有了以下演進(jìn):
v3.0(實(shí)時(shí)預(yù)測(cè) & 交叉驗(yàn)證)
實(shí)時(shí)預(yù)測(cè)
在我們的平臺(tái)中可以通過建模實(shí)驗(yàn)訓(xùn)練模型,模型可以通過 PMML 這樣的標(biāo)準(zhǔn)導(dǎo)出,同樣也可以通過我們的模型導(dǎo)出功能將模型以 parquet 格式保存在 Hdfs 相應(yīng)的目錄上。用戶可以得到這些模型標(biāo)準(zhǔn),自己去實(shí)現(xiàn)一些功能。但是我們覺得實(shí)時(shí)預(yù)測(cè)的功能在我們平臺(tái)上也可以抽象出來。于是 3.0 的架構(gòu)中我們開發(fā)了提供實(shí)時(shí)預(yù)測(cè)服務(wù)的 tcscoring 系統(tǒng):
tcscoring 系統(tǒng)的依賴介質(zhì)就是模型的 PMML 文件,用戶可以在機(jī)器學(xué)習(xí)平臺(tái)上直接部署訓(xùn)練完成了的模型對(duì)應(yīng)的 PMML 文件,或者通過其他路徑生成的 PMML 文件。部署成功后會(huì)返回用于預(yù)測(cè)的 rest 接口供業(yè)務(wù)使用:
當(dāng)然,PMML 的部署也可以結(jié)合 BDK 設(shè)置成周期性調(diào)度,這些結(jié)合模型的周期性訓(xùn)練,整個(gè)訓(xùn)練 + 預(yù)測(cè)的過程都可以交給機(jī)器學(xué)習(xí)平臺(tái) +BDK 實(shí)現(xiàn)托管。
交叉驗(yàn)證
在機(jī)器學(xué)習(xí)平臺(tái)的第三個(gè)版本中,我們還有個(gè)關(guān)注點(diǎn)就是交叉驗(yàn)證,之前的版本中用戶一次只能實(shí)驗(yàn)一組超參數(shù),有了交叉驗(yàn)證,用戶便可以在一次實(shí)驗(yàn)中配置多組超參數(shù),在訓(xùn)練集中在按比例進(jìn)行循環(huán)拆分,一部分訓(xùn)練,一部分驗(yàn)證,從而得到***模型:
平臺(tái)展望
個(gè)性化
迭代完 3 個(gè)版本后,機(jī)器學(xué)習(xí)平臺(tái)抽象出了很多通用的東西,但是還有一些個(gè)性化的東西沒有辦法很好地變現(xiàn)。我們的想法是對(duì)于用戶來說,***的個(gè)性化途徑就是讓用戶自己寫代碼,我們會(huì)嘗試開放接口自定義插件,同時(shí)利用動(dòng)態(tài)編譯技術(shù)加載這些個(gè)性化的組件,融合進(jìn)建模流程中。
融合其他算法包
我們目前也在嘗試融合 spark ml 之外的算法包,如使用度較廣的 xgboost 等。另一方面目前的算法還是基于傳統(tǒng)的機(jī)器學(xué)習(xí)算法,對(duì)于深度學(xué)習(xí),不管是嵌入 tensorflow 還是使用一些第三方的深度學(xué)習(xí)庫,如 Deeplearning4j 等。我們接下來會(huì)嘗試融合這些 spark ml 之外的算法包。