資料中で出てくるサンプルには次の URL からアクセスできます
GitHub: https://github.com/reproio/lab_sample_pipelines/tree/main/kfp 解説ブログ: https://tech.repro.io/entry/2021/06/22/125113 Colab : https://gist.github.com/AseiSugiyama/d189a43f656a3313837e820bc54f873b
Vertex Pipelines ではじめるサーバーレス機械学習パイプラインAsei Sugiyama
View Slide
tl;dr機械学習パイプラインは機械学習で行われる一連の処理をパイプラインとして実行できるよう定義したものVertex Pipelines は機械学習パイプラインをサーバーレスに実行するGCP のサービスで、パイプラインは Kubeflow Pipelines SDK を用いてPython で記述するサンプルとして reproio/lab_sample_pipelines を用意したので触ってみてください
自己紹介杉山 阿聖 (@K_Ryuichirou)Software Engineer @ Repro機械学習基盤の設計構築Advisor @ moneyforwardTensorFlow User GroupTFX & KubeflowPipeline機械学習図鑑 共著
TOC機械学習パイプライン Kubeflow Pipeline SDK を用いたパイプライン構築Lab Sample Pipeline の紹介
機械学習パイプラインとは機械学習で行われる一連の処理をパイプラインとして並べたもの典型的にはデータ取得・前処理・訓練・デプロイが含まれるO'Reilly Japan - 入門 機械学習パイプライン
機械学習パイプラインに求められる要件オーケストレーションパイプラインを構成するタスクと、実行時のリソースの管理コードとデータの管理モデルの振る舞いを決めるものを同時に管理可視化入出力と合わせてそれを可視化したもの(典型的にはグラフ)を管理
機械学習はとにかく複雑Machine Learning: The High Interest Credit Card of Technical Debt – Google Research
TFX (TensorFlow Extended)TFX: A TensorFlow-Based Production-Scale Machine Learning Platform – Google Research
KubeflowKubernetes 上で機械学習のワークフローを実行するプロジェクトGoogle 社内の機械学習基盤 TFX のOSS 実装を目指して開始 (今は独自路線)
KubeflowPipelinesKubeflow のコンポーネントのひとつ機械学習パイプラインを実行
Vertex Pipelines機械学習パイプラインをサーバーレスに実行する GCPのサービスKubeflow Pipelines と同じパイプラインを実行
TOC機械学習パイプラインKubeflow Pipeline SDK を用いたパイプライン構築 Lab Sample Pipeline の紹介
Kubeflow Pipeline SDK を用いたパイプライン構築Hello, worldコンポーネントの実行順序の定義GPU の利用
Hello, worlddef hello_world(text: str):print(text)hello_world("Hello, world") # Hello, worldこの関数を実行する機械学習パイプラインをこれから作成
Python の関数からコンポーネントの作成from kfp.v2 import componentshw_op = components.component_factory.create_component_from_func(hello_world,output_component_file="hw.yaml")関数 hello_worldを実行するコンポーネントを準備hw_opはコンポーネントを生成するファクトリ関数hw.yamlについては後ほど
@componentデコレーターfrom kfp.v2.dsl import component@component(output_component_file='hw.yaml')def hw_op(text: str):print(text)同様のことを @componentデコレーターを用いると短く記述可能
パイプラインの定義from kfp.v2 import dslGCS_PIPELINE_ROOT = "gs://your-gcs-bucket/"@dsl.pipeline(name="hello-world",description="A simple intro pipeline",pipeline_root=f"{GCS_PIPELINE_ROOT}helloworld/")def hello_world_pipeline(text: str = "hi there"):hello_world_task = hw_op(text)pipeline_rootはパイプラインの生成物を保管する先のバケット
コンパイルfrom kfp.v2 import compilercompiler.Compiler().compile(pipeline_func=hello_world_pipeline,package_path='hello-world-pipeline.json',)パイプラインを Python の関数から JSON に変換生成される JSON のスキーマは PipelineSpec と呼ばれる
実行結果hello_worldコンポーネントだけのパイプライン実行したことがあるとキャッシュされた値が返る
hw.yaml中身は右の通りComponentSpec と呼ばれるスキーマで記述
ComponentSpec (抜粋)inputs:- {name: text, type: String} #入力 textの定義# outputs: #出力は outputsとして定義implementation:container:image: python:3.7 #動かすコンテナの指定command: #コンテナで動かすコマンドの指定- sh- -ec...args: #コンテナに与える引数の指定- --text- {inputValue: text} #パイプラインで与えた値が入る
コンポーネントの実行順序の定義次の 2 つのどちらも可能入出力の依存関係に基づく実行順の定義 明示的な実行順の定義
Producer / Consumer Pipeline (1/2)@dsl.componentdef echo(text: str) -> str:return text@dsl.pipeline(name="producer-consumer-pipeline",pipeline_root=f"{GCS_PIPELINE_ROOT}producer-consumer/")def producer_consumer_pipeline(text: str = "hi there"):producer = echo(text)consumer = echo(producer.output) # producerの出力を利用
Producer / ConsumerPipeline (2/2)実行結果は右の通り入出力の依存関係に基づき、実行順が定義されるキャッシュが利用可能
明示的な実行順の定義@dsl.pipeline(name="producer-consumer",pipeline_root=f"{GCS_PIPELINE_ROOT}producer-consumer/")def use_after_pipeline(text: str = "hi there"):producer = echo(text)consumer = echo(text).after(producer) # producerのあとに実行afterを使うことで明示的に実行順を定義可能キャッシュは必ずしも担保されないので注意
GPU の利用@dsl.pipeline(name="hello-world-with-gpu",pipeline_root=f"{GCS_PIPELINE_ROOT}helloworld/")def hello_world_pipeline_with_gpu(text: str = "hi accelerator"):hello_world_task = (hw_op(text).add_node_selector_constraint( # GPUの追加を宣言'cloud.google.com/gke-accelerator', #利用できる GPUの種類は'nvidia-tesla-k80') # Custom Trainingに同じ.set_gpu_limit(1))コンポーネントで CPU やメモリ、 GPU の指定が可能確保に失敗することもあるので注意
TOC機械学習パイプラインKubeflow Pipeline SDK を用いたパイプライン構築Lab Sample Pipeline の紹介
Lab Sample Pipeline の紹介パイプライン概要ディレクトリ構造コンポーネントの実装と単体テストComponentSpec の記述例パイプラインの実装Metadata
パイプライン概要reproio/lab_sample_pipelinespenguin dataset のサブセットを用いた機械学習パイプライン機械学習ライブラリには scikit-learnを利用前処理・訓練・評価を含むシンプルなパイプラインVertex Pipelines で動作
ディレクトリ構造% tree ..├── README.md├── components│ ├── data_generator #コンポーネントごとのディレクトリ│ │ ├── Dockerfile #コンポーネントの Dockerfile│ │ ├── README.md #コンポーネントの仕様│ │ ├── data_generator.yaml # ComponentSpec│ │ ├── src #ソースコード一式│ │ └── tests #テストコード一式│ ...└── pipeline.py #パイプラインの定義Kubeflow Pipelines のドキュメントと同じ
コンポーネントの実装if __name__ == "__main__":#引数をパースartifacts = Artifacts.from_args()# main関数で処理train_data, eval_data = main(artifacts.component_arguments)#与えられた出力先に CSVファイルを保存write_csv(artifacts.output_destinations.train_data_path,train_data)write_csv(artifacts.output_destinations.eval_data_path,eval_data)コンポーネントは普通の CLI アプリケーション
単体テストimport pytestclass TestTrainModel:def test_train_model_from_small_dataset(self):source = np.array([(0, 1, 2, 3, 4), (1, 2, 3, 4, 5), (0, 3, 4, 5, 6)],...model = trainer.train(source, "species_xf")assert model is not Noneassert model.predict([[1, 2, 3, 4]]) == [0]pytestで単体テストを実装経験上、可能な限り単体テストを書くべき
ComponentSpec (data-generator)name: data_generatoroutputs:- { name: train_data_path, type: { GCPPath: { data_type: CSV } } }- { name: eval_data_path, type: { GCPPath: { data_type: CSV } } }implementation:container:image: us.gcr.io/your-project-id/kfp-sample-data-generator:v0.0.0args:- { outputPath: train_data_path }- { outputPath: eval_data_path }kfp1.8.4 では commandを書かなくてもコンパイルできる将来的には commandが必須に
パイプラインの実装 (一部)@kfp.dsl.pipeline(name=PIPELINE_NAME,pipeline_root=f"gs://{GCP_GCS_PIPELINE_ROOT}/",)def kfp_sample_pipeline(suffix: str = "_xf"):data_generator = _data_generator_op()transform = _transform_op(train_data_path=data_generator.outputs[GeneratedData.TrainData.value],eval_data_path=data_generator.outputs[GeneratedData.EvalData.value],suffix=suffix,)出力が複数あるときには outputsに出力変数名を渡す
実行結果Componentが縦に並ぶそれぞれの入出力も、同時に表示
Metadata
まとめ機械学習パイプラインは機械学習で行われる一連の処理をパイプラインとして実行できるよう定義したものVertex Pipelines は機械学習パイプラインをサーバーレスに実行するGCP のサービスで、パイプラインは Kubeflow Pipelines SDK を用いてPython で記述するサンプルとして reproio/lab_sample_pipelines を用意したので触ってみてください