談?wù)剻C(jī)器學(xué)習(xí)模型的部署

隨著機(jī)器學(xué)習(xí)的廣泛應(yīng)用,如何高效的把訓(xùn)練好的機(jī)器學(xué)習(xí)的模型部署到生產(chǎn)環(huán)境,正在被越來越多的工具所支持。我們今天就來看一看不同的工具是如何解決這個問題的。

上圖的過程是一個數(shù)據(jù)科學(xué)項目所要經(jīng)歷的典型的過程。從數(shù)據(jù)采集開始,經(jīng)歷數(shù)據(jù)分析,數(shù)據(jù)變形,數(shù)據(jù)驗(yàn)證,數(shù)據(jù)拆分,訓(xùn)練,模型創(chuàng)建,模型驗(yàn)證,大規(guī)模訓(xùn)練,模型發(fā)布,到提供服務(wù),監(jiān)控和日志。諸多的機(jī)器學(xué)習(xí)工具如Scikt-Learn,Spark, Tensorflow, MXnet, PyTorch提供給數(shù)據(jù)科學(xué)家們不同的選擇,同時也給模型的部署帶來了不同的挑戰(zhàn)。

我們先來簡單的看一看機(jī)器學(xué)習(xí)的模型是如何部署,它又會遇到那些挑戰(zhàn)。

模型持久化

模型部署一般就是把訓(xùn)練的模型持久化,然后運(yùn)行服務(wù)器加載模型,并提供REST或其它形式的服務(wù)接口。我們以RandomForestClassification為例,看一下Sklearn,Spark和Tensorflow是如何持久化模型。

Sklearn

我們使用Iris數(shù)據(jù)集,利用RandomForestClassifier分類。


訓(xùn)練的代碼如上。這里模型導(dǎo)出的代碼在最后一句。joblib.dump(),參考這里。Sklearn的模型到處本質(zhì)上是利用Python的Pickle機(jī)制。Python的函數(shù)進(jìn)行序列化,也就是說把訓(xùn)練好的Transformer函數(shù)序列化并存為文件。

要加載模型也很簡單,只要調(diào)用joblib.load()就好了。

Sklearn對Pickle做了一下封裝和優(yōu)化,但這并不能解決Pickle本身的一些限制,例如:

版本兼容問題,不同的Python,Pickle,Sklearn的版本,生成的序列化文件并不兼容

安全性問題,例如序列化的文件中被人注入惡意代碼

擴(kuò)展問題,你自己寫了一個擴(kuò)展類,無法序列化,或者你在Python中調(diào)用了C函數(shù)

模型的管理,如果我生成了不同版本的模型,該如何管理

Spark

Spark的Pipeline和Model都支持Save到文件,然后可以很方便的在另一個Context中加載。

訓(xùn)練的代碼如下:

模型加載的代碼如下:

調(diào)用model的toDebugString方法可以看到分類器的內(nèi)部細(xì)節(jié)。


下圖是Spark存儲的Piple模型的目錄結(jié)構(gòu):

我們可以看到,它包含了元數(shù)據(jù)Pipeline的五個階段的數(shù)據(jù),這里的文件都是二進(jìn)制的數(shù)據(jù),只有Spark自己可以加載。

Tensorflow

最后我們來看一下Tensorflow。Tensorflow提供了tf.train.Saver來導(dǎo)出他的模型到元圖(MetaGraph)。

導(dǎo)出的模型會包含以下文件:

其中checkpoint是元數(shù)據(jù),包含其它文件的路徑信息。還包含了一個Pickle文件和其它幾個checkpiont文件??梢钥闯?,Tensorflow也利用了Python的Pickle機(jī)制來存儲模型,并在這之外加入了額外的元數(shù)據(jù)。

模型加載的代碼如下:

這里要注意的是,RandomForest不是tensforflow的核心包,所以在模型加載的時候必須tensorflow.contrib.tensor_forest.python.tensor_forest, 否則模型是無法成功加載的。因?yàn)椴患虞d的話tensor_forest中定義的一些屬性會缺失。

另外就是Tensorflow也可以存儲計算圖,調(diào)用tf.train.write_graph()方法可以把圖定義存儲下來。當(dāng)然也可以在TesnsorBoard中展示該圖。

好了,我們看到,Sklearn,Spark和Tensorflow都提供了自己的模型持久化的方法,那么簡單來說,只要使用一個web服務(wù)器例如Flask,加一些模型加載和管理的方法,然后暴露REST API就可以提供預(yù)測服務(wù)了,是不是很簡單呢?

其實(shí)要在生產(chǎn)環(huán)境下提供服務(wù),還需要面對很多其它的挑戰(zhàn),例如:

在云上如何擴(kuò)展和伸縮

如何進(jìn)行性能調(diào)優(yōu)

如何管理模型的版本

