深度學(xué)習(xí)模型部署的那些事兒

當(dāng)我們千辛萬苦完成了前面的數(shù)據(jù)獲取、數(shù)據(jù)清洗枪蘑、模型訓(xùn)練损谦、模型評(píng)估等等步驟之后,終于等到老大說“上線”啦腥寇。想到辛苦訓(xùn)練出來的模型要被調(diào)用還有點(diǎn)小激動(dòng)呢成翩,可是真當(dāng)下手的時(shí)候就有點(diǎn)懵了:模型要怎么部署?部署在哪里赦役?有什么限制或要求麻敌?

本文基于以上常見的部署困惑,介紹一下深度學(xué)習(xí)中TensorFlow(Keras)模型部署時(shí)需要考慮的問題以及常用部署方法掂摔,并通過實(shí)際的模型部署來進(jìn)行方案比較术羔。

問題分析

筆者較為推薦的思考路徑是從問題和限制出發(fā)赢赊,思考好了這些限制條件之后再去搜索對(duì)應(yīng)的解決方案,這樣就可以避免限于方案過多挑不過來的窘境级历,并且若是挑不到完美的方案释移,還可以根據(jù)條件對(duì)現(xiàn)有方案進(jìn)行改造。

現(xiàn)在就來看看部署模型我們通常需要考慮什么問題寥殖。

首先是模型的使用場(chǎng)景玩讳,根據(jù)使用場(chǎng)景就可以獲取到對(duì)應(yīng)的性能等要求。舉個(gè)例子來說嚼贡,如果是要上線給用戶使用的熏纯,哦吼,恭喜你粤策,這塊最起碼速度要求就很高樟澜,畢竟用戶可不像自己人,沒有多少耐心一直等你的加載圈轉(zhuǎn)呀轉(zhuǎn)叮盘,具體的指標(biāo)根據(jù)場(chǎng)景和應(yīng)用而定秩贰,不過一般會(huì)在數(shù)毫秒 最多可以到數(shù)十毫秒每條的樣子。此外柔吼,如果是基于網(wǎng)絡(luò)調(diào)用那還好說毒费,機(jī)器在自己手上,土豪就可以各顯神通了嚷堡,如果是離線的手機(jī)APP蝗罗,那就還有大小的要求,畢竟動(dòng)不動(dòng)讓你下個(gè)幾百M(fèi)的app看著也煩呀蝌戒。

接下來串塑,如果是基于網(wǎng)絡(luò)調(diào)用的,還要看看自己手里的資源夠不夠北苟,是壕到有專門的GPU用于部署呢桩匪,還是只能苦逼地使用CPU呢,如果是GPU部署友鼻,那可以偷笑了傻昙,GPU部署服務(wù)方便的同時(shí)性能又好,畢竟各種各樣的優(yōu)化都是苦于資源不夠彩扔,對(duì)于大伙兒來說可以躺賺誰愿意坐著賺錢啊妆档。

好吧,CPU就CPU虫碉,然而CPU服務(wù)器里頭也是可以區(qū)別的贾惦,是選擇有裝好例如python、TensorFlow等環(huán)境的呢,還是赤條條的要么自己裝要么另尋出路的须板。

方案介紹

接下來碰镜,本文會(huì)根據(jù)幾種常見的限制組合來列出對(duì)應(yīng)的解決方案,需要部署到手機(jī)端的話TensorFlow已經(jīng)給出了TensorFlow Lite的解決方案习瑰,筆者暫未接觸到手機(jī)部署相關(guān)的需求绪颖,就不深入介紹了。接下來就以最常見的服務(wù)提供方部署模型甜奄,通過網(wǎng)絡(luò)調(diào)用方式通信介紹兩套方案柠横。

基于預(yù)測(cè)改造的方案

