手把手教你如何部署深度學習模型

摘要: 本文將講解如何部署深度學習模型,讓你不再對如何快速地將機器學習模型部署到生產中感到困擾

我剛剛訓練了機器學習模型——那麼現在呢

這篇文章介紹了一種快速的方法,將經過訓練的機器學習模型部署到生產中。

請閱讀以下內容:如果您已經成功地使用諸如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
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯繫作者獲得授權並註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章