03.06 「工程」深度學習模型部署的那些事兒

來源 | AI實戰派

作者 | AI實戰派

「工程」深度學習模型部署的那些事兒

AI實戰派

和你一起看看AI真實落地的樣子


當我們千辛萬苦完成了前面的數據獲取、數據清洗、模型訓練、模型評估等等步驟之後,終於等到老大說“上線”啦。想到辛苦訓練出來的模型要被調用還有點小激動呢,可是真當下手的時候就有點懵了:模型要怎麼部署?部署在哪裡?有什麼限制或要求?


本文基於以上常見的部署困惑,介紹一下深度學習中TensorFlow(Keras)模型部署時需要考慮的問題以及常用部署方法,並通過實際的模型部署來進行方案比較。


01

問題分析

筆者較為推薦的思考路徑是從問題和限制

出發,思考好了這些限制條件之後再去搜索對應的解決方案,這樣就可以避免限於方案過多挑不過來的窘境,並且若是挑不到完美的方案,還可以根據條件對現有方案進行改造。

現在就來看看部署模型我們通常需要考慮什麼問題。

首先是模型的使用場景,根據使用場景就可以獲取到對應的性能等要求。舉個例子來說,如果是要上線給用戶使用的,哦吼,這塊最起碼速度要求就很高,畢竟用戶可不像自己人,沒有多少耐心一直等你的加載圈轉呀轉,具體的指標根據場景和應用而定,不過一般會在數毫秒 最多可以到數十毫秒每條的樣子。

此外,如果是基於網絡調用那還好說,機器在自己手上,土豪就可以各顯神通了,如果是離線的手機APP,那就還有大小的要求,畢竟動不動讓你下個幾百M的app看著也煩呀。

接下來,如果是基於網絡調用的,還要看看自己手裡的資源夠不夠,是壕到有專門的GPU用於部署呢,還是隻能苦逼地使用CPU呢,如果是GPU部署,那可以偷笑了,GPU部署服務方便的同時性能又好,畢竟各種各樣的優化都是苦於資源不夠,對於大夥兒來說可以躺賺誰願意坐著賺錢啊。

好吧,CPU就CPU,然而CPU服務器裡頭也是可以區別的,是選擇有裝好例如Python、TensorFlow等環境的呢,還是赤條條的要麼自己裝要麼另尋出路的。


02

方案介紹


接下來,本文會根據幾種常見的限制組合來列出對應的解決方案,需要部署到手機端的話TensorFlow已經給出了TensorFlow Lite的解決方案,筆者暫未接觸到手機部署相關的需求,就不深入介紹了。接下來就以最常見的服務提供方部署模型,通過網絡調用方式通信介紹兩套方案。

基於預測改造的方案

模型在測試集上進行測試知道吧?讀取文件後調用模型對每條case進行預測,最後將所有預測結果和正確答案對比,計算出各種指標。整個流程如下圖:

「工程」深度學習模型部署的那些事兒


而在提供服務時,輸入是由外部傳入的,因此不需要前面的讀取文件操作,最後提供預測結果即可,也不需要最後的對比、計算指標的步驟。為了處理接收外部輸入、返回預測結果,並做一些業務邏輯相關的處理,需要引入一個處理中心,這個處理中心通常是web框架 如 flask、tornado、Django等,其作用是搭建http服務,將外部輸入傳給模型,將模型預測結果返回。流程如下圖:

「工程」深度學習模型部署的那些事兒

再來梳理一下流程,在同一臺機器上通過web框架如flask等搭建好對外服務,初始化時加載好模型。當外部應用服務例如搜索應用的輸入到來時,例如傳來一句話,或者上傳了一張圖片,對外服務就將輸入傳給預處理函數,將輸入處理成可以給模型預測的樣子,例如做標準化、去噪等等,隨後模型進行預測,並將結果返回給對外服務,服務將結果包裝一下返回給搜索應用回去。

一個搜索應用會有很多個模型和子模塊構成,那麼對於每個模型都需要有一個對外服務來對模型進行封裝並提供通信接口。

