Help us understand the problem. What is going on with this article?

Kubeflow PipelinesでTensorFlow Extendedを動かしてみた

More than 1 year has passed since last update.

この記事はTensorFlow Advent Calendar2018年 3日目の記事です。
今年のAdvent CalendarはKubeflow Pipeliensについて書こうと思います。
タイトルでは「動かしてみた」と言っていますが、全部を動かすことは出来ませんでした。ちゃんと動けばもう少し詳細まで見て行きたかったのですが、ひとまずやってみたところまで記事にまとめましたので、アップデートあれば追記していきます。

機械学習システムの実環境へのデプロイ&サービング

機械学習が普及した2018年ですが、PoC(Proof of Concept)を超えて実運用まで漕ぎ着けている事例が増えてきたとはいえ、実システムに組み込んで運用する場合のハードルは依然高いように見えます。 その理由としては、2014年にGoogleから出された論文Machine Learning: The High Interest Credit Card of Technical Debt でいくつか課題が挙げられており、それらの一つの解決策として機械学習プラットフォームであるTensorFlow Extended(TFX)が提案されています。

現在、OSSとして公開されているTFXはそれぞのコンポーネントがバラバラであり、機械学習のワークフロー全体としては管理しづらいものでした。そこで機械学習のワークフロー全体をEndToEndで管理できるようにするためのコンポーネントがkubeflow pipelineです。以前から機械学習システム構築するためのツールキットであるKubeflowにTFXはその一部が取り込まれていましたが、今年11月に発表されたKubeflow pipelinesでワークフローの管理が洗練されより使いやすくなったように感じます。

2017年末にkubeflowが出てきてから一年、kubeflow自体はまだ0.4と発展途上であり、公式のexamplesもまともに動かなかったりします。このKubeflow Pipelinesも例に漏れずexampleを動かすのさえ苦行ではありますが、ユーザーが増えて知見が貯まることを願ってご紹介をしようと思います。

Kubeflow Pipelines

kubeflow pipelinesはKubeflowの新しいコンポーネントであり、機械学習システムのワークフローを管理できるツールです。ワークフローの定義はPythonをベースにしたDSLで記述し、その中でTFXのコンポーネントを活用する事ができます。また、ワークフローごとに異なる設定をして実験(Experiment)を実施したログが残せたり、ワークフローがちゃんと動いているかモニタリングができるようになっていたりと、機会学習システムのモデリング以外に必要な機能が整備されています。ワークフローマネジメント自体はKubeflowのCoreComponentである、Argoが動いているらしいですが、UIが整ったことでやっと統一感があるpipeline管理ツールが出てきたなというところです。

Kubeflow Pipelines examples

今回はkubeflowのslackで紹介されていたこのexamplesを試してみます。GKEを使ってBigQueryのChicago taxiのデータを用いて、TFXのコンポーネントを使って機械学習のワークフローを定義し、サービングまで機械学習モデルをデプロイしていく良いチュートリアルです。

基本的にはREADME.mdに書かれている通りに動かしますが、そのままではエラーが出る部分などあるのでworkaroundも示しながら進めたいと思います。

  1. GCP環境のセットアップ
  2. Kubernetes Engine (GKE) クラスタの準備
  3. Kubeflow Pipelinesのインストール
  4. Examplesを試す

GCP環境のセットアップ

まずはGCPの環境を整えます。大まかな手順としては下記です。
- GCPプロジェクトを作る
- 必要なAPIをenableにする
- Cloud Machine Learning Engine、Kubernetes Engine、オプションでTFTやTFMAをDataflow上で動かしたり、データソースをcsvファイルからBigQueryに変えるなどする場合はそれぞれEnableする必要があります
- gcloud sdkをインストールする、もしくはcloud shellを使う
- GCSのバケットを用意する
- Backet名はXXXにしてあります。

Kubernetes Engine (GKE) クラスタの準備

このREADME.mdにGKEクラスタを作成します。

gcloud beta container --project <PROJECT_NAME> clusters create "kubeflow-pipelines" --zone "us-central1-a" --username "admin" --cluster-version "1.9.7-gke.11" --machine-type "custom-8-40960" --image-type "COS" --disk-type "pd-standard" --disk-size "100" --scopes "https://www.googleapis.com/auth/cloud-platform" --num-nodes "4" --enable-cloud-logging --enable-cloud-monitoring --no-enable-ip-alias --network "projects/<PROJECT_NAME>/global/networks/default" --subnetwork "projects/<PROJECT_NAME>/regions/us-central1/subnetworks/default" --addons HorizontalPodAutoscaling,HttpLoadBalancing,KubernetesDashboard --enable-autoupgrade --enable-autorepair