模型在測(cè)試集上進(jìn)行測(cè)試知道吧?讀取文件后調(diào)用模型對(duì)每條case進(jìn)行預(yù)測(cè)贺嫂,最后將所有預(yù)測(cè)結(jié)果和正確答案對(duì)比滓鸠,計(jì)算出各種指標(biāo)。整個(gè)流程如下圖:

而在提供服務(wù)時(shí)第喳,輸入是由外部傳入的,因此不需要前面的讀取文件操作踱稍,最后提供預(yù)測(cè)結(jié)果即可曲饱,也不需要最后的對(duì)比、計(jì)算指標(biāo)的步驟珠月。為了處理接收外部輸入扩淀、返回預(yù)測(cè)結(jié)果,并做一些業(yè)務(wù)邏輯相關(guān)的處理啤挎,需要引入一個(gè)處理中心驻谆,這個(gè)處理中心通常是web框架 如 flask、tornado庆聘、Django等胜臊,其作用是搭建http服務(wù),將外部輸入傳給模型伙判,將模型預(yù)測(cè)結(jié)果返回象对。流程如下圖:

model1.png

再來梳理一下流程,在同一臺(tái)機(jī)器上通過web框架如flask等搭建好對(duì)外服務(wù)宴抚,初始化時(shí)加載好模型勒魔。當(dāng)外部應(yīng)用服務(wù)例如搜索應(yīng)用的輸入到來時(shí),例如傳來一句話菇曲,或者上傳了一張圖片冠绢,對(duì)外服務(wù)就將輸入傳給預(yù)處理函數(shù),將輸入處理成可以給模型預(yù)測(cè)的樣子常潮,例如做標(biāo)準(zhǔn)化弟胀、去噪等等,隨后模型進(jìn)行預(yù)測(cè),并將結(jié)果返回給對(duì)外服務(wù)邮利,服務(wù)將結(jié)果包裝一下返回給搜索應(yīng)用回去弥雹。

一個(gè)搜索應(yīng)用會(huì)有很多個(gè)模型和子模塊構(gòu)成,那么對(duì)于每個(gè)模型都需要有一個(gè)對(duì)外服務(wù)來對(duì)模型進(jìn)行封裝并提供通信接口延届。

整個(gè)過程并沒有多少難點(diǎn)剪勿,搭建http服務(wù)使用簡(jiǎn)單的demo即可,然后將預(yù)測(cè)函數(shù)改造改造就可以啦方庭,最終的性能視乎部署的設(shè)備及模型深度而定厕吉。

基于TF-Serving的方案

如果在要部署的服務(wù)器上不愿或無法裝和訓(xùn)練一樣的環(huán)境,也可以使用TensorFlow推出的Serving工具械念,此處對(duì)小白來說更推薦基于docker的安裝方式头朱,只需要安好對(duì)應(yīng)鏡像即可,否則得自己編譯安裝龄减∠钆ィ基于docker安裝的話需要提前想好是用cpu版本還是gpu版,根據(jù)版本拉取對(duì)應(yīng)的鏡像希停。

那這個(gè)TF-Serving是什么樣的呢烁巫?先來看看基于TF-Serving后最終整個(gè)流程是怎么工作的:

model3.png

如圖,在TF-Serving流程上一般會(huì)用到兩臺(tái)機(jī)器(或更多)宠能,其中一臺(tái)作為TF-Serving的服務(wù)器亚隙,專門給模型用來部署并預(yù)測(cè),應(yīng)用服務(wù)放在另外的服務(wù)器违崇,跟其他服務(wù)共享環(huán)境阿弃。

我們將模型部署在TF-Serving的服務(wù)器上,TF-Serving會(huì)自動(dòng)根據(jù)傳入的端口和模型路徑進(jìn)行部署羞延,模型所在的服務(wù)器不需要python環(huán)境(以python訓(xùn)練為例)渣淳,隨后應(yīng)用服務(wù)直接對(duì)模型所在服務(wù)器發(fā)起服務(wù)調(diào)用,調(diào)用可以通過java或python的grpc進(jìn)行調(diào)用肴楷,具體調(diào)用方式參考當(dāng)前使用版本的手冊(cè)水由。

