如今有許多關於 AI 的教程。好比如何進行目標檢測、圖像分類、NLP 以及構建聊天機器人等,不勝枚舉。瀏覽器
但當我查找如何正確擴展 AI 的內容時,卻發現少得可憐。更使人驚訝的是,現有的極少數資源在反覆強調相同的幾點:緩存
我對第二點更感興趣,由於我已經開發好了一個模型,但令我驚訝的是,沒有任何關於如何實現第二點的細節,而關於每一個解決方案缺點的信息則更少。研究了幾天並在 Crane.ai 上擴展 AI 以後,我整理了一些關於如何部署這些方法、這些方法的缺點以及如何在低級別優化 TensorFlow 模型的內容。安全
將模型打包到客戶端——這種方法太糟了!服務器
最經常使用的方法之一是用像 TensorFlow.js、TF Lite 或 TensorFlow Slim 這樣的工具將 AI 打包到你所選擇的客戶端中。我不會詳細介紹這些框架如何運行,但我會重點說明它們的缺點。網絡
這些缺點使得在客戶端上部署和維護大型神經網絡幾乎不可能,因此咱們從擴展模型的備選項中排除這一項。架構
部署爲雲端點框架
雲是能夠大規模部署模型的強大工具。你能夠根據須要定製環境、容器化應用程序、當即水平擴展應用程序,同時提供足以和大公司媲美的 SLA 和運行時間。微服務
對大部分 TensorFlow 模型來講,部署流程是相同的:工具
第一部分相對簡單。「固化」圖要用全部命名節點、權重、架構和檢查點元數據建立一個 protobuf 二進制文件。這一步能夠用多種工具實現,最經常使用的是 TF 本身的工具,它能夠固化任何給定輸出節點名字的圖。性能
調整推斷代碼也不難。在大多數狀況下,feed_dict 是不變的,主要區別在於添加了加載模型的代碼,也許還有輸出節點的規範。
容器化也很簡單——只要在 Dockerfile 中設置環境便可。而當咱們開始添加 API 層時,事情就會變得混亂。一般用這兩種方法:
部署能夠運行推斷腳本的擴展容器。這些容器根據輸入運行腳本,腳本啓動一個會話並執行推斷,再經過管道返回輸出結果。這是頗有問題的:對大多數雲供應商而言添加一個能夠操縱容器和管道進出的 API 層並不容易(例如,AWS 有 API 網關,但它並不像你指望的那麼方便),並且這種方法是你能夠採用的效率最低的方法。這裏的問題是你在啓動容器、分配硬件、啓動會話以及推斷時損失的寶貴時間。若是你讓 stdin 開着並保持管道輸出,那麼你的腳本就會加速可是會失去可擴展性(如今你已經鏈接到容器的 STDIN,而它沒法接受多個請求)。
部署運行 API 層的擴展容器。儘管在架構上類似,但因爲如下幾個緣由,這種方法效率更高。將 API 層內置在容器中,能夠緩解以前提出的大多數問題。雖然這須要更多資源,但它已經用了最少資源並且沒有垂直擴展;它容許每一個容器保持運行狀態,並且因爲這種狀況下 API 是分散的,所以能夠將特定的 stdin/stout 鏈接到主要的請求路由器上。這意味着省去了啓動時間,能夠在服務多個請求的同時維持速度並保證水平擴展。能夠用負載平衡器集中容器,並用 Kubernetes 保證近乎 100% 的運行時間並管理集羣。這種方式簡單且有效。
部署集羣!
經過容器集羣分散 API 的主要缺點在於計算成本會相對較快地累積起來。不幸的是這在 AI 中是不可避免的,但有一些方法能夠緩解這一問題。
使用任務隊列。通常須要運行或大或小的推斷任務(在咱們的例子中是較大和較小、複雜和簡單的圖像)。對 UX 來講,使用堆隊列(heap queue)可能更好,它會優先處理小一些的任務,因此要運行簡單步驟的用戶只要等這一步結束就好了,而沒必要等另外一個用戶的更大推斷任務先完成。(也許你會想我在這裏爲何不用水平擴展,你能夠這麼作可是會增長計算成本)。
在帶有任務隊列的專用 GPU 上訓練模型。訓練是一項長期、困難的任務,它須要大量可用的資源,並且模型在訓練過程當中沒法使用。若是你要將每一個交互返回到模型中進行訓練,請考慮在單獨的服務器或 GPU 上運行。一旦訓練結束,你就能夠將模型(在 AWS 中,你能夠將模型 repo 集中在 S3 中)部署到容器中了。
結論
深思熟慮後,咱們提出了一個大規模部署 AI 的高效工做流程:
使用這些技術,你就能夠在成本最小、速度和效率最大的狀況下大規模部署 AI。
感興趣的能夠本身來個人Java架構羣,能夠獲取免費的學習資料,羣號:855801563 對Java技術,架構技術感興趣的同窗,歡迎加羣,一塊兒學習,相互討論。