00. 平臺(tái)的業(yè)務(wù)
從平臺(tái)這個(gè)概念本身來(lái)說(shuō),它提供的是支撐作用,通過(guò)整合、管理不同的基礎(chǔ)設(shè)施、技術(shù)框架,一些通用的流程規(guī)范來(lái)形成一個(gè)通用的、易用的GUI來(lái)給用戶使用。通用性是它的考量之一、也是所有平臺(tái)的愿景之一:希望平臺(tái)能適用于各個(gè)不同的業(yè)務(wù)線來(lái)產(chǎn)生價(jià)值。所以從業(yè)務(wù)上來(lái)說(shuō),作為一個(gè)平臺(tái)本身是不會(huì)、也不應(yīng)該有太多specific的業(yè)務(wù)功能的。當(dāng)然這只是理想情況,有時(shí)候?yàn)榱似脚_(tái)使用方的需求,也不得不加上一些業(yè)務(wù)領(lǐng)域特定的功能或者補(bǔ)丁來(lái)適應(yīng)業(yè)務(wù)方,特別是平臺(tái)建設(shè)初期,在沒(méi)有太多業(yè)務(wù)的使用的時(shí)候。整體來(lái)看,平臺(tái)自身的業(yè)務(wù)可謂是非常簡(jiǎn)單,可以用一張圖來(lái)表示:
平臺(tái)的業(yè)務(wù)
上面這個(gè)分支是標(biāo)準(zhǔn)的機(jī)器學(xué)習(xí)流程的抽象。從數(shù)據(jù)準(zhǔn)備,數(shù)據(jù)處理,模型訓(xùn)練,再到模型上線實(shí)現(xiàn)價(jià)值完成整個(gè)流程。
下面這個(gè)分支,也是機(jī)器學(xué)習(xí)和數(shù)據(jù)科學(xué)領(lǐng)域中不可或缺的,主要指的是類似于Jupyter Notebook這類,提供高度靈活性和可視化的數(shù)據(jù)探索服務(wù),用戶可以在里面進(jìn)行數(shù)據(jù)探索、嘗試一些實(shí)驗(yàn)來(lái)驗(yàn)證想法。當(dāng)然當(dāng)平臺(tái)擁有了SDK/CLI之后,也可以在里面無(wú)縫集成上面這條線里面的功能,將靈活性與功能性融合在一起。
01. 基礎(chǔ)設(shè)施
上面提到平臺(tái)本身是整合了不同的基礎(chǔ)設(shè)施、技術(shù)框架和流程規(guī)范。在正式開(kāi)始之前,有必要介紹下本文后續(xù)所使用的的基礎(chǔ)設(shè)施和框架。
在容器化、云化的潮流中,Kubernetes基本上是必選的基礎(chǔ)設(shè)施,它提供靈活易用的基礎(chǔ)設(shè)施和應(yīng)用管理能力,同時(shí)擴(kuò)展性非常好。它可以用于
部署平臺(tái)本身
調(diào)度一些批處理任務(wù)(這里主要指離線任務(wù),如數(shù)據(jù)處理、模型訓(xùn)練。適用的技術(shù)為:Spark on kubernetes/Kubernetes Job),
部署常駐服務(wù)(一般指的是RESTful/gRPC等為基礎(chǔ)的服務(wù),如啟動(dòng)的Notebook、模型發(fā)布后的模型推理服務(wù)。適用的技術(shù)為Kubernetes Deployment/Kubernetes Statefulset/Service等)。
機(jī)器學(xué)習(xí)的主要場(chǎng)景下,數(shù)據(jù)量都是非常大的,所以Hadoop這一套也是必不可少的,其中包含基礎(chǔ)的Hadoop(HDFS/HIVE/HBase/Yarn)以及上層計(jì)算框架Spark等。大數(shù)據(jù)技術(shù)體系主要用于數(shù)據(jù)存儲(chǔ)和分布式數(shù)據(jù)處理、訓(xùn)練的業(yè)務(wù)。
最后就是一些機(jī)器學(xué)習(xí)框架,Spark系的(Spark MLlib/Angel),Python系的(Tensorflow/Pytorch)。主要用途就是模型訓(xùn)練和模型發(fā)布(Serving)的業(yè)務(wù)。
02.原始數(shù)據(jù)
原始數(shù)據(jù),也叫做數(shù)據(jù)源,也就是機(jī)器學(xué)習(xí)的燃料。平臺(tái)本身并不關(guān)心原始數(shù)據(jù)是如何被收集的,只關(guān)心數(shù)據(jù)存儲(chǔ)的方式和位置。存儲(chǔ)的方式?jīng)Q定了平臺(tái)是否能支持此種數(shù)據(jù)的操作。存儲(chǔ)的位置決定了平臺(tái)是否有權(quán)限、有能力去讀取到此數(shù)據(jù)。按主流的情況來(lái)看,原始數(shù)據(jù)的存儲(chǔ)一般支持四類形式:
傳統(tǒng)的數(shù)據(jù)庫(kù),例如RDS/NoSQL。這類數(shù)據(jù)源見(jiàn)得比較少,因?yàn)橐话阍诖髷?shù)據(jù)場(chǎng)景下,通用的解決方案是將此類數(shù)據(jù)源通過(guò)一些工具導(dǎo)入到大數(shù)據(jù)體系中(如Sqoop)。對(duì)于此類數(shù)據(jù)源的支持也是很簡(jiǎn)單的,使用通用的Driver 或者 Connector即可。
以HDFS為媒介的通用大數(shù)據(jù)存儲(chǔ)。此類數(shù)據(jù)源使用較為廣泛,最常見(jiàn)的是HDFS文件(parquet/csv/txt)和基于HDFS的HIVE數(shù)據(jù)源。另外,由于是大數(shù)據(jù)場(chǎng)景下的經(jīng)典數(shù)據(jù)源,所以上層的框架支持較為完善。
NFS。NFS由于其快速的讀寫(xiě)能力,以及悠久的歷史。很多企業(yè)內(nèi)部都有此基礎(chǔ)設(shè)施,因而已有的數(shù)據(jù)也極有可能存儲(chǔ)在上面。
OSS(對(duì)象存儲(chǔ))。最過(guò)于流行的要屬S3了。對(duì)象存儲(chǔ)是作為數(shù)據(jù)湖的經(jīng)典方案,使用簡(jiǎn)單,存儲(chǔ)理論上無(wú)限,和HDFS一樣具備數(shù)據(jù)高可用,不允許按片段更改數(shù)據(jù),只能修改整個(gè)對(duì)象是其缺點(diǎn)。
值得注意的是,NFS和OSS一般用于存儲(chǔ)非結(jié)構(gòu)化數(shù)據(jù),例如圖片和視屏?;蛘哂糜诔志没敵瞿康?,如容器存儲(chǔ),業(yè)務(wù)日志存儲(chǔ)。而HDFS和數(shù)據(jù)庫(kù)里面存放的都是結(jié)構(gòu)化、半結(jié)構(gòu)化的數(shù)據(jù),一般都是已經(jīng)經(jīng)過(guò)ETL處理過(guò)的數(shù)據(jù)。存儲(chǔ)的數(shù)據(jù)不一樣決定了后續(xù)的處理流程的區(qū)別:
NFS/OSS系數(shù)據(jù)源,基本上都是通過(guò)TensorFlow/Pytorch來(lái)處理,數(shù)據(jù)一般通過(guò)Mount或者API來(lái)操作使用。當(dāng)然也有特例,如果是使用云服務(wù),例如AWS的大數(shù)據(jù)體系的話,絕大多數(shù)場(chǎng)景下,是使用S3來(lái)代替HDFS使用的,這也得益于AWS本身對(duì)于S3的專屬EMRFS的定制化。當(dāng)然Spark本身等大數(shù)據(jù)處理框架也是支持此類云存儲(chǔ)的。
HDFS系和傳統(tǒng)數(shù)據(jù)庫(kù)系數(shù)據(jù)源,這個(gè)大數(shù)據(jù)框架、Python系框架都是可以的。
平臺(tái)一般會(huì)內(nèi)嵌對(duì)以上數(shù)據(jù)源的支持能力。對(duì)于不支持的其他存儲(chǔ),比如本地文件,一般的解決方案是數(shù)據(jù)遷移到支持的環(huán)境。
03.數(shù)據(jù)導(dǎo)入
這應(yīng)該是整個(gè)平臺(tái)里較為簡(jiǎn)單的功能,有點(diǎn)類似于元數(shù)據(jù)管理的功能,不過(guò)功能要更簡(jiǎn)單。要做的是在平臺(tái)創(chuàng)建一個(gè)對(duì)應(yīng)的數(shù)據(jù)Mapping。為保證數(shù)據(jù)源的可訪問(wèn),以及用戶的操作感知。平臺(tái)要做的事情可以分為三步:
訪問(wèn)對(duì)應(yīng)的數(shù)據(jù)源,以測(cè)試數(shù)據(jù)是否存在、是否有權(quán)限訪問(wèn)。
拉取小部分?jǐn)?shù)據(jù)作為采樣存放在平臺(tái)中(如MySQL),以便于快速展示,同時(shí)這也是數(shù)據(jù)本身的直觀展現(xiàn)(Sample)。對(duì)于圖片、視頻類的,只需要存儲(chǔ)元信息(如資源的url、大小、名稱),展示的時(shí)候通過(guò)Nginx之類的代理訪問(wèn)展示即可。
如果是有Schema的數(shù)據(jù)源,例如Hive表,數(shù)據(jù)源的Schema也需要獲取到。為后續(xù)數(shù)據(jù)處理作為輸入信息。
技術(shù)上來(lái)說(shuō),平臺(tái)中會(huì)存在與各種存儲(chǔ)設(shè)施交互的代碼,大量的外部依賴。此時(shí),外部依賴可能會(huì)影響到平臺(tái)本身的性能和可用性,比如Hive的不可用、訪問(wèn)緩慢等,這個(gè)是需要注意的。
業(yè)務(wù)上來(lái)說(shuō),更多考量的是提高系統(tǒng)的易用性,舉個(gè)例子,創(chuàng)建Hive表數(shù)據(jù)源,是不是可以支持自動(dòng)識(shí)別分區(qū),選擇分區(qū)又或者是動(dòng)態(tài)分區(qū)(支持變量)等。
04.數(shù)據(jù)處理
這里的數(shù)據(jù)處理是一個(gè)大的概念,從我的認(rèn)知上來(lái)看。大體可以分成兩個(gè)部分, 數(shù)據(jù)標(biāo)注以及特征處理。
數(shù)據(jù)標(biāo)注
數(shù)據(jù)標(biāo)注針對(duì)是的監(jiān)督學(xué)習(xí)任務(wù),目前機(jī)器學(xué)習(xí)的應(yīng)用場(chǎng)景大多都是應(yīng)用監(jiān)督學(xué)習(xí)任務(wù)習(xí)得的。巧婦難為無(wú)米之炊,沒(méi)有足夠的標(biāo)注數(shù)據(jù),算法的發(fā)揮也不會(huì)好到哪兒去。對(duì)于標(biāo)注這塊。業(yè)務(wù)功能上來(lái)說(shuō),基本上可以當(dāng)成是另一套系統(tǒng)了,我們可以把它叫做標(biāo)注平臺(tái)。但從邏輯關(guān)系上來(lái)說(shuō),標(biāo)注數(shù)據(jù)是為了機(jī)器學(xué)習(xí)服務(wù)的。本質(zhì)上也是對(duì)數(shù)據(jù)的處理,所以劃到機(jī)器學(xué)習(xí)平臺(tái)里面也沒(méi)有什么問(wèn)題。
標(biāo)注平臺(tái)對(duì)應(yīng)了之前提到平臺(tái)的另一功能:提供通用的流程規(guī)范。這里,流程指的是整個(gè)標(biāo)注流程,規(guī)范指的是標(biāo)注數(shù)據(jù)存儲(chǔ)的規(guī)范,比如在圖像領(lǐng)域,目前沒(méi)有通用而且規(guī)范的存儲(chǔ)格式,比較需要平臺(tái)來(lái)提供一種通用的存儲(chǔ)格式。
數(shù)據(jù)標(biāo)注有兩種,一種是人工標(biāo)注; 另一種是使用已訓(xùn)練好的機(jī)器學(xué)習(xí)模型來(lái)標(biāo)注,然后再輔以人工確定和修訂。無(wú)論是使用哪種方式,最后都需要人工介入。因?yàn)閿?shù)據(jù)標(biāo)注的正確性是非常重要的,大家應(yīng)該都聽(tīng)過(guò)一句話: 數(shù)據(jù)和特征決定了機(jī)器學(xué)習(xí)的上限,而模型和算法只是逼近這個(gè)上限而已。 如果給你的數(shù)據(jù)都是有問(wèn)題的,那模型如何能學(xué)習(xí)到正確的能力呢。
在標(biāo)注平臺(tái)中,往往都是人工+模型混合使用的,整體流程如下:
在標(biāo)注平臺(tái)中,人工+模型混合使用
在最開(kāi)始可能沒(méi)有模型來(lái)輔助進(jìn)行標(biāo)注(這里的預(yù)標(biāo)注),這個(gè)時(shí)候就需要人為手工介入,以此來(lái)訓(xùn)練出一個(gè)模型
當(dāng)我們根據(jù)標(biāo)注出的數(shù)據(jù)(訓(xùn)練數(shù)據(jù)集)訓(xùn)練出不錯(cuò)的模型之后,就可以使用此模型來(lái)對(duì)新輸入的數(shù)據(jù)做一個(gè)預(yù)標(biāo)注的工作,然后再輔以人工確認(rèn)和修訂
如此反復(fù)迭代,隨著輸入數(shù)據(jù)的增多,當(dāng)我們訓(xùn)練出的模型準(zhǔn)確率達(dá)到一個(gè)很高的水準(zhǔn)之后,需要人工操作的數(shù)據(jù)就會(huì)越來(lái)越少。以此減少人工成本費(fèi)
標(biāo)注平臺(tái)中需要考量的問(wèn)題有幾點(diǎn):
一般來(lái)說(shuō),需要標(biāo)注的數(shù)據(jù)量都是非常巨大的。不存在說(shuō)兩三個(gè)人隨便標(biāo)幾下就完事。所以更為通用的做法是做一個(gè)眾包平臺(tái),外包給其他公司或者自由職業(yè)者(標(biāo)注員)來(lái)做。參考AWS的Amazon Mechanical Turk。這就涉及到了權(quán)限控制、角色控制。
標(biāo)注數(shù)據(jù)的準(zhǔn)確性問(wèn)題。不能避免有些標(biāo)注員劃水摸魚(yú),隨意標(biāo)注。此時(shí)是需要己方人員去做一個(gè)審計(jì)工作的,這里就是一個(gè)工作流,和上圖所示差不多。是一個(gè)相對(duì)來(lái)說(shuō)較為規(guī)范的流程,可以隨著業(yè)務(wù)來(lái)增加額外的流程。
標(biāo)注工具的開(kāi)發(fā)。如果有合適開(kāi)源工具,可以集成開(kāi)源工具,如VGG-VIA/Vatic, poplar。開(kāi)源工具一般不會(huì)滿足所有的需求,在開(kāi)源上做二次開(kāi)發(fā)往往成本更高。這里更傾向于自己開(kāi)發(fā),這樣更能滿足需要,自定義程度高,靈活性強(qiáng)
標(biāo)注數(shù)據(jù)的存儲(chǔ)。最好是一個(gè)相對(duì)通用的格式,以便于往各種其他格式做一個(gè)轉(zhuǎn)換。在使用時(shí)做一個(gè)數(shù)據(jù)格式轉(zhuǎn)換。這里更偏好Json格式類似的存儲(chǔ),可讀性和代碼可操作性都非常高
技術(shù)上的考量,這里并不是太多。唯一需要注意的可能是數(shù)據(jù)的處理,如圖片、視頻標(biāo)注,資源的拆剪、縮放,各種標(biāo)注數(shù)據(jù)的保存,坐標(biāo)計(jì)算等。相對(duì)而言,后端主要是工作流處理,前端的各種標(biāo)注工具是技術(shù)核心點(diǎn)。
特征處理
在正式開(kāi)始模型構(gòu)建與訓(xùn)練之前,對(duì)數(shù)據(jù)做特征處理基本上是必不可少的環(huán)節(jié)。特征處理的輸入是之前創(chuàng)建的數(shù)據(jù)集、或者是標(biāo)注完成后產(chǎn)生的數(shù)據(jù)集。它的輸出是經(jīng)過(guò)一系列數(shù)據(jù)操作后、可以直接輸入到模型中的數(shù)據(jù),這里稱它為訓(xùn)練數(shù)據(jù)。
這里又可以分為兩類,一類是不需要太多操作的特征處理,常見(jiàn)于非結(jié)構(gòu)化數(shù)據(jù),如圖片、視屏。另一類是針對(duì)結(jié)構(gòu)化/半結(jié)構(gòu)化數(shù)據(jù)的特征處理流程,這類數(shù)據(jù)往往不是拿來(lái)即可用的,需要一定的特征處理。
首先來(lái)看第一類,第一類的典型應(yīng)用場(chǎng)景就是CNN圖像領(lǐng)域。對(duì)于輸入的圖片,一般不需要太多的操作。此類數(shù)據(jù)源往往也是存儲(chǔ)在NFS/OSS上的。對(duì)于此類數(shù)據(jù)的處理,一般也不會(huì)使用到大數(shù)據(jù)框架,一般都是自己手?jǐn)]Python(C++)來(lái)處理;或者是放在模型訓(xùn)練一起處理,不單獨(dú)拎開(kāi)。Spark2.3開(kāi)始是支持圖片格式的,不過(guò)目前沒(méi)有看到太多的使用案例。整體流程如下:
CNN圖像領(lǐng)域
本質(zhì)上是一個(gè)批處理過(guò)程,Kubernetes的Job天然適用于此類問(wèn)題。當(dāng)然其他調(diào)度框架來(lái)做這個(gè)任務(wù)調(diào)度也是可以的。
然后是第二類,這種基本上就是傳統(tǒng)的特征工程了,以Hive/HDFS輸入為經(jīng)典例子。由于對(duì)數(shù)據(jù)的操作是非常多樣的,所以一般傾向于構(gòu)建一個(gè)數(shù)據(jù)處理的流水線,也就是Pipeline:
傳統(tǒng)的特征工程
把對(duì)數(shù)據(jù)的操作拆分成一個(gè)一個(gè)的操作運(yùn)算(也就是一個(gè)Pipeline Node節(jié)點(diǎn)),可以把它叫做算子,然后利用Pipeline把操作進(jìn)行自由組合,從而達(dá)到對(duì)數(shù)據(jù)進(jìn)行各種變換處理的過(guò)程。使用過(guò)Sklearn pipeline或者Spark MLlib pipeline的小伙伴應(yīng)該對(duì)此并不陌生,事實(shí)上,這就是基于此的可視化建模。使得用戶可以在界面上進(jìn)行拖拉拽,選擇和輸入一些參數(shù)來(lái)完成對(duì)于數(shù)據(jù)的操作,提供更靈活的功能。
那么這條Pipeline里面都有哪些操作呢,整個(gè)算子大致可以分為這幾類別:
特征處理
技術(shù)上,使用Spark MLlib是個(gè)不錯(cuò)的選擇,可以適應(yīng)不同數(shù)據(jù)量的規(guī)模。且天然支持這種Pipeline的形式,只需要對(duì)此做一定的封裝。同時(shí),考慮到業(yè)務(wù)功能,還需要手動(dòng)定制、修改一些算子;對(duì)于擴(kuò)展這點(diǎn),它的支持也是非常不錯(cuò)的,自定義算子、算法都比較簡(jiǎn)單。當(dāng)然也可以基于其他框架(如Azkaban)或者自己造輪子。需要注意的是,在大數(shù)據(jù)場(chǎng)景下,Spark MLlib里面部分自帶的算子會(huì)有性能問(wèn)題(有些直接OOM),需要分析源碼定位然后修復(fù)。包括我們自己實(shí)現(xiàn)的算子,也都要考量大數(shù)據(jù)場(chǎng)景下這個(gè)問(wèn)題,這對(duì)于測(cè)試而言是個(gè)Case。
整個(gè)Pipeline的核心是構(gòu)造一個(gè)DAG,解析后,提交給對(duì)應(yīng)的框架來(lái)做處理。拋開(kāi)技術(shù)來(lái)說(shuō),功能上來(lái)說(shuō),易用性和快速反饋是Pipeline需要注意的。比如:
所有的算子都應(yīng)該能自動(dòng)獲取到可用的輸入、對(duì)應(yīng)類型,自動(dòng)生成輸出
支持參數(shù)校驗(yàn),Pipeline完整性校驗(yàn)
支持調(diào)試/快速模式,利用部分Sample data快速驗(yàn)證效果,相當(dāng)于一個(gè)試驗(yàn)功能
日志查看,每個(gè)算子狀態(tài)查看,以及操作完成后的Sample data查看
支持一些變量、SQL書(shū)寫(xiě),以擴(kuò)展更靈活的功能,比如參數(shù)動(dòng)態(tài)化
支持定時(shí)調(diào)度,任務(wù)狀態(tài)郵件、短袖及時(shí)告警、同步等
05.模型訓(xùn)練
到了模型訓(xùn)練這塊。從功能上來(lái)看需要的不是很多,更多是體驗(yàn)上的設(shè)計(jì)。比如參數(shù)在界面上的展示和使用,日志、訓(xùn)練出的Metrics的可視化、交互方式,模型的一些可視化等。核心功能包含這幾塊兒:
1.預(yù)置算法/模型
這里考量的點(diǎn)是:
支持界面手動(dòng)調(diào)參
訓(xùn)練中日志、Metrics的可視化。支持同時(shí)使用不同的參數(shù)多次訓(xùn)練,直觀對(duì)比結(jié)果方便調(diào)參
需要支持常用的框架,如Spark MLlib/Tensorflow/Pytorch,或者一些特定的框架(業(yè)務(wù)方需要的)
預(yù)置算法/模型很簡(jiǎn)單,在不同的框架上封裝一層并且暴露對(duì)應(yīng)的參數(shù)給到用戶即可。有些算法可能框架不支持,這種根據(jù)情況決定如何解決(自己實(shí)現(xiàn)或者其他解決方案)。有一點(diǎn)就是,框架不宜太多,否則在后續(xù)模型發(fā)布的Serving上,也需要多套解決方案。對(duì)于訓(xùn)練本身來(lái)說(shuō),分為兩種:?jiǎn)误w/單機(jī)訓(xùn)練和分布式訓(xùn)練,分布式訓(xùn)練是訓(xùn)練這塊的大頭(也是技術(shù)難點(diǎn)所在)。
對(duì)于單體/單機(jī)訓(xùn)練的解決方案,和上訴特征處理中的解決方案一致。優(yōu)先使用Kubernetes的Job,或者使用Spark,控制下Executor即可。
對(duì)于分布式訓(xùn)練,目前接觸到的,基本上都是數(shù)據(jù)并行:
分布式機(jī)器學(xué)習(xí)
以Spark為基礎(chǔ)的基本都使用的是PS模式。PS模式一般使用的都是異步更新參數(shù),每個(gè)Worker只需要和PS通信,所以容錯(cuò)管理上會(huì)更加簡(jiǎn)單。AllReduce模式則是同步的參數(shù)模式,而且每個(gè)Worker都需要上下游通信,相對(duì)而言,容錯(cuò)處理會(huì)更苛刻一些。
Spark系的分布式訓(xùn)練,經(jīng)典的算法可以由Spark MLlib提供。但是其對(duì)于DNN的支持并不好,而且Spark的訓(xùn)練是一個(gè)同步的過(guò)程,如果數(shù)據(jù)傾斜的話,整個(gè)訓(xùn)練的速度取決于最慢的RDD。如果要在Spark上跑深度學(xué)習(xí)的模型,一般會(huì)選用其他框架或者基于Spark的框架,如騰訊的Angel、 Intel的BigDL。兩者的思想都是一致的,同屬于PS模式下的分布式訓(xùn)練,整個(gè)流程可以概括為這幾步:
利用Spark來(lái)作為任務(wù)調(diào)度、資源分配、數(shù)據(jù)讀取和容錯(cuò)處理的容器
從PS拉取參數(shù),然后將數(shù)據(jù)和參數(shù)通過(guò)JNI喂到底層的框架代碼中去(如Pytorch C++ Frontend)完成訓(xùn)練,返回梯度
使用優(yōu)化算法和梯度,更新參數(shù),再將新的參數(shù)更新到PS。如此反復(fù)
借用一張Angel的圖:
Angel的圖
順著這個(gè)思路,可以以Spark為基礎(chǔ),兼容任何深度學(xué)習(xí)框架。只要底層框架:
支持模型/代碼序列化,以支持分發(fā)模型到所有Worker中進(jìn)行本地訓(xùn)練
通過(guò)JNI能調(diào)用模型提供的接口,如Forward/Backward
這要比自己造輪子更加便利和友好,畢竟Spark已經(jīng)是一個(gè)成熟的分布式計(jì)算框架了。
如果使用的是Python系的深度學(xué)習(xí)框架有兩點(diǎn)需要注意:
如何讀取分布式存儲(chǔ)上的數(shù)據(jù)以支持?jǐn)?shù)據(jù)并行。也就是Spark里面Partition的概念。當(dāng)然最簡(jiǎn)單的方法,就是將數(shù)據(jù)拆分成塊,不同的節(jié)點(diǎn)讀取不同的數(shù)據(jù)來(lái)訓(xùn)練。
另外一點(diǎn)在于容錯(cuò)性,基于Spark的分布式訓(xùn)練的優(yōu)勢(shì)就在于數(shù)據(jù)的分配、容錯(cuò)處理?,F(xiàn)在就得自己去保障這兩點(diǎn)了。
訓(xùn)練部署上面。Spark系的,使用Spark支持的即可(Yarn/Kubernetes/Standalone)。Python系的更傾向于云原生、或者基于Kubernetes的解決方案(自定義Operator是個(gè)比較好的選擇),這里有個(gè)為云原生和容器化而生的框架:Polyaxon,值得一試。
2. 自定義算法
關(guān)于自定義算法,個(gè)人更傾向于將這個(gè)功能放在Notebook中而不是界面化的操作上,因?yàn)檫@個(gè)功能的自由度很高,允許用戶自己寫(xiě)代碼。平臺(tái)其實(shí)只需要提供:
數(shù)據(jù)讀取能力,這里包括源數(shù)據(jù)、平臺(tái)內(nèi)生成的數(shù)據(jù)
NFS/OSS使用Mount形式或者API提供(如Databricks 的DBFS)
HDFS系列的API提供支持(如提供pyspark)
調(diào)度能力,能根據(jù)需求調(diào)度起任務(wù)。
以上兩者功能,都或多或少依賴于SDK/API/CLI??梢詤⒖即髲S的實(shí)現(xiàn)Amazon SageMaker、Databricks Notebooks。
另外一點(diǎn)是GPU的支持,這點(diǎn),如果是選擇Kubernetes作為基礎(chǔ)設(shè)施,是有基本的功能支持的,利用Extended Resource(ER)配合 Device plugin體系:
Extended Resource(ER)配合 Device plugin體系
對(duì)于Hadoop體系的話,3.1.X之后也是支持的。
這兩者對(duì)于GPU的支持都非常有限,都是處于一個(gè)能用,但是不好用的狀態(tài)。使用的時(shí)候,淌坑可能在所難免。
3. AutoML
關(guān)于AutoML這塊。目前還沒(méi)有太多的接觸。從我看來(lái),做個(gè)簡(jiǎn)單的隨機(jī)搜索還是問(wèn)題不大的,集成算法來(lái)自動(dòng)調(diào)參、自動(dòng)構(gòu)建模型也是不難的。就跟上訴集成算法進(jìn)來(lái)是一樣的。唯一考量的是,集成那些算法進(jìn)來(lái)以及計(jì)算資源的考量,尤其是深度學(xué)習(xí)大行其道的今天,類似于隨機(jī)搜索這樣耗費(fèi)的資源是巨大的。如何設(shè)計(jì)這個(gè)功能,以及具體實(shí)現(xiàn)還是需要非常專業(yè)的領(lǐng)域知識(shí)。
總的來(lái)說(shuō),模型訓(xùn)練這塊。是一個(gè)很偏技術(shù)的功能。完成一個(gè)Demo的端到端,實(shí)現(xiàn)基本的功能很簡(jiǎn)單。但是要做到好用、穩(wěn)定性這兩點(diǎn)就并不那么容易。尤其是分布式機(jī)器學(xué)習(xí)這一塊兒,還是需要不斷淌坑的。
06.模型發(fā)布
終于來(lái)到最后一步,是整個(gè)平臺(tái)產(chǎn)生價(jià)值的最后一環(huán)。模型發(fā)布,通常包含兩種發(fā)布:
發(fā)布成API(RESTful/gRPC),以供業(yè)務(wù)側(cè)實(shí)時(shí)調(diào)用。這類服務(wù)通常對(duì)于性能要求苛刻
發(fā)布成批處理形式,用于批處理數(shù)據(jù),上述標(biāo)注平臺(tái)中的預(yù)標(biāo)注屬于此類任務(wù)
對(duì)于批處理形式的發(fā)布,較為簡(jiǎn)單。一般框架本身都支持模型的序列化和加載做預(yù)測(cè):
Spark系的就依舊走原始路線,提交Spark Job,做批處理預(yù)測(cè)
TensorFlow類似的,配合不同的鏡像環(huán)境,Mount模型,讀取數(shù)據(jù),配合Kubernetes Job的方式來(lái)啟動(dòng)批處理達(dá)到一個(gè)統(tǒng)一的處理流程
對(duì)于實(shí)時(shí)推理服務(wù),于平臺(tái)而言,能使用通用的框架/技術(shù)來(lái)做那當(dāng)然是極好的。然鵝,現(xiàn)實(shí)很殘酷。通用的解決方案,要么性能不夠(如MLeap),要么支持的算子/操作/輸入有限(如ONNX。想要在真正的業(yè)務(wù)場(chǎng)景下發(fā)揮價(jià)值都是需要淌坑的。用的更多的,往往都是性能領(lǐng)域強(qiáng)悍的C/C++/RUST來(lái)實(shí)現(xiàn),比如自研、或者框架本身自帶的(如TensorFlow的Serving),會(huì)更能滿足性能需求。平臺(tái)選用的框架最好是不要太多,這樣做Serving會(huì)比較麻煩,不同的框架都要去找解決方案實(shí)現(xiàn)一遍。
雖然做不到通用的模型Serving方案,但是通用的模型發(fā)布、提供服務(wù)的平臺(tái)卻是可以做到的。這是這部分的重點(diǎn),即如何設(shè)計(jì)一個(gè)通用的推理平臺(tái)。一個(gè)推理平臺(tái)需要考量的點(diǎn)如下所示:
支持各種框架,多語(yǔ)言、多環(huán)境
模型版本管理
API安全性
可用性、可擴(kuò)展性,服務(wù)狀態(tài)監(jiān)控、動(dòng)態(tài)擴(kuò)容
監(jiān)控、告警,日志可視化
灰度上線/AB Testing
把Serving看做是普通的Web服務(wù)。對(duì)于上訴的點(diǎn),Kubernetes體系是絕佳的選擇:
鏡像,配合NFS的模型,啟動(dòng)時(shí)Mount再?gòu)?fù)制到容器內(nèi)部??梢灾С侄嗾Z(yǔ)言、多環(huán)境
版本管理,每個(gè)版本在NFS上創(chuàng)建新的版本目錄,比如0.0.1,放入對(duì)應(yīng)的模型和啟動(dòng)腳本配合一個(gè)Service。這樣就允許不同版本的Service同時(shí)在線,或者部分在線
API安全性,與Kubernetes本身無(wú)關(guān)。簡(jiǎn)單的做法是為每個(gè)API生成對(duì)應(yīng)的調(diào)用Token來(lái)做鑒權(quán),或者使用API網(wǎng)關(guān)來(lái)做
可用性、可擴(kuò)展性。利用Kubernetes原生的Liveness/Readness probe,可以檢測(cè)單個(gè)Pod中服務(wù)的狀態(tài)。使用Kubernetes的HPA、或者自己實(shí)現(xiàn)監(jiān)控再配合Autoscale可以滿足需求,而且這些都可以成為一些配置暴露給用戶
監(jiān)控、告警??梢訮rometheus+Grafana+Alertmanager三件套,或者配合企業(yè)內(nèi)部的運(yùn)維體系
交給Istio即可?;叶劝l(fā)布肯定妥妥的,利用一些Cookie/Header來(lái)做分流到不同版本的服務(wù)也可以做到部分AB Testing的事情
由于Serving服務(wù)與服務(wù)之間是沒(méi)有關(guān)系的,是一個(gè)無(wú)狀態(tài)的單體服務(wù)。對(duì)于單體服務(wù)的各種處理就會(huì)比較簡(jiǎn)單。比如不使用Kubernetes,使用AWS云的EC2來(lái)部署,配合Auto Scaling、CloudWatch等也是非常簡(jiǎn)單的。
07. Addons
除開(kāi)上訴的核心功能。一般來(lái)說(shuō),機(jī)器學(xué)習(xí)平臺(tái)還有一些擴(kuò)展。最經(jīng)典的當(dāng)屬CLI和SDK了。
CLI就不用多說(shuō)了,主要提供快捷入口。可以參考AWS的CLI。需要包含的點(diǎn)主要是:
提供基本的操作功能,滿足用戶的使用
以及導(dǎo)入導(dǎo)出功能。方便用戶共享配置、快速創(chuàng)建和使用平臺(tái)的功能
支持多環(huán)境、認(rèn)證
完善的操作使用文檔、幫助命令、模板文件等
對(duì)于SDK這塊,需要和平臺(tái)本身的功能做深度集成;同時(shí),還需要一定的靈活性。比如上訴的自定義算法,用戶可以在Notebook里面讀取平臺(tái)生成的數(shù)據(jù)集,寫(xiě)完代碼后,還得支持提交分布式訓(xùn)練。既要集成平臺(tái)功能,又得支持一定程度的自定義,如何設(shè)計(jì)會(huì)是一個(gè)難點(diǎn)。
08.探索實(shí)驗(yàn)(Notebook)
Notebook本身功能并不復(fù)雜。實(shí)質(zhì)上就是對(duì)Jupyter Notebook/JupyterLab等的包裝。通常的做法是使用Kubernetes的Service,啟動(dòng)一個(gè)Notebook。以下幾點(diǎn)是需要考量的:
存儲(chǔ)要能持久化,需要引入類似于NFS這樣的持久目錄以供用戶使用
內(nèi)置Demo,如讀取平臺(tái)數(shù)據(jù)、訪問(wèn)資源、提交任務(wù)
預(yù)置不同的鏡像,支持不同的框架,以及CPU/GPU訴求用于啟動(dòng)不同的Notebook
安全問(wèn)題,一個(gè)是Notebook本身的安全。另一個(gè)是容器本身的安全
有可用的安全源,以供用戶安裝和下載一些包和數(shù)據(jù)
能夠訪問(wèn)到基礎(chǔ)設(shè)施里面的數(shù)據(jù),Mount/API
最好能有Checkpoint機(jī)制,不用的時(shí)候回收資源。需要的時(shí)候再啟動(dòng),但環(huán)境不變
大致的解決思路如下:
持久化需要Mount存儲(chǔ)。Storage class可以幫助
Notebook自身的安全,可以在里面增加Handler或者外面配置一層Proxy來(lái)鑒權(quán)。容器的安全大概有這幾點(diǎn)需要考量(要做到更嚴(yán)格還有很多可以深挖):
限制容器內(nèi)部用戶的權(quán)限
開(kāi)啟SELinux
Docker的—cap-add/—cap-drop
heckpoint機(jī)制的實(shí)現(xiàn),數(shù)據(jù)已經(jīng)持久化在外部存儲(chǔ)了。只需要Save新的鏡像,作為下次啟動(dòng)的鏡像即可,可使用Daemonset+Docker in dokcer的形式做一個(gè)微服務(wù)來(lái)提交鏡像。
09. 平臺(tái)的基石
這一節(jié)主要討論的是做平臺(tái)一定繞不開(kāi)的問(wèn)題。首先逃脫不了的是多租戶問(wèn)題:
可能要和已有的系統(tǒng)進(jìn)行集成。而不是新開(kāi)發(fā)
租戶間權(quán)限、數(shù)據(jù)隔離
租戶資源配額、任務(wù)優(yōu)先級(jí)劃分
技術(shù)上來(lái)說(shuō),系統(tǒng)自身的租戶功能難度不高。主要是數(shù)據(jù)、資源隔離這塊。要看對(duì)應(yīng)的基礎(chǔ)設(shè)施:
Hadoop可以使用Keberos
Kubernetes可以使用Namespace
再配合不同的調(diào)度隊(duì)列。即可完成需求。
另外一點(diǎn)是偏技術(shù)層面的調(diào)度功能。這可以算是整個(gè)平臺(tái)運(yùn)行的基礎(chǔ),無(wú)論是數(shù)據(jù)處理還是模型訓(xùn)練、模型部署都依賴于此, 調(diào)度系統(tǒng)分為兩塊:
調(diào)度本身,即如何調(diào)度不同的任務(wù)到不同的基礎(chǔ)設(shè)施上
狀態(tài)管理,有些任務(wù)可能存在依賴關(guān)系,會(huì)觸發(fā)不同的Action。這也是一個(gè)狀態(tài)機(jī)的問(wèn)題
狀態(tài)管理這塊,業(yè)務(wù)場(chǎng)景不復(fù)雜的情況下自己實(shí)現(xiàn)即可。一般平臺(tái)上也沒(méi)有太復(fù)雜的依賴關(guān)系,經(jīng)典的模型訓(xùn)練也不過(guò)單向鏈路而已。如果過(guò)于復(fù)雜,可以考慮其他開(kāi)源任務(wù)編排工具:
狀態(tài)管理
調(diào)度本身是一個(gè)任務(wù)隊(duì)列+任務(wù)調(diào)度組合而成。隊(duì)列用啥都可以,數(shù)據(jù)庫(kù)也可以。只要能保證多個(gè)Consumer的數(shù)據(jù)一致性即可。任務(wù)調(diào)度,如果不考慮用戶的感受,可以直接丟給對(duì)應(yīng)的基礎(chǔ)設(shè)施,如Yarn/Kubernetes都可以。由這些基礎(chǔ)設(shè)施來(lái)負(fù)責(zé)調(diào)度和管理,這樣最簡(jiǎn)單。
如果想做的盡善盡美,那還是需要維護(hù)一個(gè)資源池。同步基礎(chǔ)設(shè)施的使用情況,然后根據(jù)剩余資源和任務(wù)優(yōu)先級(jí)來(lái)做調(diào)度。
狀態(tài)更新方面。對(duì)于Yarn體系,只能通過(guò)API去輪詢狀態(tài)、獲取日志。
對(duì)于Kubernetes體系,推薦一個(gè)Informer機(jī)制,通過(guò)List&Watch機(jī)制可以方便、快速獲取整個(gè)集群的情況:
Custom Controller
關(guān)于如何提交任務(wù)到基礎(chǔ)設(shè)施:
Spark/Yarn - 直接API、包裝下命令行者Livy都可
Kubernetes - SDK
10.最終Boss
做平臺(tái),最怕的是什么?當(dāng)然不是某某技術(shù)太過(guò)于復(fù)雜,攻克不下。而是沒(méi)有用戶使用平臺(tái),或者不能通過(guò)平臺(tái)產(chǎn)生真實(shí)業(yè)務(wù)價(jià)值,這才是最重要的。有某一業(yè)務(wù)場(chǎng)景在平臺(tái)實(shí)現(xiàn)端到端產(chǎn)生價(jià)值,才能證明這個(gè)平臺(tái)的價(jià)值,才能吸引其他用戶來(lái)使用。
對(duì)于用戶來(lái)說(shuō),一般都已經(jīng)有自己成熟的技術(shù)線。想要他們往平臺(tái)上遷移,實(shí)屬不易,除非已有系統(tǒng)滿足不了他們的需求、或者已有系統(tǒng)不好用。畢竟,自己用的好好的系統(tǒng),遷移是需要耗時(shí)耗力的,用別人的東西也沒(méi)有自己做來(lái)的靈活;學(xué)習(xí)一個(gè)新的系統(tǒng)使用也是如此,有可能一開(kāi)始用著并不習(xí)慣。此外,新的系統(tǒng),沒(méi)有人期望第一個(gè)來(lái)當(dāng)小白鼠的。有這么多缺點(diǎn),當(dāng)然平臺(tái)本身也有其優(yōu)點(diǎn)。比如將基礎(chǔ)設(shè)施這塊甩給了第三方,不用去關(guān)注底層的東西,只要關(guān)注自己的業(yè)務(wù)了。
事實(shí)上的流程往往都是,隨著平臺(tái)MVP的發(fā)布。部分用戶開(kāi)始上來(lái)試用,然后提各種想法和需求;緊接著,會(huì)逐漸遷移部分功能上來(lái)試用,比如搞些數(shù)據(jù)上來(lái)跑跑Demo,看看訓(xùn)練的情況等。同時(shí),在這個(gè)階段,就會(huì)需要各種適配用戶原始的系統(tǒng)了,比如原始數(shù)據(jù)導(dǎo)入與現(xiàn)有系統(tǒng)不兼容,需要格式的轉(zhuǎn)換;再比如只想用平臺(tái)的部分功能,想集成到自己現(xiàn)有的系統(tǒng)中等。最后才是,真正的在平臺(tái)上使用。想要用戶能端到端的使用平臺(tái),來(lái)完成他們的業(yè)務(wù)需求,還是需要漫長(zhǎng)的過(guò)程的。
相對(duì)而言,至上而下的推動(dòng)往往更為有效。總有一批人要先來(lái)體驗(yàn)、先來(lái)淌坑,給出建議和反饋。這樣這個(gè)平臺(tái)才會(huì)越來(lái)越好,朝好的地方發(fā)展。而不是一開(kāi)始上來(lái)就堆功能,什么炫酷搞什么、大而全。但是在用戶使用上,易用性和穩(wěn)定性并不好,或者是并不能解決用戶的需求和難點(diǎn)。那這種平臺(tái)是活不下去的。
fqj
-
數(shù)據(jù)庫(kù)
+關(guān)注
關(guān)注
7文章
3752瀏覽量
64234 -
機(jī)器學(xué)習(xí)
+關(guān)注
關(guān)注
66文章
8353瀏覽量
132315
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論