不過TF-Serving一個(gè)很大的坑在于:數(shù)據(jù)預(yù)處理的部分需要交給應(yīng)用服務(wù)做,TF-Serving只接收張量輸入赛蔫,如文本分類的模型砂客,它就只接收序列的id,而非句子本身呵恢,并且輸出返回的是id而非文本化的標(biāo)簽鞠值,因此也需要額外一層轉(zhuǎn)換。

然后來看看怎么將模型部署到TF-Serving上:

model2.png

流程比較簡(jiǎn)單渗钉,首先在GPU服務(wù)器上訓(xùn)練好模型后彤恶,將模型保存好钞钙,再根據(jù)網(wǎng)上的轉(zhuǎn)換腳本轉(zhuǎn)換成TF-Serving接受的格式,不論使用Tensorflow還是Keras都不影響(pytorch麻煩出門右轉(zhuǎn))声离,只是保存的函數(shù)不同而已芒炼,查好具體用哪個(gè)函數(shù)即可,最后將生成出來的文件上傳到安裝了TF-Serving的服務(wù)器术徊,啟動(dòng)服務(wù)即可本刽。

方案對(duì)比

接下來本文先以一個(gè)實(shí)際的BERT-base+Fasttext文本二分類模型為例子,分別用以上兩個(gè)方案用GPU和CPU進(jìn)行部署赠涮,看看他們性能之間的差異子寓,最后在總結(jié)一下不同方案的適用場(chǎng)景和差異。

部署性能對(duì)比

GPU 基于 模型預(yù)測(cè)改造方案

首先上GPU:

tesla.png

Tesla V100 訓(xùn)練起來很給力笋除,那么預(yù)測(cè)起來時(shí)間怎么樣呢斜友?筆者以1500個(gè)句子作為輸入,在服務(wù)器上搭建好http服務(wù)后遠(yuǎn)程調(diào)用垃它,最終平均時(shí)間是0.0102s/條鲜屏,10毫秒每條,對(duì)于大多數(shù)線上使用來說算是還可以了国拇,畢竟BERT的體積之大和推理之慢但效果之好是大家有目共睹的墙歪。

CPU 基于 模型預(yù)測(cè)改造方案

那么把這個(gè)模型移到CPU上又會(huì)怎么樣呢?在Intel(R) Xeon(R) Gold 61xx CPU 2*32 上采用同樣的改造和服務(wù)搭建方式贝奇,同樣的1.5k句子跑起來,最終平均時(shí)間是0.390s/條靠胜。

看到這個(gè)結(jié)果掉瞳,筆者一開始瞪大了眼睛,仔細(xì)確認(rèn)了好幾遍數(shù)量級(jí)浪漠,最終無可奈何的接受了這個(gè)現(xiàn)實(shí)陕习,390ms/條的速度,拿給內(nèi)部自己人調(diào)用都要嫌慢吧址愿。然后回頭去某東上搜了下V100该镣,好吧。响谓。人家快是有道理的损合。

tesla0.png

CPU 基于 TF-Serving 方案

那TensorFlow官方強(qiáng)推的Serving工具表現(xiàn)怎么樣呢?或許經(jīng)過推理優(yōu)化之后運(yùn)行速度或許會(huì)快一些吧娘纷?實(shí)驗(yàn)結(jié)果也證實(shí)了這個(gè)假設(shè)嫁审,cpu版本的TF-Serving平均耗時(shí)為0.292 s/條, 比直接調(diào)用足足快了100ms赖晶,看來強(qiáng)推還是有道理的律适。

部署優(yōu)化