安全性

如何持續(xù)集成和持續(xù)部署

如何支持AB測試

為了解決模型部署的挑戰(zhàn),不同的組織開發(fā)了一些開源的工具,例如:Clipper,SeldonMFlowMLeap,Oracle GraphpipeMXnet model server?等等,我們就選其中幾個看個究竟。

Clipper

Clipper是由UC BerkeleyRISE Lab開發(fā)的, 在用戶應(yīng)用和機(jī)器學(xué)習(xí)模型之間的一個提供預(yù)測服務(wù)的系統(tǒng),通過解耦合用戶應(yīng)用和機(jī)器學(xué)習(xí)系統(tǒng)的方式,簡化部署流程。

它有以下功能:

利用簡單標(biāo)準(zhǔn)化的REST接口來簡化機(jī)器學(xué)習(xí)系統(tǒng)的集成,支持主要的機(jī)器學(xué)習(xí)框架。

使用開發(fā)模型相同的庫和環(huán)境簡化模型部署

利用可適配的Batching,緩存等技術(shù)改善吞吐量

通過智能選擇和合并模型來改善預(yù)測的準(zhǔn)確率

Clipper的架構(gòu)如下圖:

Clipper使用了容器和微服務(wù)技術(shù)來構(gòu)架架構(gòu)。使用Redis來管理配置,Prometheus來進(jìn)行監(jiān)控。Clipper支持使用Kubernetes或者本地的Docker來管理容器。

Clipper支持以下幾種模型:

純Python函數(shù)

PyShark

PyTorch

Tensorflow

MXnet

自定義

Clipper模型部署的基本過程如下,大家可以參考我的這個notebook

創(chuàng)建Clipper集群(使用K8s或者本地Docker)

創(chuàng)建一個應(yīng)用

訓(xùn)練模型

調(diào)用Clipper提供的模型部署方法部署模型,這里不同的工具需要調(diào)用不同的部署方法。部署時,會把訓(xùn)練好的Estimator利用CloudPickle之久化,本地構(gòu)建一個容器鏡像,部署到Docker或者K8s。

把模型和應(yīng)用關(guān)聯(lián)到一起,相當(dāng)于發(fā)布模型。然后就可以調(diào)用對應(yīng)的REST API來做預(yù)測了。

我試著把之前的三種工具的RomdomForest的例子用Clipper發(fā)布到我的Kubernetes集群,踩到了以下的坑坑:

我本地的Cloudpickle的版本太新,導(dǎo)致模型不能反序列化,參考這個Issue

Tensorflow在Pickle的時候失敗,應(yīng)該是調(diào)用了C的code

我的K8s運(yùn)行在AWS上,我在K8S上使用內(nèi)部IP失敗,clipper連接一直在使用外部的域名,導(dǎo)致無法部署PySpark的模型。

總之,除了Sklearn成功部署之外,Tensorflow和Spark都失敗了。

Seldon

Seldon是一家創(chuàng)辦于倫敦的公司,致力于提供對于基于開源軟件的機(jī)器學(xué)習(xí)系統(tǒng)的控制。Seldon Core是該公司開源的提供在Kubernetes上部署機(jī)器學(xué)習(xí)模型的工具。它擁有以下功能:

Python/Spark/H2O/R 的模型支持

REST API和gRPC接口

部署基于Model/Routers/Combiner/Transformers的圖的微服務(wù)

利用K8S來提供擴(kuò)展,安全性,監(jiān)控等等DevOps的功能

Seldon的使用過程如上圖,

首先在K8s上安裝Seldon Core,Seldon利用ksonnet,以CRD的形式安裝seldon core

利用S2i(s2i是openshift開源的一款工具,用于把代碼構(gòu)建成容器鏡像),構(gòu)建運(yùn)行時模型容器,并注冊到容器注冊表

編寫你的運(yùn)行圖,并提交到K8s來部署你的模型

Seldon支持基于四種基本單元,Model,Transformer, Router, Combiner來構(gòu)建你的運(yùn)行圖,并按照該圖在K8s創(chuàng)建對應(yīng)的資源和實(shí)例,來獲得AB測試,模型ensemble的功能。

例如下圖的幾個例子:

AB 測試

模型ensemble

復(fù)雜圖

圖模式是Seldon最大的亮點(diǎn),可以訓(xùn)練不同的模型,然后利用圖來組合出不同的運(yùn)行時,非常方便。

筆者嘗試在K8S上利用Seldon部署之前提到的三種工具生成的模型,都獲得了成功(代碼在這里)。這里分享一下遇到的幾個問題:

Seldon支持Java的Python,然而用運(yùn)行PySpark,這兩個都需要,所以我不得不自己構(gòu)建了一個鏡像,手工在Python鏡像上安裝Java