PROJECT_NAMEには使っているGCPのプロジェクト名を入れて下さい。次に作ったクラスタをコンテキストに割り当て、ClusterRoleリソースを作成します。

> gcloud container clusters get-credentials kubeflow-pipelines --zone us-central1-a --project <PROJECT_NAME>
Fetching cluster endpoint and auth data.
kubeconfig entry generated for kubeflow-pipelines.
> kubectl create clusterrolebinding ml-pipeline-admin-binding --clusterrole=cluster-admin --user=$(gcloud config get-value account)
clusterrolebinding.rbac.authorization.k8s.io "ml-pipeline-admin-binding" created
> kubectl create clusterrolebinding sa-admin --clusterrole=cluster-admin --serviceaccount=kubeflow:pipeline-runner
clusterrolebinding.rbac.authorization.k8s.io "sa-admin" created

Kubeflow Pipelinesのインストール

Kubeflowのこのページの中のDeploy Kubeflow Pipelinesに従います。

Kubeflow PipelinesをGKEクラスタにデプロイします。

> PIPELINE_VERSION=0.1.2
> kubectl create -f https://storage.googleapis.com/ml-pipeline/release/$PIPELINE_VERSION/bootstrapper.yaml
clusterrole.rbac.authorization.k8s.io "mlpipeline-deploy-admin" created
clusterrolebinding.rbac.authorization.k8s.io "mlpipeline-admin-role-binding" created
job.batch "deploy-ml-pipeline-qqk9j" created
 > kubectl get job
NAME                       DESIRED   SUCCESSFUL   AGE
deploy-ml-pipeline-qqk9j   1         1            7m
> kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.7.240.1   <none>        443/TCP   18m

Kubeflow Pipelines UIにローカルのブラウザからGKE上のpod内のコンテナにアクセスできるようにポートフォワードの設定をしておきます。

> export NAMESPACE=kubeflow
> kubectl port-forward -n ${NAMESPACE}  `kubectl get pods -n ${NAMESPACE} --selector=service=ambassador -o jsonpath='{.items[0].metadata.name}'` 8080:80

この状態でCloud Shellから"Web Preview"するとKubeflowのとても簡素なダッシュボードに飛びます。

kubeflowトップ画スクショ.png

またそのURLの末尾に/pipelinesを追加することでKubeflow pipelinesのUIに移れます。

workflow1.png

以上でREADME.mdに記載されているExamplesのための準備は終わりました。しかし、これ以降のExamplesを動かすためにもう少し準備をします。Examplesを完走するためには、下記2点が必要です。

  • Jupyter Notebookへ設定を追加する
  • 必要なJupyter extensionをインストールする

Jupyter Notebookへ設定を追加する

GKE上にJupyter Notebookのサービスは立ち上がるのですが、新しいnotebookを起動できません。しかしこのissueを参考にしてFixすることができました。

まずはJupyterHubに入ります。サインインにUsernameとPasswordを求められますが、何を使っても入れます。私はGCPのアカウントを使いました。まずはイメージを選択しSpawnします。今回はgcr.io/kubeflow-images-public/tensorflow-1.10.1-notebook-cpu:v0.3.1を選択しました。立ち上がったら、Jupyter NotebookのPodに入り、jupyterのコンフィグファイルに設定を追記します。

# Jupyter pod nameを調べます `jupyter-<USER>` (Here user is 'admin')
> kubectl get pods -n kubeflow

> kubectl exec -it -n kubeflow jupyter-<USER> bash

# 設定ファイルを変更します。
> jovyan@jupyter-admin:~$ vim .jupyter/jupyter_notebook_config.py

jupyter設定変更.png

上記のようにc.NotebookApp.allow_origin='*'を追記します。そしてPodを再起動。

> jovyan@jupyter-admin:~$ ps -auxw
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
jovyan       1  0.0  0.0   4528   820 ?        Ss   12:44   0:00 tini -- start-singleuser.sh --ip="0.0.0.0" --port=8888 --allow-root
jovyan       5  0.1  0.8 292128 62168 ?        Sl   12:44   0:01 /opt/conda/bin/python /opt/conda/bin/jupyterhub-singleuser --ip="0.0.0.0" --port=8888 --allow-root
jovyan      33  0.0  0.0  20316  4108 ?        Ss   12:52   0:00 bash
jovyan      41  0.0  0.0  36080  3300 ?        R+   12:53   0:00 ps -auxw

> jovyan@jupyter-admin:~$ kill 1
> jovyan@jupyter-admin:~$ command terminated with exit code 137
> export NAMESPACE=kubeflow
> kubectl port-forward -n ${NAMESPACE}  `kubectl get pods -n ${NAMESPACE} --selector=service=ambassador -o jsonpath='{.items[0].metadata.name}'` 8080:80

これでnotebookを立ち上げることができるようになりました。

Juptyter notebookでTFMAを可視化するための extensionのインストール

TFMAはインタラクティブにデータをスライスし、その結果をjupyter notebook上で可視化することができます。しかし後述するTFMAのパートでうまくレンダリングできませんでした。 こちらを参考にレンダリングに必要なExtensionを入れましたが下記のようなエラーが出ています。

> jupyter nbextension enable --py widgetsnbextension
> jupyter nbextension install --py --symlink tensorflow_model_analysis
OSError: [Errno 13] Permission denied: '/usr/local/share/jupyter/nbextensions'
> jupyter nbextension enable --py tensorflow_model_analysis

きっとExamplesのイメージもすでにエクステンションを入れた状態で作られているとは思いますが、うまく入れられていないのでレンダリングできなかったのでしょうね。解決しましたら追記します!

Running the examples

Kubeflow Pipelineに機械学習のPipelineを定義していきます。Kubeflow pipelinesのUIに入るとすでにいくつかサンプルのPipelineが定義されています。

ワークフローはここにあるように、DSLで書かれた.pyファイルをコンパイルして、Kubeflow PipelinesのUIにアップロードすることでデプロイできます。
現在、サンプルとして挙げられているものはそれぞれ、ここのSampleにあげられているもののようです。特にML-TFXはExample pipeline that does classification with model analysis based on a public tax cab BigQuery dataset.とあるように、workflowと基本的には同じっぽいです。(ちなみに、試しにやってみたら途中でエラー吐くので諦めました)。

workflowをやってみる

ここではすでにUI上にあるPipelineではなくて、新しくPipelineをアップロードして実行するようです。まずはDSLで書かれたスクリプトをコンパイルします。手順はこちらです。

> cd ~/code-snippets/ml/kubeflow-pipelines/samples/kubeflow-tf
> python3 workflow1.py
> ls
README.md  workflow1.py  workflow1.py.tar.gz  workflow2.py

Kubeflow pipelines UIにこのworkflow1.py.tar.gzをアップロードするとpipelineができます。

workflow1.png

UIからExperimentsを設定し、Runさせます。
このときpreprocess-modetfma-modelocalで実行していますが、ここをcloudにするとDataflowで動作します。

この後ワークフローが走ります。UI眺めているだけではあまり実感無いですが、CSVでGCSに保存されていたデータがTFTで処理され機械学習モデルに学習され、MLEngineにデプロイされてサービングされてます。

Screen Shot 2018-11-29 at 21.53.08.png

trainのblockからはTensorboardのダッシュボードに飛ぶこともできて便利ですね。

tfboard.png

tfboard2.png

TensorFlow Model Analysisでモデル解析

ワークフローが走り終わるとJupyterNotebook上で学習されたモデルについての解析ができます。JupyterHubにサインインします。IDもパスワードはなんでも入れますが、GCPのアカウントを使うようにしました。解析にはこのtfma_expers.ipynbを使います。OUTPUT_PATH_PREFIX = 'gs://<YOUR_BUCKET_PATH>/<WORKFLOW_NAME>/'のはクラスタ立てるときに指定したバケット名、はCloud ConsoleでGoogle Strageの当該バケットを見に行くとディレクトリができているのでそれを使います。現状、上述したエラーからレンダリングがうまくいっていないので全く意味をなしてませんが、一応セルの実行はできているようです。

TFMAレンダリング.png

機械学習モデルのサービング

Workflow1の方はデプロイがうまくいきませんでしたが、workflow2の方はGoogle ML Engineにデプロイされて、サービングできるようになってました。

cmleスクショ.png

まとめ

Pipeline上で使うモデルやデータの管理など、もう少しリッチな機能が欲しい感じですが、TFXをうまく使うための素晴らしいツールだなと感じています。機械学習モデリングの後、実運用まで持っていくための試行錯誤はまだまだ続きそうですが、KubeflowやTFXなど便利なツールが普及して知見が貯まり、そのハードルがどんどん下がっていけば良いなと思いました。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away