雖然知道業(yè)界對(duì)BERT推理過慢廣泛詬病,但在GPU和CPU下差距如此之大還是有些出乎意料。吃驚歸吃驚捂贿,還得看看有沒有優(yōu)化的方法纠修。如果我們把CPU下耗時(shí)極大的BERT放到GPU會(huì)怎么樣?將原始的BERT作為服務(wù)放到GPU上厂僧,這樣平時(shí)訓(xùn)練和線上預(yù)測(cè)取embedding都從這里取扣草,這樣我們只需要部署接在BERT后面的小模型即可,哪怕是用CPU也扛得住吧吁系?雖然會(huì)犧牲微調(diào)BERT帶來的提升德召,但是畢竟可以上線呀,比因性能太差而放棄要好多了汽纤。

在GPU上部署B(yǎng)ERT服務(wù)上岗,這里就要用到筆者非常喜歡的 bert-as-service了,它是python的一個(gè)bert庫蕴坪,能夠讓bert作為服務(wù)肴掷,接收句子輸入返回bert編碼的句子向量。

部署之后測(cè)試一下性能背传,不使用batch的單條預(yù)測(cè)下平均耗時(shí)是0.0073s/條呆瞻,7ms,可以接受径玖。那分離開來的fasttext模型呢痴脾?部署在CPU的TF-Serving后平均耗時(shí)是0.0028s/條,3ms梳星,也可以接受赞赖,總耗時(shí)竟然跟整個(gè)模型放在GPU上是一樣的,瓶頸果然還是在BERT呀冤灾。

這套方案同樣可以遷移到其他場(chǎng)景前域,例如將用戶的各種信息訓(xùn)練好Embedding后作為公共資源由模型各自調(diào)用,或者可以將耗內(nèi)存較大的word2vec embedding文件放到有較多內(nèi)存的機(jī)器上韵吨,再通過網(wǎng)絡(luò)進(jìn)行數(shù)據(jù)傳輸匿垄。

方案總結(jié)

現(xiàn)在來總結(jié)一下上邊的實(shí)驗(yàn),先看一下以上三種方案的流程圖(每個(gè)黑色框代表一臺(tái)機(jī)器):

plan0.png

然后來看一下方案分別的耗時(shí):

plan1.png

首先要說的是归粉,能上GPU一定要上GPU椿疗!鈔能力節(jié)省非常多的時(shí)間和精力。然后我們挨個(gè)方案來說說優(yōu)缺點(diǎn)盏浇。

第一套方案就是簡(jiǎn)單地將測(cè)試模式改造成連續(xù)預(yù)測(cè)模式变丧,通過web框架進(jìn)行轉(zhuǎn)發(fā)和包裝。

好處:修改簡(jiǎn)單易于上手绢掰。

壞處:

  1. 推理性能為三種方案之內(nèi)最慢的痒蓬。

  2. 推理服務(wù)器需要有python環(huán)境童擎。

第二套方案利用TF-Serving進(jìn)行部署,TF-Serving自動(dòng)會(huì)進(jìn)行部署和端口監(jiān)聽攻晒。

好處:

  1. 速度較方案一快顾复。

  2. 不需要python環(huán)境。

壞處:

  1. 安裝較麻煩鲁捏,最好使用docker芯砸。

  2. 輸入輸出都需要轉(zhuǎn)換和處理。

第三套方案是在方案二上的優(yōu)化给梅,將耗費(fèi)資源較多的部分放到性能較好的機(jī)器上假丧,可以作為公共資源給多個(gè)小網(wǎng)絡(luò)共同使用。

好處(其他同方案二):

  1. 速度最快动羽。

壞處(其他同方案二):

  1. 需要有性能好的機(jī)器存放耗資源的網(wǎng)絡(luò)包帚,這塊需要協(xié)調(diào)。

  2. 多一次網(wǎng)絡(luò)通信运吓,需要承受網(wǎng)絡(luò)波動(dòng)的影響渴邦,如果TF-Serving和GPU機(jī)器屬于不同網(wǎng)絡(luò)環(huán)境則更為麻煩,需要借助VPN等手段拘哨。

  3. 每個(gè)對(duì)外服務(wù)調(diào)用模型需要配置專門的邏輯:從GPU服務(wù)器取Embedding谋梭,作為輸入給TF-Serving,才能得到TF-Serving的輸出倦青。