因?yàn)槭褂肅DR的原因,我沒有找到有效改變?nèi)萜鞯膌iveness和readiness的設(shè)置,因?yàn)镾park初始化模型在Hadoop上,加載模型需要時間,總是readiness超時導(dǎo)致容器無法正常啟動,K8s不斷的重啟容器。所以我只好修改代碼,讓模型加載變成Lazy Load,但是這樣第一次REST Call會比較耗時,但是容器和服務(wù)總算是能夠正常啟動。

MLflow

MLflow是Databricks開發(fā)的開源系統(tǒng),用于管理機(jī)器學(xué)習(xí)的端到端的生命周期。

MLflow提供跟蹤,項目管理和模型管理的功能。使用MLFlow來提供一個基于Sklearn的模型服務(wù)非常簡單,

調(diào)用mlflow.sklearn.log_model(), MLflow創(chuàng)建以下的目錄來管理模型:

我們看到在artifacts目錄下有Python的pickle文件和另一個元數(shù)據(jù)文件,MLModel。

使用 mlflow sklearn serve -m model 就可以很方便的提供基于sklearn的模型服務(wù)了。

雖然MLFlow也號稱支持Spark和Tensorflow,但是他們都是基于Python來做,我嘗試使用,但是文檔和例子比較少,所以沒能成功。但原理上都是使用Pickle?元數(shù)據(jù)的方式。大家有興趣的可以嘗試一下。

關(guān)于部署功能,MLFlow的一個亮點(diǎn)是和Sagemaker,AzureML的支持。

MLeap

MLeap的目標(biāo)是提供一個在Spark和Sklearn之間可移植的模型格式,和運(yùn)行引擎。它包含:

????基于JSON的序列化

????運(yùn)行引擎

????Benchmark

MLeap的架構(gòu)如下圖:

這是一個使用MLeap導(dǎo)出Sklearn模型的例子:

導(dǎo)出的模型結(jié)構(gòu)如下圖所示:

這個是randonforest的模型json

我們可以看出MLeap把模型完全序列化成與代碼無關(guān)的JSON文件,這樣就可以在不同的運(yùn)行時工具Spark/Sklearn之間做到可移植。

MLeap對模型提供服務(wù),不需要依賴任何Sklearn或者Spark的代碼。只要啟動MLeap的Server,然后提交模型就好了。

下面的代碼用Scala在Spark 上訓(xùn)練一個同樣的Randonforest分類模型,并利用MLeap持久化模型。

導(dǎo)出的模型和之前的Sklearn具有相同的格式。

MLeap的問題在于要支持所有的算法,對于每一個算法都要實(shí)現(xiàn)對應(yīng)的序列化,這也使得它的需要很多的開發(fā)來支持客戶自定義的算法

總結(jié)

Seldon Core和K8S結(jié)合的很好,它提供的運(yùn)行圖的方式非常強(qiáng)大,它也是我實(shí)驗(yàn)中唯一一個能夠成功部署Sklearn,Spark和Tensorflow三種模型的工具,非常推薦!

Clipper提供基于K8s和Docker的模型部署,它的模型版本管理做得不錯,但是代碼不太穩(wěn)定,小問題不少,基于CloudPickle也有不少的限制,只能支持Python也是個問題。推薦給數(shù)據(jù)科學(xué)家有比較多的本地交互的情況。

MLFlow能夠提供很方便的基于Python的模型服務(wù),但是缺乏和容器的結(jié)合。但是它能夠支持和Sagemaker,AzureML等云的支持。推薦給已經(jīng)在使用這些云的玩家。

MLeap的特色是支持模型的可交互性,也就是說我可以把sklearn訓(xùn)練的模型導(dǎo)出在Spark上運(yùn)行,這的功能很有吸引力,但是要支持全部的算法,它還有很長的路要走。關(guān)于機(jī)器學(xué)習(xí)模型標(biāo)準(zhǔn)化的問題,大家也可以關(guān)注PMML?,F(xiàn)階段各個工具對PMML的支持比較有限,隨著深度學(xué)習(xí)的廣泛應(yīng)用,PMML何去何從還未可知。

下表是對以上幾個工具的簡單總結(jié),供大家參考

?Model PersistentML ToolsKubernetest IntegrationVersionLicenseImplementation

Seldon CoreS2i + PickleTensorflow, SKlearn, Keras, R, H2O, Nodejs, PMMLYes0.3.2ApacheDocker + K8s CRD

ClipperPicklePython, PySpark, PyTorch, Tensorflow, MXnet, Customer ContainerYes0.3.0ApacheCPP / Python

MLFlowDirectory + MetadataPython, H2O, Kera, MLeap, PyTorch, Sklearn, Spark, Tensorflow, RNoAlphaApachePython

MLeap?JSONSpark,Sklearn, TensorflowNo0.12.0ApacheScala/Java

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容