Kubeflow 管道 - GitHub 問題摘要

1. 簡介

KubeflowKubernetes 專用的機器學習工具包。這項專案旨在實現機器學習 (ML) 工作流程的部署,簡化 Kubernetes 的可攜性與可擴充性。目標是提供簡單明瞭的方式,將業界最佳的機器學習開放原始碼系統部署至多樣化的基礎架構。

從資料準備、分析、訓練、評估到部署等,機器學習工作流程可能涉及許多依賴依附元件的步驟。要臨時編寫及追蹤這些程序並不容易,例如在一組筆記本或指令碼中,稽核及可再重現性等工作也變得越來越棘手。Kubeflow Pipelines (KFP) 可讓您透過監控、稽核、版本追蹤和可重現性機制部署完善且可重複執行的機器學習管道,協助解決這些問題。Cloud AI Pipelines 可讓您輕鬆設定 KFP 安裝作業。

建構項目

在本程式碼研究室中,您將使用 Kubeflow Pipelines 建構網頁應用程式,簡述 GitHub 問題以訓練及提供模型。以 Kubeflow 範例存放區中的範例為基礎。完成之後,您的基礎架構就會包含:

課程內容

您將利用這個管道建構 GitHub 問題資料來訓練 Tensor2Tensor 模型,學習預測問題主體的問題標題。接著,匯出訓練過的模型,並透過 Tensorflow Serving 部署匯出的模型。管線的最後一個步驟會啟動網頁應用程式,這個應用程式會與 TF-Serving 執行個體互動,以取得模型預測結果。

  • 如何在 GKE 叢集中安裝 Kubeflow Pipelines
  • 如何使用 Kubeflow Pipelines 建立及執行機器學習工作流程
  • 如何從 AI 平台筆記本定義及執行管道

軟硬體需求

2. 設定

Cloud Shell

在瀏覽器中前往 GCP Console,並使用您的專案憑證登入:

按一下「選取專案」以便使用程式碼研究室專案

4f23e1fe87a47cb2.png

接著,按一下「啟用 Cloud Shell」啟動 Cloud Shell

ecf212797974dd31.png

啟動 Cloud Shell 時,系統會指出目前設定要使用的專案名稱。確認這項設定正確無誤

如要查看專案 ID,請前往 GCP 控制台的首頁面板。如果畫面空白,請按一下「是」即可建立資訊主頁

115cdf745978ad.png

然後,在 Cloud Shell 終端機中,視需要執行下列指令來設定 gcloud 以使用正確的專案:

export PROJECT_ID=<your_project_id>
gcloud config set project ${PROJECT_ID}

建立儲存空間值區

建立 Cloud Storage 值區來儲存管道檔案。您必須使用全域專屬 ID,因此可輕鬆定義包含專案 ID 的值區名稱。使用 gsutil mb (建立值區) 指令建立值區:

export PROJECT_ID=<your_project_id>
export BUCKET_NAME=kubeflow-${PROJECT_ID}
gsutil mb gs://${BUCKET_NAME}

您也可以透過 GCP 主控台建立值區。

選用**:建立 GitHub 權杖**

本程式碼研究室會呼叫 GitHub API 以擷取公開資料。如要避免頻率限制,特別是將大量匿名要求傳送至 GitHub API 的事件,請設定沒有權限的存取權杖。這只是為了授權您個人,而非匿名使用者。

  1. 前往 https://github.com/settings/tokens 產生未設定範圍的新符記。
  2. 並保存在安全的地方,如果遺失值區,則必須刪除現有資料夾,然後建立新設定檔。

如果略過這個步驟,研究室仍會正常運作,產生輸入資料用來測試模型的選項會受到限制。

選用:固定實用的資訊主頁

在 GCP 控制台中,固定「Kubernetes Engine」和「Storage」資訊主頁,以便存取。

2a50622902d75f6a.png

建立 AI 平台管道 (託管 Kubeflow Pipelines) 安裝項目

請按照「事前準備」一節中的指示操作以及「設定執行個體」請參閱這篇文章,瞭解如何設定 GKE 執行個體 (已安裝 KFP)。「務必」勾選說明文件所述的「允許存取下列 Cloud API」方塊。否則就無法成功執行範例管道。將安裝命名空間保留為 default

您必須選擇支援 Nvidia k80s 的區域。您可以使用 us-central1-aus-central1-c 做為預設值。

安裝完成後,請記下 AI Pipelines 資訊主頁列出安裝作業的 GKE 叢集名稱可用區,方便您將環境變數設為這些值。

6f0729a4fdee88ac.png

export ZONE=<your zone>
export CLUSTER_NAME=<your cluster name>

設定 kubectl 以使用新的 GKE 叢集憑證

GKE 叢集建立完成後,請在 Cloud Shell 中執行下列指令,將 kubectl 設為使用新叢集的憑證:

gcloud container clusters get-credentials ${CLUSTER_NAME} \
  --project ${PROJECT_ID} \
  --zone ${ZONE}

或者,您也可以按一下 AI Pipelines 資訊主頁中的叢集名稱,前往 GKE 頁面,然後再按一下「連結」在網頁頂端顯示留言將彈出式視窗中的指令貼到 Cloud Shell。

這會設定 kubectl 結構定義,讓您可以與叢集互動。如要驗證設定,請執行下列指令:

kubectl get nodes -o wide

您應該會看到狀態顯示為「Ready」的節點,以及節點存在時間、版本、外部 IP 位址、OS 映像檔、核心版本和容器執行階段的其他資訊。

設定叢集,在已啟用 gcloud 的節點集區中安裝 Nvidia 驅動程式

接著,我們會為叢集套用 daemonset,這會在任何已啟用 GPU 的叢集節點上安裝 Nvidia 驅動程式:

kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/nvidia-driver-installer/cos/daemonset-preloaded.yaml

接著執行下列指令,讓 KFP 元件有權建立新的 Kubernetes 資源:

kubectl create clusterrolebinding sa-admin --clusterrole=cluster-admin --serviceaccount=kubeflow:pipeline-runner

建立 GPU 節點集區

接著,請設定 GPU 節點集區的規模,大小為 1:

gcloud container node-pools create gpu-pool \
    --cluster=${CLUSTER_NAME} \
    --zone ${ZONE} \
    --num-nodes=1 \
    --machine-type n1-highmem-8 \
    --scopes cloud-platform --verbosity error \
    --accelerator=type=nvidia-tesla-k80,count=1

3. 透過「管道」資訊主頁執行管道

開啟「管道」資訊主頁

前往 Cloud 控制台中的「Pipelines」面板 (如果尚未進入該面板)。然後按一下「開啟管道資訊主頁」安裝好,然後按一下左側選單列中的「Pipelines」。如果系統顯示載入錯誤,請重新整理分頁。您應該會看到類似下方的新網頁:

7bb5a9cf0773c3bc.png

管道說明

您要執行的管道包含幾個步驟 (詳情請參閱本程式碼研究室的附錄):

  1. 現有的模型查核點會複製到您的值區。
  2. Tensor2Tensor 模型是使用預先處理的資料訓練而成,
  • 訓練會從第一個步驟複製的現有模型查核點開始,然後訓練數百個步驟。(在本程式碼研究室中,訓練完全可能需要較長時間)。
  • 訓練完成後,管道步驟會將模型匯出成適合 TensorFlow Serving 提供的模型。
  1. 系統會使用該模型部署 TensorFlow 供應執行個體。
  2. 系統會啟動網頁應用程式,以便與提供的模型互動來擷取預測結果。

下載並編譯管道

本節將說明如何編譯管道定義。首先需要安裝 KFP SDK。在 Cloud Shell 中執行下列指令:

pip3 install -U kfp

如要下載管道定義檔案,請透過 Cloud Shell 執行下列指令:

curl -O https://raw.githubusercontent.com/amygdala/kubeflow-examples/ghsumm/github_issue_summarization/pipelines/example_pipelines/gh_summ_hosted_kfp.py

接著,按照以下方式執行編譯管道定義檔:

python3 gh_summ_hosted_kfp.py

結果中會顯示 gh_summ_hosted_kfp.py.tar.gz 檔案。

上傳已編譯的管道

在 Kubeflow Pipelines 網頁版 UI 中,按一下「上傳管道」並選取「透過網址匯入」。複製並貼上以下網址,這會指向您剛編譯的同一個管道。(這是透過 Cloud Shell 上傳檔案的額外步驟,因此我們採用了快速指令)。

https://storage.googleapis.com/aju-dev-demos-codelabs/KF/compiled_pipelines/gh_summ_hosted_kfp.py.tar.gz

為管道命名,例如 gh_summ

867fdbe248d13bab.png

執行管道

按一下清單中的已上傳管道 (查看管道的靜態圖表),然後點選「建立實驗」,使用管道建立新的實驗。實驗可將語意相關執行作業分組。

d4b5b1a043d32d4a.png

為實驗命名 (例如與管道相同的名稱 gh_summ),然後點選「下一步」建立實驗。

d9f7d2177efad53.png

畫面上會出現一個頁面,您可以在該頁面輸入「Run」的參數並啟動。

建議您在 Cloud Shell 中執行下列指令,以便填入參數。

gcloud config get-value project
echo "gs://${BUCKET_NAME}/codelab"

系統會自動填入執行作業名稱,但您也可以視需求輸入其他名稱。

接著填寫三個參數欄位:

  • project
  • (選填) github-token
  • working-dir

針對工作目錄,請在您建立的 GCS 值區底下輸入一些路徑。加入「gs://」前置字串。在 github-token 欄位中輸入您先前選擇性產生的符記;如未產生符記,預留位置字串則維持原樣。

8676afba6fd32ac1.png

填妥欄位後,點選「Start」,然後點選列出的執行作業,即可查看詳細資料。在特定管道步驟執行時,您可以按一下該步驟取得更多相關資訊,包括查看其 pod 記錄檔。(即使叢集節點已中斷,您也可以透過 Cloud Logging (Stackdriver) 記錄檔的連結查看管道步驟的記錄檔)。

db2dc819ac0f5c1.png

查看管道定義

管道執行期間,您可能會想進一步瞭解管道的建構方式和執行方式。詳情請參閱程式碼研究室的附錄一節。

在 TensorBoard 中查看模型訓練資訊

訓練步驟完成後,請選取其「Visualizations」分頁標籤,按一下藍色的「Start TensorBoard」按鈕,然後在準備就緒時按一下「Open TensorBoard」

6cb511540a64b9e5.png

d55eb03c4d04f64d.png

探索構件和執行作業資訊主頁

Kubeflow Pipelines 會在管道執行期間自動記錄管道步驟的中繼資料。系統會記錄「Artifact」Artifact和「Execution」Artifact資訊。如要進一步探索,請在資訊主頁的左側導覽列中點選這些項目。

3002c4055cc8960b.png

如果是 Artifacts,你可以查看「總覽」面板和「歷程探索工具」面板。

7885776e899d1183.png

40c4f7e5b6545dec.png

啟動管道建立的網頁應用程式,並進行一些預測

管道的最後一個步驟會部署網頁應用程式,也就是提供 UI,用於查詢透過 TF Serving 提供的已訓練模型,以便進行預測。

管道完成後,請透過通訊埠轉送功能連線至網頁應用程式服務,藉此連線至網頁應用程式 (在本程式碼研究室中,網頁應用程式服務並未設為具有外部端點,因此我們才採用通訊埠轉送)。

在 Cloud Shell 中執行下列指令,來找出服務名稱:

kubectl get services

在清單中找出服務名稱:ghsumm-*-webappsvc

接著,在 Cloud Shell 中,透過通訊埠轉送功能至該服務,變更下列指令以使用 webappsvc 的名稱

kubectl port-forward svc/ghsumm-xxxxx-webappsvc 8080:80

通訊埠轉送功能執行後,按一下「預覽」圖示,然後在下拉式選單中點選「透過以下通訊埠預覽:8080」。

65572bb3b12627cc.png

新分頁應會顯示類似下方的頁面:

902ad2d555281508.png

按一下「Populate Random Issue」按鈕擷取一段文字,按一下「Generate TItle」,呼叫經過訓練的模型,並顯示預測結果。

b7c39ce51ee603bd.png

如果管道參數包含有效的 GitHub 權杖,您也可以在第二個欄位中輸入 GitHub 網址,然後按一下「產生標題」。如果您「尚未」設定有效的 GitHub 符記,請只使用「填入隨機問題」] 欄位。

4. 從 AI 平台筆記本執行管道

您也可以運用 KFP SDK,從 Jupyter 筆記本中以互動方式定義及執行 Kubeflow Pipelines。這個程式碼研究室將使用 AI 平台筆記本,因此非常簡單。

建立筆記本執行個體

我們將使用 API,透過 Cloud Shell 建立筆記本執行個體。(您也可以透過 Cloud 控制台建立筆記本)。詳情請參閱說明文件)。

在 Cloud Shell 中設定下列環境變數:

export INSTANCE_NAME="kfp-ghsumm"
export VM_IMAGE_PROJECT="deeplearning-platform-release"
export VM_IMAGE_FAMILY="tf2-2-3-cpu"
export MACHINE_TYPE="n1-standard-4"
export LOCATION="us-central1-c"

然後,透過 Cloud Shell 執行下列指令,建立筆記本執行個體:

gcloud beta notebooks instances create $INSTANCE_NAME \
  --vm-image-project=$VM_IMAGE_PROJECT \
  --vm-image-family=$VM_IMAGE_FAMILY \
  --machine-type=$MACHINE_TYPE --location=$LOCATION

首次執行這個指令時,系統可能會請您為專案啟用 notebooks API。回覆「y」如果有需要,

幾分鐘後,筆記本伺服器就會啟動並開始運作。您可以在 Cloud 控制台列出筆記本執行個體。

206adf3905413dfa.png

上傳程式碼研究室筆記本

建立筆記本執行個體後,請按一下這個連結,上傳程式碼研究室的 Jupyter 筆記本。選取要使用的筆記本執行個體。筆記本隨即會自動開啟。

執行筆記本

在研究室其餘部分,請按照筆記本中的指示操作。請注意,「設定」筆記本的部分內容,您必須先自行填入值,才能執行筆記本的其餘部分。

(如果您使用自己的專案,別忘了返回本研究室的「清除」部分)。

5. 清除所用資源

如果您使用臨時程式碼研究室帳戶,則不需要採取此做法,但如果您使用自己的專案,建議移除管道安裝作業和筆記本服務。

移除管道 GKE 叢集

您可以透過 Cloud 控制台刪除管道叢集。(如果您想要重複使用 GKE 叢集,可選擇只刪除管道安裝)。

刪除 AI 筆記本執行個體

如果執行「Notebook」當中的一部分,您可以透過 Cloud 控制台刪除停止筆記本執行個體。

選用:移除 GitHub 權杖

前往 https://github.com/settings/tokens 並移除產生的權杖。

6. 附錄

查看程式碼

定義管道

本程式碼研究室使用的管道請參閱這裡的定義。

以下將說明定義方式,以及元件 (步驟) 的定義。以下將說明部分重點資訊,但如要進一步瞭解詳情,請參閱說明文件

Kubeflow 管道步驟是以容器為基礎。建構管道時,您可以使用預先建構的元件和已建構的容器映像檔,也可以建構自己的元件。在本程式碼研究室中,我們自行建構。

這四個步驟是根據可重複使用的元件定義,您可以透過其元件定義檔案存取。在第一個程式碼片段中,我們透過網址存取這些元件定義檔案,並使用這些定義建立「作業」我們會使用這組指令來建立管道步驟

import kfp.dsl as dsl
import kfp.gcp as gcp
import kfp.components as comp

...

copydata_op = comp.load_component_from_url(
  'https://raw.githubusercontent.com/kubeflow/examples/master/github_issue_summarization/pipelines/components/t2t/datacopy_component.yaml'
  )

train_op = comp.load_component_from_url(
  'https://raw.githubusercontent.com/kubeflow/examples/master/github_issue_summarization/pipelines/components/t2t/train_component.yaml'
  )

以下是訓練運算的其中一項元件定義,採用 yaml 格式。您可以看到系統已定義其輸入、輸出、容器映像檔和容器進入點引數。

name: Train T2T model
description: |
  A Kubeflow Pipeline component to train a Tensor2Tensor
  model
metadata:
  labels:
    add-pod-env: 'true'
inputs:
  - name: train_steps
    description: '...'
    type: Integer
    default: 2019300
  - name: data_dir
    description: '...'
    type: GCSPath
  - name: model_dir
    description: '...'
    type: GCSPath
  - name: action
    description: '...'
    type: String
  - name: deploy_webapp
    description: '...'
    type: String
outputs:
  - name: launch_server
    description: '...'
    type: String
  - name: train_output_path
    description: '...'
    type: GCSPath
  - name: MLPipeline UI metadata
    type: UI metadata
implementation:
  container:
    image: gcr.io/google-samples/ml-pipeline-t2ttrain:v3ap
    args: [
      --data-dir, {inputValue: data_dir},
      --action, {inputValue: action},
      --model-dir, {inputValue: model_dir},
      --train-steps, {inputValue: train_steps},
      --deploy-webapp, {inputValue: deploy_webapp},
      --train-output-path, {outputPath: train_output_path}
    ]
    env:
      KFP_POD_NAME: "{{pod.name}}"
    fileOutputs:
      launch_server: /tmp/output
      MLPipeline UI metadata: /mlpipeline-ui-metadata.json

您也可以透過 dsl.ContainerOp 建構函式定義管道步驟,如下所示。

以下是大量管道定義。定義管道輸入 (和預設值)。接著定義管道步驟。大多數的情況下,我們要使用「Ops」我們還定義了「放送」透過 ContainerOp 內嵌步驟,直接指定容器映像檔和進入點引數。

您可以看到 trainlog_modelserve 步驟正在存取先前步驟的輸出內容,做為輸入內容。如需更多說明,請參閱這裡

@dsl.pipeline(
 name='Github issue summarization',
 description='Demonstrate Tensor2Tensor-based training and TF-Serving'
)
def gh_summ(  #pylint: disable=unused-argument
 train_steps: 'Integer' = 2019300,
 project: str = 'YOUR_PROJECT_HERE',
 github_token: str = 'YOUR_GITHUB_TOKEN_HERE',
 working_dir: 'GCSPath' = 'gs://YOUR_GCS_DIR_HERE',
 checkpoint_dir: 'GCSPath' = 'gs://aju-dev-demos-codelabs/kubecon/model_output_tbase.bak2019000/',
 deploy_webapp: str = 'true',
 data_dir: 'GCSPath' = 'gs://aju-dev-demos-codelabs/kubecon/t2t_data_gh_all/'
 ):


 copydata = copydata_op(
   data_dir=data_dir,
   checkpoint_dir=checkpoint_dir,
   model_dir='%s/%s/model_output' % (working_dir, dsl.RUN_ID_PLACEHOLDER),
   action=COPY_ACTION,
   )


 train = train_op(
   data_dir=data_dir,
   model_dir=copydata.outputs['copy_output_path'],
   action=TRAIN_ACTION, train_steps=train_steps,
   deploy_webapp=deploy_webapp
   )

 serve = dsl.ContainerOp(
     name='serve',
     image='gcr.io/google-samples/ml-pipeline-kubeflow-tfserve:v6',
     arguments=["--model_name", 'ghsumm-%s' % (dsl.RUN_ID_PLACEHOLDER,),
         "--model_path", train.outputs['train_output_path']
         ]
     )

 train.set_gpu_limit(1)

請注意,我們需要使用「訓練」在至少具備 1 個 GPU 的叢集節點上執行。

  train.set_gpu_limit(1)

管道中的最後一個步驟 (也定義為內嵌) 是條件式,會在「serve」後執行但前提是訓練步驟 launch_server 輸出為「true」字串時,才算完成。並啟動「預測網頁應用程式」,用於要求訓練過的 T2T 模型提供摘要。

 with dsl.Condition(train.outputs['launch_server'] == 'true'):
   webapp = dsl.ContainerOp(
       name='webapp',
       image='gcr.io/google-samples/ml-pipeline-webapp-launcher:v1',
       arguments=["--model_name", 'ghsumm-%s' % (dsl.RUN_ID_PLACEHOLDER,),
           "--github_token", github_token]

       )
   webapp.after(serve)

元件容器映像檔定義

Kubeflow Pipeline 說明文件會說明一些建構元件的最佳做法。在這個過程中,您必須定義並建構容器映像檔。您可以在這裡查看本程式碼研究室管道的元件步驟。Dockerfile 定義位於 containers 子目錄中,例如這裡

使用具備 GPU 的先佔 VM 進行訓練

先佔 VM 是效期最長 24 小時的 Compute Engine VM 執行個體,不提供可用性保證。先佔 VM 的定價比標準 Compute Engine VM 低。

透過 Google Kubernetes Engine (GKE),您可以輕鬆設定使用先佔 VM 的叢集或節點集區。您可以將 GPU 附加至先佔執行個體來設定這類節點集區。這些功能的運作方式與支援 GPU 的一般節點相同,但 GPU 只會在執行個體的生命週期內保留下來。

如要為叢集設定支援 GPU 的先佔節點集區,您可以執行下列指令,使用叢集名稱和可用區編輯下列指令,並視需求調整加速器類型和計數。您可以選擇定義節點集區,以便依據目前的工作負載自動調度資源。

gcloud container node-pools create preemptible-gpu-pool \
    --cluster=<your-cluster-name> \
    --zone <your-cluster-zone> \
    --enable-autoscaling --max-nodes=4 --min-nodes=0 \
    --machine-type n1-highmem-8 \
    --preemptible \
    --node-taints=preemptible=true:NoSchedule \
    --scopes cloud-platform --verbosity error \
    --accelerator=type=nvidia-tesla-k80,count=4

您也可以透過 Cloud 控制台設定節點集區。

定義使用先佔 GKE 節點的 Kubeflow 管道

如果您是在 GKE 上執行 Kubeflow,您現在可以輕鬆定義並執行 Kubeflow 管道,讓一或多個管道步驟 (元件) 在先佔節點上執行,進而降低執行工作的費用。使用先佔 VM 提供正確結果時,您識別為先佔的步驟應為冪等 (也就是說,如果您多次執行某個步驟,結果都會相同) 或應執行查核點,以便在步驟中斷時繼續執行。

定義 Kubeflow 管道時,您可以透過下列方式修改運算,表明特定步驟應在先佔節點上執行:

your_pipelines_op.apply(gcp.use_preemptible_nodepool())

詳情請參閱說明文件

如果節點遭到先佔,您也必須多次重試步驟。您可以按照以下方式進行 — 這裡是指定 5 次重試。

your_pipelines_op.set_gpu_limit(1).apply(gcp.use_preemptible_nodepool()).set_retry(5)

請嘗試編輯我們在本程式碼研究室中使用的 Kubeflow 管道,以在先佔 VM 上執行訓練步驟

變更管道規格中的下列行,以便額外使用先佔節點集區 (請確定您已按照上述方式建立),然後重試 5 次:

  train.set_gpu_limit(1)

接著,重新編譯管道、上傳新版本 (設定新名稱),然後執行新版本的管道。