縱觀所有方案瓮床,發(fā)現(xiàn)其實(shí)我們可以做一些小融合,以方案三(或方案二)為基礎(chǔ)产镐,結(jié)合方案一的包裝纤垂,來去除TF-Serving輸入輸出需要轉(zhuǎn)換,以及方案三中每個(gè)服務(wù)需要配置專門邏輯的缺點(diǎn)磷账,流程如下圖:

plan1.png

以方案三為例,在TF-Serving的服務(wù)器上再增加一層中介贾虽,主要做輸入輸出的轉(zhuǎn)換逃糟,再承擔(dān)中轉(zhuǎn)的作用。

當(dāng)外部輸入到來時(shí)蓬豁,對(duì)外服務(wù)接收請(qǐng)求绰咽,處理后傳給GPU機(jī)器,得到embedding地粪,而后將embedding傳給TF-Serving的模型取募,得到預(yù)測(cè)結(jié)果后轉(zhuǎn)換成外部需要的格式,最后打包結(jié)果返回給其他服務(wù)蟆技。

這樣玩敏,方案四既擁有了方案三速度最快的優(yōu)點(diǎn)斗忌,也避免了TF-Serving需要做輸出輸出轉(zhuǎn)換,以及在TF-Serving與GPU Embedding服務(wù)器中來回跑的缺點(diǎn)旺聚。

最后

本文列舉了基于網(wǎng)絡(luò)調(diào)用的幾個(gè)模型部署的方案织阳,并且根據(jù)實(shí)際場(chǎng)景進(jìn)行優(yōu)化和變型,如果要在此之上要追求極致的性能砰粹,就只能自己動(dòng)手豐衣足食了唧躲,例如用C++或Go重寫推理部分,或者利用大公司自研的框架進(jìn)行部署和推理碱璃。

想看更多實(shí)戰(zhàn)文章弄痹,歡迎關(guān)注微信公眾號(hào)【AI實(shí)戰(zhàn)派】

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市嵌器,隨后出現(xiàn)的幾起案子肛真,更是在濱河造成了極大的恐慌,老刑警劉巖嘴秸,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件毁欣,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡岳掐,警方通過查閱死者的電腦和手機(jī)凭疮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來串述,“玉大人执解,你說我怎么就攤上這事「傩铮” “怎么了衰腌?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)觅赊。 經(jīng)常有香客問我右蕊,道長(zhǎng),這世上最難降的妖魔是什么吮螺? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任饶囚,我火速辦了婚禮,結(jié)果婚禮上鸠补,老公的妹妹穿的比我還像新娘萝风。我一直安慰自己,他們只是感情好紫岩,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布规惰。 她就那樣靜靜地躺著,像睡著了一般泉蝌。 火紅的嫁衣襯著肌膚如雪歇万。 梳的紋絲不亂的頭發(fā)上揩晴,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音堕花,去河邊找鬼文狱。 笑死,一個(gè)胖子當(dāng)著我的面吹牛缘挽,可吹牛的內(nèi)容都是我干的瞄崇。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼壕曼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼苏研!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起腮郊,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤摹蘑,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后轧飞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體衅鹿,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年过咬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了大渤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡掸绞,死狀恐怖泵三,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情衔掸,我是刑警寧澤烫幕,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站敞映,受9級(jí)特大地震影響较曼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜振愿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一诗芜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧埃疫,春花似錦、人聲如沸孩哑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽横蜒。三九已至胳蛮,卻和暖如春销凑,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背仅炊。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工斗幼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人抚垄。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓蜕窿,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親呆馁。 傳聞我的和親對(duì)象是個(gè)殘疾皇子桐经,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容