基於 KubeVela 的機器學習實踐

語言: CN / TW / HK

作者:KubeVela 社群

在機器學習浪潮迸發的當下,AI 工程師除了需要訓練、除錯自己的模型之外,還需要將模型進行部署上線,從而驗證模型的效果(當然,有的時候,這部分工作由 AI 系統工程師來完成)。這一部分工作對於 AI 工程師們來說是繁瑣、且消耗額外精力的。

而在雲原生時代,我們的模型訓練和模型服務也通常在雲上進行。這樣做不僅提高了可擴充套件性,還能夠提升資源的利用率。這對於需要消耗大量計算資源的機器學習場景來說,是十分有效的。

但是 AI 工程師要想使用雲原生的能力通常比較困難。隨著時間的推移,雲原生的概念已經越來越複雜。想要在雲原生之上部署一個簡單的模型服務,可能對於 AI 工程師來說,需要額外學習數種概念:比如 Deployment、Service、Ingress 等。

而 KubeVela 作為一個簡單、易用、且高可擴充套件的雲原生應用管理工具,能讓開發人員方便快捷地在 Kubernetes 上定義與交付應用,無需瞭解任何底層雲原生基礎設施相關的細節。KubeVela 擁有著豐富的可擴充套件性,其 AI 外掛提供了模型訓練、模型服務、A/B 測試等功能,覆蓋了 AI 工程師的基本需求,能夠幫助 AI 工程師快速在雲原生環境中進行模型訓練和模型服務。

本文主要介紹如何使用 KubeVela 的 AI 外掛,來幫助工程師更便捷地完成模型訓練及模型服務。

KubeVela AI 外掛

KubeVela AI 外掛分為模型訓練和模型服務兩個外掛,模型訓練外掛基於 KubeFlow 的 training-operator,能夠支援如 TensorFlow、PyTorch、MXNet 等不同框架的分散式模型訓練。而模型服務外掛基於 Seldon Core,可以便捷地使用模型啟動模型服務,同時也支援流量分發,A/B 測試等高階功能。

通過 KubeVela AI 外掛,可以大大簡化模型訓練任務的部署以及模型服務的部署,同時,可以將模型訓練、模型服務等過程與 KubeVela 本身的工作流、多叢集等功能相結合,從而完成生產可用的服務部署。

注:你可以在 KubeVela Samples [1]  中找到所有的原始碼和 YAML 檔案。如果你想使用在這個例子中預訓練的模型,資料夾中的 style-model.yaml 和 color-model.yaml 會將模型複製到 PVC 中。

模型訓練

首先啟動模型訓練和模型服務的兩個外掛。

vela addon enable model-training
vela addon enable model-serving

模型訓練中包含 model-training 和 jupyter-notebook 兩個元件型別, 模型服務中包含 model-serving 這個元件型別。可以通過 vela show 命令來檢視這三個元件中的具體引數。

你也可以選擇查閱 KubeVela AI 外掛文件 [2] , 來獲取更多資訊。

vela show model-training
vela show jupyter-notebook
vela show model-serving

我們來訓練一個簡單的使用 TensorFlow 框架的模型,這個模型的效果是能夠將灰色的圖片變成彩色的。部署如下 YAML 檔案:

注:模型訓練的原始碼來源於:emilwallner/Coloring-greyscale-images [3]

apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
  name: training-serving
  namespace: default
spec:
  components:
  # 訓練模型
  - name: demo-training
    type: model-training
    properties:
      # 訓練模型的映象
      image: fogdong/train-color:v1
      # 模型訓練的框架
      framework: tensorflow
      # 宣告儲存,將模型持久化。此處會使用叢集內的預設 storage class 來建立 PVC
      storage:
        - name: "my-pvc"
          mountPath: "/model"

此時, KubeVela 將拉起一個 TFJob 進行模型訓練。

僅僅是訓練模型很難看出效果,我們修改一下這個 YAML 檔案,將模型服務放到模型訓練的步驟之後。同時,因為模型服務會直接啟動模型,而模型的輸入輸出不太直觀(ndarray 或者 Tensor),因此,我們再部署一個測試服務來呼叫服務,並將結果轉換成影象。

部署如下 YAML 檔案:

apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
  name: training-serving
  namespace: default