整個過程並沒有多少難點,搭建http服務使用簡單的demo即可,然後將預測函數改造改造就可以啦,最終的性能視乎部署的設備及模型深度而定。

基於TF-Serving的方案

如果在要部署的服務器上不願或無法裝和訓練一樣的環境,也可以使用TensorFlow推出的Serving工具,此處對小白來說更推薦基於docker的安裝方式,只需要安好對應鏡像即可,否則得自己編譯安裝。基於docker安裝的話需要提前想好是用cpu版本還是gpu版,根據版本拉取對應的鏡像。

那這個TF-Serving是什麼樣的呢?先來看看基於TF-Serving後最終整個流程是怎麼工作的:

「工程」深度學習模型部署的那些事兒

如圖,在TF-Serving流程上一般會用到兩臺機器(或更多),其中一臺作為TF-Serving的服務器,專門給模型用來部署並預測,應用服務放在另外的服務器,跟其他服務共享環境。

我們將模型部署在TF-Serving的服務器上,TF-Serving會自動根據傳入的端口和模型路徑進行部署,模型所在的服務器不需要python環境(以python訓練為例),隨後應用服務直接對模型所在服務器發起服務調用,調用可以通過java或python的grpc進行調用,具體調用方式參考當前使用版本的手冊。

不過TF-Serving一個很大的坑在於:數據預處理的部分需要交給應用服務做,TF-Serving只接收張量輸入,如文本分類的模型,它就只接收序列的id,而非句子本身,並且輸出返回的是id而非文本化的標籤,因此也需要額外一層轉換。

然後來看看怎麼將模型部署到TF-Serving上:

「工程」深度學習模型部署的那些事兒

流程比較簡單,首先在GPU服務器上訓練好模型後,將模型保存好,再根據網上的轉換腳本轉換成TF-Serving接受的格式,不論使用Tensorflow還是Keras都不影響(pytorch麻煩出門右轉),只是保存的函數不同而已,查好具體用哪個函數即可,最後將生成出來的文件上傳到安裝了TF-Serving的服務器,啟動服務即可。


03

方案對比


接下來本文先以一個實際的BERT-base+Fasttext文本二分類模型為例子,分別用以上兩個方案用GPU和CPU進行部署,看看他們性能之間的差異,最後在總結一下不同方案的適用場景和差異。

部署性能對比

GPU 基於 模型預測改造方案

首先上GPU:

「工程」深度學習模型部署的那些事兒

Tesla V100 訓練起來很給力,那麼預測起來時間怎麼樣呢?筆者以1500個句子作為輸入,在服務器上搭建好http服務後遠程調用,最終平均時間是0.0102s/條,10毫秒每條,對於大多數線上使用來說算是還可以了,畢竟BERT的體積之大和推理之慢但效果之好是大家有目共睹的。

CPU 基於 模型預測改造方案

那麼把這個模型移到CPU上又會怎麼樣呢?在Intel(R) Xeon(R) Gold 61xx CPU 2*32 上採用同樣的改造和服務搭建方式,同樣的1.5k句子跑起來,最終平均時間是0.390s/條。

看到這個結果,筆者一開始瞪大了眼睛,仔細確認了好幾遍數量級,最終無可奈何的接受了這個現實,390ms/條的速度,拿給內部自己人調用都要嫌慢吧。然後回頭去某東上搜了下V100,好吧。。人家快是有道理的。

「工程」深度學習模型部署的那些事兒

CPU 基於 TF-Serving 方案

那TensorFlow官方強推的Serving工具表現怎麼樣呢?或許經過推理優化之後運行速度或許會快一些吧?實驗結果也證實了這個假設,cpu版本的TF-Serving平均耗時為0.292 s/條, 比直接調用足足快了100ms,看來強推還是有道理的。

部署優化

