Kubeflow 모르면 사서 고생이다...
Google Cloud에서 시작되었으며, 머신러닝 워크플로우를 Kuberentes 기반 엔진에서 간소화하기 위한 오픈소스 프로젝트.
: Kubeflow의 기본적인 구조. 크게 다음과 같은 구성요소를 지니고 있다.
원래 하나의 ML Pipeline을 구축하기 위해서는 다음과 같은 수작업이 필요했다.
⇒ 머신러닝 전문가와 DevOps 전문가 없이 이러한 작업들을 일일이 하는 것은 매우 힘든 일.
이러한 Challenges를 극복하고자 등장한 점이 바로 ML Automation이며, Kubeflow는 ML Automation을 실현하고자 등장한 프로젝트다.
: 모델 선정 및 학습 과정에 도움을 주는 전반적인 Tool들을 제공함으로써 더욱 편리하게 ML Model Training & Deployment를 가능하게 해준다.
: Kubeflow는 다양한 기능을 통해 다음과 같은 ML Automation을 실현시킨다.
위에서 기술한 모든 자동화 과정을 지원하는 Tool들이 Kubeflow에 다 있으므로, Tool들만 잘 이용하면 자동화를 손쉽게 실현시킬 수 있다.
: 컨테이너 환경에서 모델 학습이 이루어지려면 이에 필요한 모든 실행파일들과 라이브러리, 설정 파일들이 필요하다.
💡 만일 모델이 지속적으로 업데이트 된다면??⇒ 이런 ML Code들과 관련 파일들을 자동으로 컨테이너화 하는 것이 Kubeflow Fairing!
: Kubeflow가 설치된 환경에서 ML Model을 손쉽게 학습 및 배포할 수 있는 파이썬 패키지.
Build, Train, Deploy를 원격으로 수행할 수 있다. 한마디로, ML Code를 컨테이너하기 위해 이미지를 빌드하고 push하고, .yaml 파일 만들고 실행하고… 이걸 단 코드 몇 줄로 수행이 가능하다.
특징:
Fairing 예시:
import os
import tensorflow as tf
from kubeflow import fairing
# Setting up google container repositories (GCR) for storing output containers
# You can use any docker container registry istead of GCR
DOCKER_REGISTRY = 'localhost:5000'
fairing.config.set_builder(
'append',
base_image='gcr.io/kubeflow-images-public/tensorflow-2.0.0a0-notebook-gpu:v0.7.0',
registry=DOCKER_REGISTRY,
push=True)
fairing.config.set_deployer('job',
namespace='test')
def train():
tf.print(tf.constant(os.environ['PATH']))
if __name__ == '__main__':
print('local train()')
train()
print('remote train()')
remote_train = fairing.config.fn(train)
remote_train()
(fairing) root@jyhwang-XPS-15-9570:/home/jyhwang/fairing# python fairing_append_simple_job.py
# Local Train 실행
local train()
/root/miniconda3/envs/fairing/bin:/root/miniconda3/condabin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
# Docker Image만들고 Push
remote train()
[W 191217 16:03:35 function:49] The FunctionPreProcessor is optimized for using in a notebook or IPython environment. For it to work, the python version should be same for both local python and the python in the docker. Please look at alternatives like BasePreprocessor or FullNotebookPreprocessor.
[I 191217 16:03:35 config:123] Using preprocessor: <kubeflow.fairing.preprocessors.function.FunctionPreProcessor object at 0x7fde9f42cb50>
[I 191217 16:03:35 config:125] Using builder: <kubeflow.fairing.builders.append.append.AppendBuilder object at 0x7fde66cdbd50>
[I 191217 16:03:35 config:127] Using deployer: <kubeflow.fairing.builders.append.append.AppendBuilder object at 0x7fde66cdbd50>
[W 191217 16:03:35 append:50] Building image using Append builder...
[I 191217 16:03:35 base:105] Creating docker context: /tmp/fairing_context_39wi82qz
[W 191217 16:03:35 base:92] /root/miniconda3/envs/fairing/lib/python3.7/site-packages/kubeflow/fairing/__init__.py already exists in Fairing context, skipping...
[I 191217 16:03:35 docker_creds_:234] Loading Docker credentials for repository 'gcr.io/kubeflow-images-public/tensorflow-2.0.0a0-notebook-gpu:v0.7.0'
[W 191217 16:03:38 append:54] Image successfully built in 2.427372837002622s.
[W 191217 16:03:38 append:94] Pushing image localhost:5000/fairing-job:E11C94...
[I 191217 16:03:38 docker_creds_:234] Loading Docker credentials for repository 'localhost:5000/fairing-job:E11C94'
[W 191217 16:03:38 append:81] Uploading localhost:5000/fairing-job:E11C94
[I 191217 16:03:38 docker_session_:284] Layer sha256:b5ff3e3cab27890dfd0b520eeeaf68baaf0b7e957bea0f567af3e6ea8e15c6ed pushed.
...
# TF-JOB 실행
[W 191217 17:06:20 job:90] The job fairing-job-dhvh6 launched.
[W 191217 17:06:20 manager:227] Waiting for fairing-job-dhvh6-xfscv to start...
[W 191217 17:06:20 manager:227] Waiting for fairing-job-dhvh6-xfscv to start...
[W 191217 17:06:20 manager:227] Waiting for fairing-job-dhvh6-xfscv to start...
[I 191217 17:06:23 manager:233] Pod started running True
...
# 원격에서 Train() 실행
2019-12-17 08:06:23.882515: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1304] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 3117 MB memory) -> physical GPU (device: 0, name: GeForce GTX 1050 Ti with Max-Q Design, pci bus id: 0000:01:00.0, compute capability: 6.1)
/usr/local/nvidia/bin:/usr/local/cuda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
[W 191217 17:06:24 job:162] Cleaning up job fairing-job-dhvh6...
⇒ 원격으로 image를 만들고 Push 한 후 학습을 시키면, Registry가 생기고 배포가 된다.
: K8s Cluster는 기본적으로 휘발성 환경이기 때문에 모델의 학습 등의 머신러닝 과정 등이 문제없이 돌아가도록 보장하기 어렵다.
⇒ k8s의 파드는 매우 동적이고 재시작이 빈번하게 일어나므로 각 학습 과정이 제대로 되고 있는 지 check 해야 함.
: TF-Job 등, Training Job가 실행되면 이와 관련된 Operator가 작동하여 다음과 같은 역할을 수행한다.
ex) TFOperator:
apiVersion: kubeflow.org/v1
kind: TFJob
metadata:
generateName: tfjob
namespace: your-user-namespace
spec:
tfReplicaSpecs:
PS:
replicas: 1
restartPolicy: OnFailure
template:
metadata:
annotations:
sidecar.istio.io/inject: "false"
spec:
containers:
- name: tensorflow
image: gcr.io/your-project/your-image
command:
- python
- -m
- trainer.task
- --batch_size=32
- --training_steps=1000
Worker:
replicas: 3
restartPolicy: OnFailure
template:
metadata:
annotations:
sidecar.istio.io/inject: "false"
spec:
containers:
- name: tensorflow
image: gcr.io/your-project/your-image
command:
- python
- -m
- trainer.task
- --batch_size=32
- --training_steps=1000
: 사용자의 요청이 지나치게 많아지면 ML 추론 서버에 과부하가 생기며, 이로 인한 여러가지 문제점이 발생할 수 있음
⇒ Kubeflow 트래픽에 따른 추론 서버의 Scaling 자동화를 지원하는 기능이 탑재되어 있다.
보통 Serveless라 하면 강한 벤더 의존성 (AWS Lambda, Azure Functions, Google Cloud Functions, IBM Cloud Functions)을 지니고 있음.
: Stateless app 및 이벤트 핸들링을 위한 모델 제공, 컨테이너를 빌드할 수 있는 환경을 제공하는데, 이 때 Knative에 탑재된 Istio는 다음과 같은 역할을 한다.
⇒ 즉 추론 서버를 운용할 때, K8s 클러스터를 Istio 기반 라우팅을 통해 효율적이고 빠른 네트워킹 시스템을 구축함
: Kubeflow에서 제공하는 다양한 추론 프레임워크 (Tensorflow, PyTorch, ONXX 등)를 위한 인터페이스 제공 및 k8s를 통한 서버리스 추론 Tool
⇒ 어느 위치에 모델을 저장하고, 이걸 InferenceService라는 커스텀 리소르를 배포하면, 알아서 Pod에 모델을 제공해주고 API도 자동으로 제공해준다.
(잘 보면 Transformer Service와 Predictor Service에 연결된 두 종류의 Replicaset들이 min/max replicas 사이에서 Scaling을 한다고 적혀있다.)
⇒ 이 모든 것이 InferenceService라는 Manifest 파일 하나만으로 끝남
InferenceService:
apiVersion: "serving.kserve.io/v1beta1"
kind: "InferenceService"
metadata:
name: "sklearn-iris"
spec:
predictor:
model:
modelFormat:
name: sklearn
storageUri: "gs://kfserving-examples/models/sklearn/1.0/model"
EOF
실제 구동:
KServe 이 보다 더 쉬운 ML Model Serving 은 없다.
: 하이퍼파라미터 튜닝 및 모델 아키텍쳐 검색은 계속 시도하면서 고쳐 나가거나 조정해야 하는 등, 여러가지 복잡한 문제점들이 많음.
: 자동으로 최적화 된 파라미터를 찾고, NAS (Neural Architecture Search) 지원 및 하이퍼파라미터를 최적화하는 Kubeflow의 Add-on;
Automated Hyperparameter Tuning
보통 하이퍼파라미터라면 다음과 같은 전체 프로세스의 상위 변수들을 조절한다:
⇒ 이걸 자동으로 설정해준다는 의미. 즉, 최적화된 하이퍼파라미터를 일일이 모델을 학습시키면서 조정할 필요 없이, 알아서 돌려보고 알아서 Best Value를 설정해준다.
Neural Architecture Search (NAS) Support
: 목표를 달성하기 위해 필요한 인공 신경망을 자동으로 디자인해주고 골라준다. 즉, 모델의 구조와 노드의 가중치, 하이퍼 파라미터들을 최적화해준다는 것.
또한, 다음과 같은 AutoML 알고리즘을 지원한다:
cf) AutoML
: 데이터 사이언스의 역할에 필요한 전문 지식이나 배경 지식 없이도, 각 구성요소에 대한 최적의 솔루션을 알아서 찾는 검색 알고리즘.
모델에 대한 깊은 이해가 필요없이, 알아서 데이터에 맞는 모델을 찾아준다…???
MNIST 예제 파일이다. 다음과 같이 어떤 알고리즘을 쓸건지 등의 구체적인 설정을 yaml에 명시한다.
apiVersion: kubeflow.org/v1beta1
kind: Experiment
metadata:
...
name: random
namespace: kubeflow-user-example-com
...
spec:
algorithm:
algorithmName: random
maxFailedTrialCount: 3
maxTrialCount: 12
metricsCollectorSpec:
collector:
kind: StdOut
objective:
additionalMetricNames:
- Train-accuracy
goal: 0.99
metricStrategies:
- name: Validation-accuracy
value: max
- name: Train-accuracy
value: max
objectiveMetricName: Validation-accuracy
type: maximize
parallelTrialCount: 3
parameters:
- feasibleSpace:
max: "0.03"
min: "0.01"
name: lr
parameterType: double
- feasibleSpace:
max: "5"
min: "2"
name: num-layers
parameterType: int
- feasibleSpace:
list:
- sgd
- adam
- ftrl
name: optimizer
parameterType: categorical
resumePolicy: Never
...
그 후, 다음 코드를 실행하면 끝이다.
kubectl -n kubeflow describe experiment random
그럼, 자동으로 최적의 결과를 알려주는 파라미터 세트를 알려준다.
: ML Pipeline을 구성할 때, K8s 클러스터 내에서 각각의 구성요소들을 컨테이너화 시켜 ML Workflow를 구성할 수 있다.
⇒ 다음과 같이 파이프라인의 각 구성요소들을 담당하는 컨테이너들을 파드들로 분리하는 모습. 이렇게 각 컴포너트들을 컨테이너화 시키면 다음과 같은 이점이 있다.
References
Kubeflow and ML Automation: Part 1
Running Distributed TensorFlow Jobs on Kubeflow 3.5
정리가 잘 된 글이네요. 도움이 됐습니다.