spec:
  components:
  # 訓練模型
  - name: demo-training
    type: model-training
    properties:
      image: fogdong/train-color:v1
      framework: tensorflow
      storage:
        - name: "my-pvc"
          mountPath: "/model"
  
  # 啟動模型服務
  - name: demo-serving
    type: model-serving
    # 模型服務會在模型訓練完成後啟動
    dependsOn:
      - demo-training
    properties:
      # 啟動模型服務使用的協議,可以不填,預設使用 seldon 自身的協議
      protocol: tensorflow
      predictors:
        - name: model
          # 模型服務的副本數
          replicas: 1
          graph:
            # 模型名
            name: my-model
            # 模型框架
            implementation: tensorflow
            # 模型地址,上一步會將訓練完的模型儲存到 my-pvc 這個 pvc 當中,所以通過 pvc://my-pvc 指定模型的地址
            modelUri: pvc://my-pvc

  # 測試模型服務
  - name: demo-rest-serving
    type: webservice
    # 測試服務會在模型訓練完成後啟動
    dependsOn:
      - demo-serving
    properties:
      image: fogdong/color-serving:v1
      # 使用 LoadBalancer 暴露對外地址,方便呼叫
      exposeType: LoadBalancer
      env:
        - name: URL
          # 模型服務的地址
          value: http://ambassador.vela-system.svc.cluster.local/seldon/default/demo-serving/v1/models/my-model:predict
      ports:
        # 測試服務的埠
        - port: 3333
          expose: true

部署之後,通過 vela ls 來檢視應用的狀態:

$ vela ls

training-serving        demo-training        model-training           running  healthy  Job Succeeded  2022-03-02 17:26:40 +0800 CST
├─                    demo-serving         model-serving            running  healthy  Available      2022-03-02 17:26:40 +0800 CST
└─                    demo-rest-serving    webservice               running  healthy  Ready:1/1      2022-03-02 17:26:40 +0800 CST

可以看到,應用已經正常啟動。通過 vela status <app-name> --endpoint 來檢視應用的服務地址。

$ vela status training-serving --endpoint

+---------+-----------------------------------+---------------------------------------------------+
| CLUSTER |     REF(KIND/NAMESPACE/NAME)      |                     ENDPOINT                      |
+---------+-----------------------------------+---------------------------------------------------+
|         | Service/default/demo-rest-serving | tcp://47.251.10.177:3333                          |
|         | Service/vela-system/ambassador    | http://47.251.36.228/seldon/default/demo-serving  |
|         | Service/vela-system/ambassador    | https://47.251.36.228/seldon/default/demo-serving |
+---------+-----------------------------------+---------------------------------------------------+

該應用有三個服務地址,第一個是我們的測試服務的地址,第二個和第三都是原生模型的地址。我們可以呼叫測試服務來檢視模型的效果:測試服務會讀取影象的內容,並將其轉成 Tensor 並請求模型服務,最後將模型服務返回的 Tensor 轉成影象返回。

我們選擇一張黑白的女性圖片作為輸入:

請求後,可以看到,輸出了一張彩色圖片:

模型服務:灰度測試

除了直接啟動模型服務,我們還可以在一個模型服務中使用多個版本的模型,並對其分配不同的流量以進行灰度測試。

部署如下 YAML,可以看到,v1 版本的模型和 v2 版本的模型都設定為了 50% 的流量。同樣,我們在模型服務後面部署一個測試服務:

apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
  name: color-serving
  namespace: default
spec:
  components:
  - name: color-model-serving
    type: model-serving
    properties:
      protocol: tensorflow
      predictors:
        - name: model1
          replicas: 1
          # v1 版本的模型流量為 50
          traffic: 50
          graph:
            name: my-model
            implementation: tensorflow
            # 模型地址,在 color-model 這個 pvc 中 /model/v1 路徑下存放了我們的 v1 版本模型,所以通過 pvc://color-model/model/v1 指定模型的地址
            modelUri: pvc://color-model/model/v1
        - name: model2
          replicas: 1
          # v2 版本的模型流量為 50
          traffic: 50
          graph:
            name: my-model
            implementation: tensorflow
            # 模型地址,在 color-model 這個 pvc 中 /model/v2 路徑下存放了我們的 v2 版本模型,所以通過 pvc://color-model/model/v2 指定模型的地址
            modelUri: pvc://color-model/model/v2
  - name: color-rest-serving
    type: webservice
    dependsOn:
      - color-model-serving
    properties:
      image: fogdong/color-serving:v1
      exposeType: LoadBalancer
      env:
        - name: URL
          value: http://ambassador.vela-system.svc.cluster.local/seldon/default/color-model-serving/v1/models/my-model:predict
      ports:
        - port: 3333
          expose: true

當模型部署完成後,通過 vela status <app-name> --endpoint 檢視模型服務的地址:

$ vela status color-serving --endpoint

+---------+------------------------------------+----------------------------------------------------------+
| CLUSTER |      REF(KIND/NAMESPACE/NAME)      |                         ENDPOINT                         |
+---------+------------------------------------+----------------------------------------------------------+
|         | Service/vela-system/ambassador     | http://47.251.36.228/seldon/default/color-model-serving  |
|         | Service/vela-system/ambassador     | https://47.251.36.228/seldon/default/color-model-serving |
|         | Service/default/color-rest-serving | tcp://47.89.194.94:3333                                  |
+---------+------------------------------------+----------------------------------------------------------+

使用一張黑白的城市圖片請求模型:

可以看到,第一次請求的結果如下。雖然天空和地面都被渲染成彩色了,但是城市本身還是黑白的:

再次請求,可以看到,這次請求的結果中,天空、地面和城市都被渲染成了彩色:

通過對不同版本的模型進行流量分發,可以幫助我們更好地對模型結果進行判斷。

模型服務:A/B 測試

同樣一張黑白的圖片,我們既可以通過模型將其變成彩色的,也可以通過上傳另一張風格圖片,對原圖進行風格遷移。

對於使用者來說,究竟是彩色的圖片好還是不同風格的圖片更勝一籌?我們可以通過進行 A/B 測試,來探索這個問題。

部署如下 YAML,通過設定 customRouting,將 Header 中帶有 style: transfer 的請求,轉發到風格遷移的模型。同時,使這個風格遷移的模型與彩色化的模型共用一個地址。

注:風格遷移的模型來源於 TensorFlow Hub [4]

apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
  name: color-style-ab-serving
  namespace: default
spec:
  components:
  - name: color-ab-serving
    type: model-serving
    properties:
      protocol: tensorflow
      predictors:
        - name: model1
          replicas: 1
          graph:
            name: my-model
            implementation: tensorflow
            modelUri: pvc://color-model/model/v2
  - name: style-ab-serving
    type: model-serving
    properties:
      protocol: tensorflow
      # 風格遷移的模型需要的時間較長,設定超時時間使請求不會被超時
      timeout: "10000"
      customRouting:
        # 指定自定義 Header
        header: "style: transfer"
        # 指定自定義路由
        serviceName: "color-ab-serving"
      predictors:
        - name: model2
          replicas: 1
          graph:
            name: my-model
            implementation: tensorflow
            modelUri: pvc://style-model/model
  - name: ab-rest-serving
    type: webservice
    dependsOn:
      - color-ab-serving
      - style-ab-serving
    properties:
      image: fogdong/style-serving:v1
      exposeType: LoadBalancer
      env:
        - name: URL
          value: http://ambassador.vela-system.svc.cluster.local/seldon/default/color-ab-serving/v1/models/my-model:predict
      ports:
        - port: 3333
          expose: true

部署成功後,通過 vela status <app-name> --endpoint 檢視模型服務的地址:

$ vela status color-style-ab-serving --endpoint

+---------+---------------------------------+-------------------------------------------------------+
| CLUSTER |    REF(KIND/NAMESPACE/NAME)     |                       ENDPOINT                        |
+---------+---------------------------------+-------------------------------------------------------+
|         | Service/vela-system/ambassador  | http://47.251.36.228/seldon/default/color-ab-serving  |
|         | Service/vela-system/ambassador  | https://47.251.36.228/seldon/default/color-ab-serving |
|         | Service/vela-system/ambassador  | http://47.251.36.228/seldon/default/style-ab-serving  |
|         | Service/vela-system/ambassador  | https://47.251.36.228/seldon/default/style-ab-serving |
|         | Service/default/ab-rest-serving | tcp://47.251.5.97:3333                                |
+---------+---------------------------------+-------------------------------------------------------+

這個應用中,兩個服務各自有兩個地址,但是第二個 style-ab-serving 的模型服務地址是無效的,因為這個模型服務已經被指向了 color-ab-serving 的地址中。同樣,我們通過請求測試服務來檢視模型效果。

首先,在不加 header 的情況下,影象會從黑白變為彩色:

我們新增一個海浪的圖片作為風格渲染:

我們為本次請求加上 style: transfer 的 Header,可以看到,城市變成了海浪風格:

我們還可以使用一張水墨畫的圖片作為風格渲染:

可以看到,這次城市變成了水墨畫風格:

總結

通過 KubeVela 的 AI 外掛,可以幫助你更便捷地進行模型訓練與模型服務。

除此之外,通過與 KubeVela 的結合,我們還能將測試完效果的模型通過 KubeVela 的多環境功能,下發到不同的環境中,從而實現模型的靈活部署。

相關連結

[1] KubeVela Samples

​https://github.com/oam-dev/samples/tree/master/11.Machine_Learning_Demo​

[2] KubeVela AI 外掛文件

​https://kubevela.io/zh/docs/next/reference/addons/ai​

[3] emilwallner/Coloring-greyscale-images

​https://github.com/emilwallner/Coloring-greyscale-images​

[4]TensorFlow Hub

​https://tfhub.dev/google/magenta/arbitrary-image-stylization-v1-256/2​

近期熱門

您可以通過如下材料瞭解更多關於 KubeVela 以及 OAM 專案的細節:

  • 專案程式碼庫:​github.com/oam-dev/kubevela​ 歡迎 Star/Watch/Fork!
  • 專案官方主頁與文件:kubevela.io ,從 1.1 版本開始,已提供中文、英文文件,更多語言文件歡迎開發者進行翻譯。
  • 專案釘釘群:23310022;Slack:CNCF #kubevela Channel
  • 加入微信群:請先新增以下 maintainer 微訊號,表明進入 KubeVela 使用者群:

點選“​此處​​”,檢視 KubeVela 專案官網。​