雖然知道業界對BERT推理過慢廣泛詬病,但在GPU和CPU下差距如此之大還是有些出乎意料。吃驚歸吃驚,還得看看有沒有優化的方法。如果我們把CPU下耗時極大的BERT放到GPU會怎麼樣?將原始的BERT作為服務放到GPU上,這樣平時訓練和線上預測取embedding都從這裡取,這樣我們只需要部署接在BERT後面的小模型即可,哪怕是用CPU也扛得住吧?雖然會犧牲微調BERT帶來的提升,但是畢竟可以上線呀,比因性能太差而放棄要好多了。

在GPU上部署BERT服務,這裡就要用到筆者非常喜歡的 bert-as-service了,它是python的一個bert庫,能夠讓bert作為服務,接收句子輸入返回bert編碼的句子向量。

部署之後測試一下性能,不使用batch的單條預測下平均耗時是0.0073s/條,7ms,可以接受。那分離開來的fasttext模型呢?部署在CPU的TF-Serving後平均耗時是0.0028s/條,3ms,也可以接受,總耗時竟然跟整個模型放在GPU上是一樣的,瓶頸果然還是在BERT呀。

這套方案同樣可以遷移到其他場景,例如將用戶的各種信息訓練好Embedding後作為公共資源由模型各自調用,或者可以將耗內存較大的word2vec embedding文件放到有較多內存的機器上,再通過網絡進行數據傳輸。


04

方案總結


現在來總結一下上邊的實驗,先看一下以上三種方案的流程圖(每個黑色框代表一臺機器):

「工程」深度學習模型部署的那些事兒

然後來看一下方案分別的耗時:

「工程」深度學習模型部署的那些事兒

首先要說的是,能上GPU一定要上GPU!鈔能力節省非常多的時間和精力。然後我們挨個方案來說說優缺點。

第一套方案就是簡單地將測試模式改造成連續預測模式,通過web框架進行轉發和包裝。

好處:修改簡單易於上手。

壞處:

  1. 推理性能為三種方案之內最慢的。
  2. 推理服務器需要有python環境。

第二套方案利用TF-Serving進行部署,TF-Serving自動會進行部署和端口監聽。

好處:

  1. 速度較方案一快。
  2. 不需要python環境。

壞處:

  1. 安裝較麻煩,最好使用docker。
  2. 輸入輸出都需要轉換和處理。

第三套方案是在方案二上的優化,將耗費資源較多的部分放到性能較好的機器上,可以作為公共資源給多個小網絡共同使用。

好處(其他同方案二):

  1. 速度最快。

壞處(其他同方案二):

  1. 需要有性能好的機器存放耗資源的網絡,這塊需要協調。
  2. 多一次網絡通信,需要承受網絡波動的影響,如果TF-Serving和GPU機器屬於不同網絡環境則更為麻煩,需要藉助VPN等手段。
  3. 每個對外服務調用模型需要配置專門的邏輯:從GPU服務器取Embedding,作為輸入給TF-Serving,才能得到TF-Serving的輸出。

縱觀所有方案,發現其實我們可以做一些小融合,以方案三(或方案二)為基礎,結合方案一的包裝,來去除TF-Serving輸入輸出需要轉換,以及方案三中每個服務需要配置專門邏輯的缺點,流程如下圖:

「工程」深度學習模型部署的那些事兒

以方案三為例,在TF-Serving的服務器上再增加一層中介,主要做輸入輸出的轉換,再承擔中轉的作用。

當外部輸入到來時,對外服務接收請求,處理後傳給GPU機器,得到embedding,而後將embedding傳給TF-Serving的模型,得到預測結果後轉換成外部需要的格式,最後打包結果返回給其他服務。

這樣,方案四既擁有了方案三速度最快的優點,也避免了TF-Serving需要做輸出輸出轉換,以及在TF-Serving與GPU Embedding服務器中來回跑的缺點。


05

最後


本文列舉了基於網絡調用的幾個模型部署的方案,並且根據實際場景進行優化和變型,如果要在此之上要追求極致的性能,就只能自己動手豐衣足食了,例如用C++或Go重寫推理部分,或者利用大公司自研的框架進行部署和推理。


The End


分享到:


相關文章: