手把手教你如何部署深度學習模型
摘要: 本文將講解如何部署深度學習模型,讓你不再對如何快速地將機器學習模型部署到生產中感到困擾
我剛剛訓練了機器學習模型——那麼現在呢?
這篇文章介紹了一種快速的方法,將經過訓練的機器學習模型部署到生產中。
請閱讀以下內容:如果您已經成功地使用諸如Tensorflow或Caffe這樣的ML框架來培訓ML模型,那麼您最好先做一個演示,最好早一點而不是晚一點,而且您更喜歡更便捷的解決方案,而不是將整個技術堆疊都打包。
閱讀時間:10-15分鐘
TL;DR:檢查報告
檢查您的tensorflow安裝
從stdin執行線上分類
在本地主機上執行線上分類
將分類器放在硬編碼代理之後
將分類器置於具有服務發現的代理之後
使用偽DNS呼叫分類器
ML在生產中
當我們第一次進入Hive的機器學習空間時,我們已經擁有了數百萬個標記為影象的地面實況,這使得我們可以在一個星期內訓練一個最先進的深度卷積影象分類模型(即隨機權重),專門用於我們的用例。 然而,更典型的ML使用案例通常是數百幅影象的數量級,為此我建議微調現有的模型。例如,https://www.tensorflow.org/tutorials/image_retraining有一個很好的教程關於如何微調Imagenet模型(訓練1.2圖片,1000類)來對花卉樣本資料(3647圖片,5類)進行分類。
對於連線Tensorflow教程的快速tl;dr,在安裝bazel和tensorflow之後,您需要執行以下程式碼,這需要大約30分鐘的時間來搭建和5分鐘的時間來訓練:
或者,如果您安裝了Docker,則可以使用以下預構建的Docker映象:
在容器內的互動式shell中執行上述命令;如果您願意,您也可以跟著這個文章的其他部分在容器內操作。
現在,tensorflow已經將模型資訊儲存到/tmp/output_graph.pb和/tmp/output_labels.txt中,這些作為命令列引數傳遞給label_image.py指令碼。 Google的image_recognition教程也連結到另一個推理指令碼,但是現在我們將堅持使用label_image.py。
將一次性推斷轉換為線上推斷(Tensorflow)
如果我們只想接受來自標準輸入的檔名,每行一個,我們就可以很容易地進行“線上”推斷:
從效能的角度來看,這很糟糕——我們正在重新載入神經網路、權重、整個Tensorflow框架和python本身,對於每個輸入示例都是如此!
我們可以做得更好。 讓我們開始編輯label_image.py指令碼——對於我來說,它位於bazel-bin / tensorflow / examples / image_retraining / label_image.runfiles / org_tensorflow / tensorflow / examples / image_retraining / label_image.py中。
讓我們改變行
到
這確實快了很多,但是這還不是我們能做的最好的!
原因是tf.Session()在第100行上的sess構造。Tensorflow基本上每次呼叫run_graph時都將所有的計算載入到記憶體中。當您開始嘗試在GPU上進行推理時,這一點就變得很明顯了——您可以看到GPU記憶體隨著Tensorflow在GPU上載入和解除安裝模型引數而上下移動。據我所知,這種結構並不存在於其他ML框架中,比如Caffe或Pytorch。
然後解決方案是拉出with語句,並傳遞一個sess變數到run_graph:
(在https://github.com/hiveml/simple-ml-serving/blob/master/label_image.py上看程式碼)
如果你執行這個程式,你會發現每張圖片載入大約需要0.1秒,對於線上使用來說足夠快。
將一次性推斷轉換為線上推理(其他ML框架)
Caffe使用它的net.forward程式碼,這個程式碼很容易放入可呼叫的框架中:請參閱http://nbviewer.jupyter.org/github/BVLC/caffe/blob/master/examples/00-classification.ipynb
Mxnet也是非常獨特的:它實際上具有開源的隨時可用的推理伺服器程式碼:https://github.com/awslabs/mxnet-model-server。
部署
計劃是將這些程式碼包裝在Flask應用程式中。 如果您還沒有聽說過它,Flask是一個非常輕量級的Python Web框架,它允許您用最少的工作來建立一個http api伺服器。
作為一個快速的參考,這是一個flask應用程式,它接收來自多個表單資料的POST請求:
這是對應的flask應用程式連線到run_graph上面:
這看起來很好,除了flask和tensorflow都是完全同步的——按照接收到的順序一次處理一個請求,而Tensorflow在進行影象分類時完全佔用執行緒。
正如它所寫的那樣,速度瓶頸可能還在實際的計算工作中,所以升級Flask包裝程式碼沒有太多的意義。現在,也許這段程式碼足夠處理您的負載了。
有兩種很明顯的方法可以提高請求的通用性:通過增加worker的數量來橫向放大,這在下一節將會介紹,或者通過使用GPU和批處理邏輯來縱向擴充套件。實現後者需要一個能夠同時處理多個掛起請求的web伺服器,並決定是否繼續等待更大的批處理,或者將其傳送到Tensorflow圖形執行緒,以便進行分類,而這對於Flask應用程式是非常不適合。有兩種可能性,使用Twisted + Klein來儲存Python程式碼,或者如果您更喜歡第一個類的事件迴圈支援,並且能夠連線到非Python ML框架(如Torch),則可以使用Node.js + ZeroMQ。
擴充套件:負載平衡和服務發現
好的,現在我們有一臺伺服器來服務我們的模型,但也許它太慢了,或者我們的負載變得太高了。我們想要啟動更多的這些伺服器——我們如何在每個伺服器上分配請求?
普通的方法是新增一個代理層,可能是haproxy或nginx,它平衡後端伺服器之間的負載,同時向客戶機提供一個統一的介面。為了在本節稍後使用,以下是執行基本Node.js負載均衡器http代理的一些示例程式碼:
為了自動檢測後端伺服器的數量和位置,人們通常會使用“服務發現”工具,該工具可能與負載平衡器捆綁在一起或者是單獨的。一些知名的是Consul和Zookeeper。設定和學習如何使用它不在本文的討論範圍之內,所以我使用了node.js服務發現包seaport來包含一個非常基本的代理。
代理程式碼:
Worker 程式碼:
但是,對於ML,這個設定會遇到頻寬問題。
在任何地方,每秒幾十到幾百張影象,系統就會被網路頻寬阻塞。在目前的設定中,所有的資料都必須通過我們的單個seaport 主站,這是呈現給客戶端的單個端點。
為了解決這個問題,我們要求我們的客戶端不在http://127.0.0.1:12480點選單個端點,而是在後端伺服器之間自動輪換點選。如果你知道一些網路,這聽起來就像DNS的工作!
但是,設定自定義的DNS伺服器已經超出了本文的範圍。 相反,通過更改客戶端來遵循兩步“手動DNS”協議,我們可以重新使用我們的基本seaport代理來實現客戶端直接連線到其伺服器的“點對點”協議:
代理程式碼:
(worker程式碼與上述相同)
客戶端程式碼:
RPC部署
即將到來!上面的Flask版本被ZeroMQ替換。
結論和進一步閱讀
在這一點上,你應該有一些在生產中工作的東西,但它肯定不是未來的保障。本指南中沒有涉及到的幾個重要的主題:
自動部署和設定新的硬體。
如果你在自己的硬體上,值得注意的工具包括Openstack/VMware,Chef / Puppet用於安裝Docker和處理網路路由,以及Docker用於安裝Tensorflow、Python和其他任何東西。
如果你在雲端,Kubernetes或Marathon/Mesos也很棒。
模型版本管理
在開始的時候手動處理並不太難。
Tensorflow Serving是一個很好的工具,它可以非常徹底地處理這個問題,以及批處理和整體部署。缺點是設定和編寫客戶端程式碼有點困難,而且不支援Caffe/PyTorch。
如何從Matlab移植你的ML程式碼
不要在生產中使用matlab。
GPU驅動程式,Cuda,CUDNN
使用nvidia-docker並嘗試線上查詢一些Docker檔案。
後處理圖層。一旦您在生產中獲得了一些不同的ML模型,您可能會開始想要混合並匹配不同的用例——只有在模型B不確定的情況下執行模型A,在Caffe中執行模型C,並將結果傳遞給Tensorflow中的模型D等等。
作者資訊
Bowei,Hive機器學習工程師
本文由阿里云云棲社群組織翻譯。
文章原標題《Step-by-step Guide to Deploying Deep Learning Models》
作者:Bowei譯者:董昭男 稽核:
作者:阿里云云棲社群
連結:https://www.jianshu.com/p/43da2553a2fb
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。