函數計算部署機器學習遇到的問題和解法

來自專欄我是程序員6 人贊了文章

摘要 隨著 Serverless 的流行,將應用遷移到雲上已經成了一種必然的趨勢。我們今天來看一下如何將機器學習應用遷移到函數計算上。 1. 本地開發 首先我們看一下本地開發機器學習應用的步驟。我們大概可以將本地開發概括為三個步驟,分別是代碼編寫,安裝依賴,運行調試。

隨著 Serverless 的流行,將應用遷移到雲上已經成了一種必然的趨勢。

我們今天來看一下如何將機器學習應用遷移到函數計算上。

1. 本地開發

首先我們看一下本地開發機器學習應用的步驟。我們大概可以將本地開發概括為三個步驟,分別是代碼編寫,安裝依賴,運行調試。我們分別來看一下。

1.1 代碼編寫假定我們的項目結構為:

其中 index.py 存放了機器學習相關的代碼,model_data 存放了數據模型,pic 中存放了要進行測試的圖片。index.py 的內容為(代碼參考了這篇文章):

1.2 安裝依賴在運行應用前,需要先安裝應用依賴的模塊,這裡主要依賴了 opencv 以及 tensorflow,安裝方法很簡單:

執行完這兩條命令後,opencv-python 以及 tensorflow 就被安裝到系統目錄里。Linux 下默認為 /usr/local/lib/pythonX.Y/site-packages。

1.3 運行

運行時,python 會自動在配置的路徑下查找相關模塊並進行載入。

經過這三個步驟,我們就完成了本地機器學習應用的開發,我們接下來看下如何遷移應用到函數計算。

2. 遷移函數計算

2.1 本地開發與函數計算開發對比首先,我們需要做一些準備工作。讓我們來思考下函數計算應用開發方式與本地應用應用的開發方式有什麼不同呢?
  1. 代碼入口。本地開發時,代碼可以省略 main 函數,也可以提供 main 函數作為程序入口,但在函數計算中,函數入口是固定的,非 Http 觸發器的函數入口必須是一個包含了兩個參數的函數,比如:def handler(event, context)。
  2. 模塊依賴。本地開發時,項目依賴的模塊通常會被安裝到系統的某個目錄。比如我們上面執行的 pip install tensorflow。而對於函數計算,由於為了能夠最大限度的對應用進行優化,開放給用戶的操作空間通常是比較小的。因此,對於函數計算,目前還無法做到安裝項目依賴到運行環境。我們只能通過將自定義模塊一同打包的方式。參考。
  3. 運行。本地開發時,需要使用 python 命令或者 IDE 來運行代碼。而在函數計算,我們需要首先部署應用到函數計算,再通過觸發器或者控制台手動觸發執行。

接下來我們針對這三點開發方式的不同對代碼進行改造。

2.2 改造代碼

2.2.1 代碼入口改造這個比較簡單,只需要將

修改為

並刪除下面代碼:

2.2.2. 模塊依賴這一塊稍微複雜些。不同的語言因為模塊載入機制的不同,這裡的處理邏輯也會有差異。比如對於 java,無論是使用 maven,還是 gradle,都可以很容易的一鍵將代碼以及依賴打包成 jar。但遺憾的是 python 目前沒有這種機制。我們先根據場景對 python 依賴的模塊做個簡單的分類。

應用依賴: 對於本例中使用 pip 安裝的模塊,比如 pip install tensorflow,我們暫且將其稱為應用依賴。系統依賴: 在某些場景下,python 安裝的庫僅僅是對底層 c、c++ 庫調用的封裝,例如使用 zbar 時,除了使用 pip install zbar,還要在系統中安裝相應的庫:apt-get install -y libzbar-dev。我們暫且把像 libzbar-dev 一樣需要使用系統軟體包管理器安裝的庫稱為系統依賴。資源依賴: 對於一些應用,比如機器學習,啟動後還需要載入數據模型,數據模型需要在程序啟動時準備好,我們暫且將這種依賴稱為資源依賴。資源依賴比較特殊,它是我們的應用邏輯所需要的,通常體積比較大。對於應用依賴,我們可以通過 pip 的 -t 參數改變其安裝位置,比如 pip install -t $(pwd) tensorflow。並且可以通過 sys.path 改變載入行為,使得可以從指定目錄載入模塊。

對於系統依賴,我們可以通過 apt-get 下載 deb 包,再利用 deb 包安裝到指定目錄。

對於系統依賴包含的鏈接庫,可以通過 LD_LIBRARY_PATH 變數改變其載入行為。對於資源依賴,因為控制權在我們的代碼里,因此只需要改變代碼的處理邏輯就可以了。根據上面的描述,我們可以整理成下面的表格:

控制2.2.3 下載依賴的邏輯

對於我們的 demo 應用,存在兩種依賴,一種是應用依賴,另一種是資源依賴。而需要我們特別處理的只有應用依賴。我們需要在項目目錄下創建一個名為 applib 的目錄,並下載應用依賴到該目錄。這裡需要注意的是如果引用的模塊使用 C / C++ / go 編譯出來的可執行文件或者庫文件,那麼推薦使用 fcli 的 sbox 進行下載,使用方法為:

執行完畢後,就會發現 applib 中就包含了項目所需要的應用依賴。

2.2.4 打包依賴上傳到 OSS

機器學習的應用依賴、資源依賴通常比較大,會很容易超過函數計算對代碼包的限制(50M)。為了避開這個問題,我們需要將這些依賴上傳到 OSS:

執行完畢後,項目會多出一個名為 applib.zip 的壓縮包,上傳到 oss 即可。同樣的,對資源依賴進行相同的操作:

2.2.5 初始化依賴

這裡我們提供一個模板代碼,負責在函數第一次啟動時,從 OSS 下載資源到本地、解壓,並配置好相應的環境變數。我們可以在項目中創建一個名為 loader.py 文件,內容為:

這段代碼會首先讀取 AppLibObject 環境變數,用於從 OSS 下載應用依賴,並解壓到 AppLibDir 這個環境變數所代表的目錄。其次會讀取 ModelObject 環境變數,用於從 OSS 下載資源依賴,並解壓到 ModelDir 這個環境變數所代表的目錄。最後,當依賴準備妥當後,會調用 index.py 中的 handler 函數。理論上,這個代碼可以用於其它任何需要下載應用依賴、資源依賴的場景。而我們的 index.py 需要修改的,只有將原先的獲取模型依賴的固定的路徑,修改為利用 ModelDir 獲取路徑即可。

2.3 本地運行調試代碼編寫完成後,我們的目錄結構調整為:

我們本地運行看下效果,這裡我們藉助於函數計算推出的 fc-dcoker 工具。

為了避免本地每次調試做無謂的下載,我們取下巧,將應用依賴、資源依賴掛載到 fc-docker 中,並開啟 local 的標識:

得到結果:

2.4 部署

本地開發完成,接下來,我們就需要部署應用到線上了。這裡我們藉助函數計算推出的 Fun 工具。Fun 工具使用步驟如下:
  1. 去 release 頁面對應平台的 binary 版本,解壓就可以使用。或者使用 npm install @alicloud/fun -g 也可以直接使用。
  2. 使用 fun config 配置 ak、region 等信息。
  3. 編寫 template.yml
  4. fun deploy 部署

是的,不需要登錄控制台進行繁瑣的配置,僅僅在項目下提供一個 template.yml 即可:

至此,我們的項目中又多了一個 template.yml,結構為

通過這一個 template.yml,執行 fun deploy 後即可創建好相應的服務、函數,並配置好函數的環境變數。

即使修改了代碼,只要重複執行 fun deploy 即可。

接下來,打開 https://fc.console.aliyun.com/ 控制台,依次找到創建好的服務、函數,點擊執行,即可得到與本地一致的輸出:

2.5 補充在上面的例子中,我們只列出了應用依賴、資源依賴的情況。對於系統依賴的處理邏輯是比較簡單的,比如我們拿 zbar 舉例。除了需要在 applib 中通過 pip 安裝 zbar,還要在 code 目錄下新建一個 lib 目錄,並通過 sandbox 在這個目錄中執行:

執行完成後,目錄結構變化為:

就像上面提到的,我們需要修改 LD_LIBRARY_PATH 來改變系統依賴的載入行為,因此我們需要在 template.yaml 中的 EnvironmentVariables 下添加一行:

至此,就可以直接在 index.py 等文件中直接使用 zbar 了。

3. 總結

結果一番努力,我們終於將機器學習應用上線到函數計算了。回顧上面的所有操作可以發現,其實大部分的改造工作都是可以通過工具解決的。無論是 template.yml,還是 loader.py 都是直接拿來就能用的。而真正需要開發者操作的也就只有下載依賴、修改對資源依賴的引用路徑了。

本文作者:tanhe123

原文鏈接

更多技術乾貨敬請關注云棲社區知乎機構號:阿里云云棲社區 - 知乎

本文為阿里云云棲社區原創內容,未經允許不得轉載。


推薦閱讀:
查看原文 >>
相关文章