bilibili基于 Flink 的机器学习工作流平台在 b 站的应用
分享嘉賓:張楊,B 站資深開發(fā)工程師
導(dǎo)讀:整個(gè)機(jī)器學(xué)習(xí)的過(guò)程,從數(shù)據(jù)上報(bào)、到特征計(jì)算、到模型訓(xùn)練、再到線上部署、最終效果評(píng)估,整個(gè)流程非常冗長(zhǎng)。在 b 站,多個(gè)團(tuán)隊(duì)都會(huì)搭建自己的機(jī)器學(xué)習(xí)鏈路,來(lái)完成各自的機(jī)器學(xué)習(xí)需求,工程效率和數(shù)據(jù)質(zhì)量都難以保證。于是我們基于 Flink 社區(qū)的 aiflow 項(xiàng)目,構(gòu)建了整套機(jī)器學(xué)習(xí)的標(biāo)準(zhǔn)工作流平臺(tái),加速機(jī)器學(xué)習(xí)流程構(gòu)建,提升多個(gè)場(chǎng)景的數(shù)據(jù)實(shí)效和準(zhǔn)確性。本次分享將介紹 b 站的機(jī)器學(xué)習(xí)工作流平臺(tái) ultron 在 b 站多個(gè)機(jī)器學(xué)習(xí)場(chǎng)景上的應(yīng)用。目錄:
1、機(jī)器學(xué)習(xí)實(shí)時(shí)化
2、Flink 在 B 站機(jī)器學(xué)習(xí)的使用
3、機(jī)器學(xué)習(xí)工作流平臺(tái)構(gòu)建
4、未來(lái)規(guī)劃
GitHub 地址
https://github.com/apache/flink
歡迎大家給 Flink 點(diǎn)贊送 star~
一、機(jī)器學(xué)習(xí)實(shí)時(shí)化
首先講下機(jī)器學(xué)習(xí)的實(shí)時(shí)化,主要是分為三部分:
- 第一是樣本的實(shí)時(shí)化。傳統(tǒng)的機(jī)器學(xué)習(xí),樣本全部都是 t+1,也就是說(shuō),今天模型用的是昨天的訓(xùn)練數(shù)據(jù),每天早上使用昨天的全天數(shù)據(jù)訓(xùn)練一次模型;
- 第二是特征的實(shí)時(shí)化。以前的特征也基本都是 t+1,這樣就會(huì)帶來(lái)一些推薦不準(zhǔn)確的問(wèn)題。比如,今天我看了很多新的視頻,但給我推薦的卻還是一些昨天或者更久之前看到的內(nèi)容;
- 第三就是模型訓(xùn)練的實(shí)時(shí)化。我們有了樣本的實(shí)時(shí)化和特征的實(shí)時(shí)化之后,模型訓(xùn)練也是完全可以做到在線訓(xùn)練實(shí)時(shí)化的,能帶來(lái)更實(shí)時(shí)的推薦效果。
傳統(tǒng)離線鏈路
上圖是傳統(tǒng)的離線鏈路圖,首先是 APP 產(chǎn)生日志或者服務(wù)端產(chǎn)生 log,整個(gè)數(shù)據(jù)會(huì)通過(guò)數(shù)據(jù)管道落到 HDFS 上,然后每天 t+1 做一些特征生成和模型訓(xùn)練,特征生成會(huì)放到特征存儲(chǔ)里面,可能是 redis 或者一些其他的 kv 存儲(chǔ),再給到上面的 inference 在線服務(wù)。
傳統(tǒng)離線鏈路的不足
那它有什么問(wèn)題呢?
- 第一是 t+1 數(shù)據(jù)模型的特征時(shí)效性都很低,很難做到特別高時(shí)效性的更新;
- 第二是整個(gè)模型訓(xùn)練或者一些特征生產(chǎn)的過(guò)程中,每天都要用天級(jí)的數(shù)據(jù),整個(gè)訓(xùn)練或者特征生產(chǎn)的時(shí)間非常長(zhǎng),對(duì)集群的算力要求非常高。
實(shí)時(shí)鏈路
上圖我們進(jìn)行優(yōu)化之后整個(gè)實(shí)時(shí)鏈路的過(guò)程,紅叉的部分是被去掉的。整個(gè)數(shù)據(jù)上報(bào)后通過(guò) pipeline 直接落到實(shí)時(shí)的 kafka,之后會(huì)做一個(gè)實(shí)時(shí)特征的生成,還有實(shí)時(shí)樣本的生成,特征結(jié)果會(huì)寫到 feature store 里面去,樣本的生成也需要從 feature store 里面去讀取一些特征。
生成完樣本之后我們直接進(jìn)行實(shí)時(shí)訓(xùn)練。整個(gè)右邊的那個(gè)很長(zhǎng)的鏈路已經(jīng)去掉了,但是離線特征的部分我們還是保存了。因?yàn)獒槍?duì)一些特殊特征我們還是要做一些離線計(jì)算,比如一些特別復(fù)雜不好實(shí)時(shí)化的或者沒(méi)有實(shí)時(shí)化需求的。
二、Flink 在 b 站機(jī)器學(xué)習(xí)的使用
下面講下我們是怎么做到實(shí)時(shí)樣本、實(shí)時(shí)特征和實(shí)時(shí)效果評(píng)估的。
- 第一個(gè)是實(shí)時(shí)樣本。Flink 目前托管 b 站所有推薦業(yè)務(wù)樣本數(shù)據(jù)生產(chǎn)流程;
- 第二個(gè)是實(shí)時(shí)特征。目前相當(dāng)一部分特征都使用了 Flink 進(jìn)行實(shí)時(shí)計(jì)算,時(shí)效性非常高。有很多特征是使用離線 + 實(shí)時(shí)組合的方式得出結(jié)果,歷史數(shù)據(jù)用離線算,實(shí)時(shí)數(shù)據(jù)用 Flink,讀取特征的時(shí)候就用拼接。
但是,這兩套計(jì)算邏輯有的時(shí)候不能復(fù)用,所以我們也在嘗試使用 Flink 做批流一體,將特征的定義全部用 Flink 來(lái)做,根據(jù)業(yè)務(wù)需要,實(shí)時(shí)算或者離線算,底層的計(jì)算引擎全部是 Flink;
- 第三是實(shí)時(shí)效果的一個(gè)評(píng)估,我們使用了 Flink+olap 來(lái)打通整個(gè)實(shí)時(shí)計(jì)算 + 實(shí)時(shí)分析鏈路,進(jìn)行最終的模型效果評(píng)估。
實(shí)時(shí)樣本生成
上圖是目前實(shí)時(shí)樣本的生成,是針對(duì)整個(gè)推薦業(yè)務(wù)鏈路的。日志數(shù)據(jù)落入 kafka 后,首先我們做一個(gè) Flink 的 label-join,把點(diǎn)擊和展現(xiàn)進(jìn)行拼接。結(jié)果繼續(xù)落入 kafka 后,再接一個(gè) Flink 任務(wù)進(jìn)行特征 join,特征 join 會(huì)拼接多個(gè)特征,有些特征是公域特征,有些是業(yè)務(wù)方的私域特征。特征的來(lái)源比較多樣,有離線也有實(shí)時(shí)。特征全部補(bǔ)全之后,就會(huì)生成一個(gè) instance 樣本數(shù)據(jù)落到 kafka,給后面的訓(xùn)練模型使用。
實(shí)時(shí)特征生成
上圖是實(shí)時(shí)特征的生成,這邊列的是一個(gè)比較復(fù)雜的特征的過(guò)程,整個(gè)計(jì)算流程涉及到了 5 個(gè)任務(wù)。第一個(gè)任務(wù)是離線任務(wù),后面有 4 個(gè) Flink 任務(wù),一系列復(fù)雜計(jì)算后生成的一個(gè)特征落到 kafka 里面,再寫入 feature-store,然后被在線預(yù)測(cè)或者實(shí)時(shí)訓(xùn)練所用到。
實(shí)時(shí)效果評(píng)估
上圖是實(shí)時(shí)效果的評(píng)估,推薦算法關(guān)注的一個(gè)非常核心的指標(biāo)就是 ctr 點(diǎn)擊率,做完 label-join 之后,就可以算出 ctr 數(shù)據(jù)了,除了進(jìn)行下一步的樣本生成之外,同時(shí)會(huì)導(dǎo)一份數(shù)據(jù)到 clickhouse 里面,報(bào)表系統(tǒng)對(duì)接后就可以看到非常實(shí)時(shí)的效果。數(shù)據(jù)本身會(huì)帶上實(shí)驗(yàn)標(biāo)簽,在 clickhouse 里面可以根據(jù)標(biāo)簽進(jìn)行實(shí)驗(yàn)區(qū)分,看出對(duì)應(yīng)的實(shí)驗(yàn)效果。
三、機(jī)器學(xué)習(xí)工作流平臺(tái)構(gòu)建
痛點(diǎn)
- 機(jī)器學(xué)習(xí)的整個(gè)鏈路里面有樣本生成、特征生成、訓(xùn)練、預(yù)測(cè)、效果評(píng)估,每個(gè)部分都要配置開發(fā)很多任務(wù),一個(gè)模型的上線最終需要橫跨多個(gè)任務(wù),鏈路非常長(zhǎng)。
- 新的算法同學(xué)很難去理解這個(gè)復(fù)雜鏈路的全貌,學(xué)習(xí)成本極高。
- 整個(gè)鏈路的改動(dòng)牽一發(fā)而動(dòng)全身,非常容易出故障。
- 計(jì)算層用到多個(gè)引擎,批流混用,語(yǔ)義很難保持一致,同樣的邏輯要開發(fā)兩套,保持沒(méi)有 gap 也很困難。
- 整個(gè)實(shí)時(shí)化成本門檻也比較高,需要有很強(qiáng)的實(shí)時(shí)離線能力,很多小的業(yè)務(wù)團(tuán)隊(duì)在沒(méi)有平臺(tái)支持下難以完成。
上圖是一個(gè)模型從數(shù)據(jù)準(zhǔn)備到訓(xùn)練的大概過(guò)程,中間涉及到了七八個(gè)節(jié)點(diǎn),那我們能不能在一個(gè)平臺(tái)上完成所有的流程操作?我們?yōu)槭裁匆?Flink?是因?yàn)槲覀儓F(tuán)隊(duì)實(shí)時(shí)計(jì)算平臺(tái)是基于 Flink 來(lái)做的,我們也看到了 Flink 在批流一體上的潛力以及在實(shí)時(shí)模型訓(xùn)練和部署上一些未來(lái)發(fā)展路徑。
引入 Aiflow
Aiflow 是阿里的 Flink 生態(tài)團(tuán)隊(duì)開源的一套機(jī)器學(xué)習(xí)工作流平臺(tái),專注于流程和整個(gè)機(jī)器學(xué)習(xí)鏈路的標(biāo)準(zhǔn)化。去年八、九月份,我們?cè)诤退麄兘佑|后,引入了這樣一套系統(tǒng),一起共建完善,并開始逐漸在 b 站落地。它把整個(gè)機(jī)器學(xué)習(xí)抽象成圖上的 example、transform 、Train、validation、inference 這些過(guò)程。在項(xiàng)目架構(gòu)上非常核心的能力調(diào)度就是支持流批混合依賴,元數(shù)據(jù)層支持模型管理,非常方便的進(jìn)行模型的迭代更新。我們基于此搭建了我們的機(jī)器學(xué)習(xí)工作流平臺(tái)。
平臺(tái)特性
接下來(lái)講一下平臺(tái)特性:
- 第一是使用 Python 定義工作流。在 ai 方向,大家用 Python 還是比較多的,我們也參考了一些外部的,像 Netflix 也是使用 Python 來(lái)定義這種機(jī)器學(xué)習(xí)的工作流。
- 第二是支持批流任務(wù)混合依賴。在一個(gè)完整鏈路里面,涉及到的實(shí)時(shí)離線過(guò)程都可以加入到里面,并且批流任務(wù)之間可以通過(guò)信號(hào)就行互相依賴。
- 第三是支持一鍵克隆整個(gè)實(shí)驗(yàn)過(guò)程。從原始 log 到最終整個(gè)實(shí)驗(yàn)拉起訓(xùn)練這塊,我們是希望能夠一鍵整體鏈路克隆,快速拉起一個(gè)全新的實(shí)驗(yàn)鏈路。
- 第四是一些性能方面的優(yōu)化,支持資源共享。
- 第五是支持特征回溯批流一體。很多特征的冷啟動(dòng)需要計(jì)算歷史很長(zhǎng)時(shí)間的數(shù)據(jù),專門為冷啟動(dòng)寫一套離線特征計(jì)算邏輯成本非常高,而且很難和實(shí)時(shí)特征計(jì)算結(jié)果對(duì)齊,我們支持直接在實(shí)時(shí)鏈路上來(lái)回溯離線特征。
基本架構(gòu)
上圖是基本架構(gòu),最上面是業(yè)務(wù),最下面是引擎。目前支持的引擎也比較多:Flink、spark、Hive、kafka、Hbase、Redis。其中有計(jì)算引擎,也有存儲(chǔ)引擎。以 aiflow 作為中間的工作流程管理,Flink 作為核心的計(jì)算引擎,來(lái)設(shè)計(jì)整個(gè)工流平臺(tái)。
工作流描述
整個(gè)工作流是用 Python 來(lái)描述的,在 python 里面用戶只需要定義計(jì)算節(jié)點(diǎn)和資源節(jié)點(diǎn),以及這些節(jié)點(diǎn)之間的依賴關(guān)系即可,語(yǔ)法有點(diǎn)像調(diào)度框架 airflow。
依賴關(guān)系定義
批流的依賴關(guān)系主要有 4 種:流到批,流到流,批到流,批到批。基本可以滿足目前我們業(yè)務(wù)上的所有需求。
資源共享
資源共享主要是用來(lái)做性能方面,因?yàn)楹芏鄷r(shí)候一個(gè)機(jī)器的學(xué)習(xí)鏈路非常長(zhǎng),比如剛剛那個(gè)圖里面我經(jīng)常改動(dòng)的可能只有五六個(gè)節(jié)點(diǎn),當(dāng)我想重新拉起整個(gè)實(shí)驗(yàn)流程,把整個(gè)圖克隆一遍,中間我只需要改動(dòng)其中的部分節(jié)點(diǎn)或者大部分節(jié)點(diǎn),上游節(jié)點(diǎn)是可以做數(shù)據(jù)共享的。
這個(gè)是技術(shù)上的實(shí)現(xiàn),克隆之后對(duì)共享節(jié)點(diǎn)做了一個(gè)狀態(tài)追蹤。
實(shí)時(shí)訓(xùn)練
上圖是實(shí)時(shí)訓(xùn)練的過(guò)程。特征穿越是一個(gè)非常常見的問(wèn)題,多個(gè)計(jì)算任務(wù)的進(jìn)度不一致時(shí)就會(huì)發(fā)生。在工作流平臺(tái)里面,我們定義好各個(gè)節(jié)點(diǎn)的依賴關(guān)系即可,一旦節(jié)點(diǎn)之間發(fā)生了依賴,處理進(jìn)度就會(huì)進(jìn)行同步,通俗來(lái)說(shuō)就是快的等慢的,避免特征穿越。在 Flink 里面我們是使用 watermark 來(lái)定義處理進(jìn)度。
特征回溯
上圖是特征回溯的過(guò)程,我們使用實(shí)時(shí)鏈路,直接去回溯它歷史數(shù)據(jù)。離線和實(shí)時(shí)數(shù)據(jù)畢竟不同,這中間有很多問(wèn)題需要解決,因此也用到了 spark,后面這塊我們會(huì)改成 Flink。
特征回溯的問(wèn)題
特征回溯有幾個(gè)比較大的問(wèn)題:
- 第一是如何保證數(shù)據(jù)的順序性。實(shí)時(shí)數(shù)據(jù)有個(gè)隱含的語(yǔ)義就是數(shù)據(jù)是順序進(jìn)來(lái)的,生產(chǎn)出來(lái)立馬處理,天然有一定的順序性。但是離線的 HDFS 不是,HDFS 是有分區(qū)的,分區(qū)內(nèi)的數(shù)據(jù)完全亂序,實(shí)際業(yè)務(wù)里面大量計(jì)算過(guò)程是依賴時(shí)序的,如何解決離線數(shù)據(jù)的亂序是一個(gè)很大的問(wèn)題。
- 第二是如何保證特征和樣本版本的一致性。比如有兩條鏈路,一條是特征的生產(chǎn),一條是樣本生產(chǎn),樣本生產(chǎn)依賴特征生產(chǎn),如何保證它們之間版本的一致性,沒(méi)有穿越?
- 第三就是如何保證實(shí)時(shí)鏈路和回溯鏈路計(jì)算邏輯的一致?這個(gè)問(wèn)題其實(shí)對(duì)我們來(lái)說(shuō)不用擔(dān)心,我們是直接在實(shí)時(shí)鏈路上回溯離線數(shù)據(jù)。
- 第四是一些性能方面的問(wèn)題,怎么快速得算完大量的歷史數(shù)據(jù)。
解決方案
以下是第一、第二個(gè)問(wèn)題的解決方案:
- 第一個(gè)問(wèn)題。為了數(shù)據(jù)的順序性,我們 HDFS 的離線數(shù)據(jù)進(jìn)行 kafka 化處理,這里不是把它灌到 kafka 里面去,而是模擬 kafka 的數(shù)據(jù)架構(gòu),分區(qū)并且分區(qū)內(nèi)有序,我們把 HDFS 數(shù)據(jù)也處理成類似的架構(gòu),模擬成邏輯上的分區(qū),并且邏輯分區(qū)內(nèi)有序,Flink 讀取的 hdfssource 也進(jìn)行了對(duì)應(yīng)的開發(fā)支持這種模擬的數(shù)據(jù)架構(gòu)。這塊的模擬計(jì)算目前是使用 spark 做的,后面我們會(huì)改成 Flink。
第二個(gè)問(wèn)題分為兩部分:
- 實(shí)時(shí)特征部分的解決依賴于 Hbase 存儲(chǔ),Hbase 支持根據(jù)版本查詢。特征計(jì)算完后直接按照版本寫入 Hbase,樣本生成的時(shí)候去查 Hbase 帶上對(duì)應(yīng)的版本號(hào)即可,這里面的版本通常是數(shù)據(jù)時(shí)間。
- 離線特征部分,因?yàn)椴恍枰匦掠?jì)算了,離線存儲(chǔ) hdfs 都有,但是不支持點(diǎn)查,這塊進(jìn)行 kv 化處理就好,為了性能我們做了異步預(yù)加載。
異步預(yù)加載的過(guò)程如圖。
四、未來(lái)規(guī)劃
接下來(lái)介紹下我們后面規(guī)劃。
- 一個(gè)是數(shù)據(jù)質(zhì)量保證。現(xiàn)在整個(gè)鏈路越來(lái)越長(zhǎng),可能有 10 個(gè)節(jié)點(diǎn)、 20 個(gè)節(jié)點(diǎn),那怎么在整個(gè)鏈路出問(wèn)題的時(shí)候快速發(fā)現(xiàn)問(wèn)題點(diǎn)。這里我們是想針對(duì)節(jié)點(diǎn)集來(lái)做 dpc,對(duì)每個(gè)節(jié)點(diǎn)我們可以自定義一些數(shù)據(jù)質(zhì)量校驗(yàn)規(guī)則,數(shù)據(jù)通過(guò)旁路到統(tǒng)一的 dqc-center 進(jìn)行規(guī)則運(yùn)算告警。
- 第二是全鏈路的 exactly once,工作流節(jié)點(diǎn)之間如何保證精確一致,這塊目前還沒(méi)有想清楚。
- 第三是我們會(huì)在工作流里面加入模型訓(xùn)練和部署的節(jié)點(diǎn)。訓(xùn)練和部署可以是連接到別的平臺(tái),也可能是 Flink 本身支持的訓(xùn)練模型和部署服務(wù)。
嘉賓介紹:張楊,17 年入職 b 站,從事大數(shù)據(jù)方面工作。
原文鏈接:https://developer.aliyun.com/article/784356?
版權(quán)聲明:本文內(nèi)容由阿里云實(shí)名注冊(cè)用戶自發(fā)貢獻(xiàn),版權(quán)歸原作者所有,阿里云開發(fā)者社區(qū)不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。具體規(guī)則請(qǐng)查看《阿里云開發(fā)者社區(qū)用戶服務(wù)協(xié)議》和《阿里云開發(fā)者社區(qū)知識(shí)產(chǎn)權(quán)保護(hù)指引》。如果您發(fā)現(xiàn)本社區(qū)中有涉嫌抄襲的內(nèi)容,填寫侵權(quán)投訴表單進(jìn)行舉報(bào),一經(jīng)查實(shí),本社區(qū)將立刻刪除涉嫌侵權(quán)內(nèi)容。總結(jié)
以上是生活随笔為你收集整理的bilibili基于 Flink 的机器学习工作流平台在 b 站的应用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 回顾 | Apache Flink 1.
- 下一篇: Flink + Iceberg 在去哪儿