Skip to main content
Version: 1.3

Tuner 로 모델 튜닝하기

시작하면서#

이전 장에서 Tuner를 사용할 준비를 마쳤습니다.
이번 장에서는 UI, YAML, SDK 로 Tuner를 사용하는 방법을 배웁니다.
이 튜토리얼은 Notebook과 Tuner에서 진행됩니다.


info

이번 과정은 개발을 위한 준비 챕터에서 만든 handson 노트북서버에서 진행됩니다.
Tuner 사용 준비 에서 작성한 코드를 베이스로 사용할 것입니다.
전체 코드는 아래 링크에서 확인하실 수 있습니다.
06.tuner.ipynb

Goal#

  • Tuner UI로 튜닝하기
  • YAML을 이용하여 튜닝하기
  • SDK를 이용하여 튜닝하기

Tuner UI로 튜닝하기#

Tuner 메뉴로 이동하여 CREATE 버튼을 누릅니다. CAP의 Tuner는 사용자가 순서대로 입력할 수 있게 UI를 제공합니다.

1. Metadata 설정#

metadata Tuner의 이름을 설정합니다. fashion-mnist-tuner라고 정하겠습니다. 나중 리스트에 보여질 이름입니다.


2. Trial Thresholds 설정#

trial_thresholds 동시에 3개의 탐색을 진행하며, 총 12번의 탐색을 진행합니다. 그리고 탐색이 3번 실패하면 멈추도록 설정하겠습니다.


3. 목표 설정#

objective

  • type : Maximize
  • Metric : Validation-accuracy
  • Goal : 0.99
  • Additional metrics : ➕ 버튼을 눌러 accuracy, loss, Validation-loss 를 적습니다.
  • set metrics stargey는 일단 그대로 둡니다.

위처럼 설정 하면 Validation-accuracy 값이 0.99가 되는 것을 목표로 하이퍼파라미터 탐색을 시작합니다.
accuracy, loss, Validaiton-loss와 같은 다른 메트릭도 같이 수집합니다.

tip

만약 탐색 도중 0.99가 된다면 Tuner는 현재 탐색을 종료시킵니다.
만약 종료가 되지 않는다면 0.99에 가장 가까운 값을 Best 로 정합니다.


4. 탐색 알고리즘 설정#

search_alg 하이퍼파라미터 튜닝을 선택한 후, 탐색 알고리즘을 Random으로 선택합니다.
이는 하이퍼파라미터의 값을 매 탐색(Trial) 마다 랜덤으로 정하여 진행합니다.


5. Early Stopping 설정#

탐색이 과적합(overfitting)으로 가거나 아니면 비정상적으로 진행될 때 멈추는 기능입니다.
Median Stopping Rule의 기본 세팅으로 설정하겠습니다.

early_stopping


6. 하이퍼파라미터 설정#

MyModel에서 탐색해야할 하이퍼파라미터를 입력합니다.
MyModel에서 argparse 로 입력받기로 했던 항목을 추가합니다.

node_amount : Type 은 Categorical , Value로 64, 128, 256, 512로 설정합니다. node_amount

dropout_rate : Type은 Double, Value로 0.1에서 0.9로 설정합니다. dropout_rate

optimizer : Type 은 Categorical, Value로 sgd, adam, nadam, rmsprop 를 추가합니다. optimzer

TYPE

하이퍼파라미터의 타입에 따라 넣는 형식이 다릅니다.
Integer, Double : Min, Max 값을 넣어 범위형태로 파라미터를 넣을 수 있습니다.
Categorical : 순서가 상관 없는 범주형 파라미터를 넣어 줍니다.
Discrete : Categorical과 비슷하지만 Numeric 한 파라미터를 넣을 때 사용합니다.


7. 로그 수집 방법 설정#

metric_collector Tuner에서 로그 수집하는 방법은 여러가지가 있지만 MyModel 클래스에서 print 함수로 로그를 출력하게 때문에
Standard output 설정인 Stdout으로 설정합니다.


8. Trial Template 설정#

Tuner에서는 탐색을 진행할 Kubernetes Job 기본 템플릿을 제공합니다.
이 템플릿을 복사해서 MyModel에 맞게 수정하겠습니다. trial_template

MyModel.yaml
# MyModel Yaml, 이미지 이름을 본인이 만든 이미지 이름과 태그로 바꿔줍니다.apiVersion: batch/v1kind: Jobspec:  template:    metadata:      annotations:        sidecar.istio.io/inject: "false"         spec:      containers:        - name: training-container          image: yourID/fashion-mnist-tuner:yourTAG # fairing으로 만들어진 자신의 이미지           command:            - "python"            - "/app/fashion_mnist_tuner.py"            - "--node_amount=${trialParameters.node_amount}"            - "--dropout_rate=${trialParameters.dropout_rate}"            - "--optimizer=${trialParameters.optimizer}"      restartPolicy: Never   

Source Type을 YAML로 바꾸고 위 템플릿을 복사하여 붙여넣습니다.

  • spec.containers.image 필드의 이미지 이름을 본인이 만든 이미지 이름과 태그로 바꿔줍니다.
  • argparse로 입력받는 영역과 python 파일로 변환된 fashion_mnist_tuner.py 이 템플릿에 적용되어 있습니다. trial_template

마지막 단계에서 템플릿에 입력값으로 들어간 trialParameters.node_amount등의 하이퍼파라미터들을
앞서 입력한 하이퍼파라미터들와 매칭시켜줍니다. 혼동의 여지가 있어서 이름을 다 통일하였습니다.

reference

모든 준비는 끝났습니다. CREATE 버튼을 눌러 Tuner를 실행해봅시다!

tuner_list

Status가 READY 로 변경이 되면 Trials가 실행이 됩니다. 상세 보기로 들어가면 자세한 탐색 내용을 확인할 수 있습니다.

trial_graph

12번의 탐색이 완료 되면, Best trial's params, Best trial performance를 확인할 수 있습니다.
물론 탐색중에서도 확인이 가능합니다.

tuner_result

:🎉: Validation-accuracy가 85%에서 88%로 3퍼센트가 올랐습니다!


탐색 범위 변경, epoch도 하이퍼파라미터로 추가하기#

12번의 탐색결과(trial)에서 기존 85%의 Validation-accuracy에서 좀 더 높은 정확도(88%)를 얻게 되었습니다.
그러면 이제 epoch도 변경할 수 있도록 argparse로 입력을 받게 바꾸고, 탐색횟수도 좀 더 늘려봅시다.

note

TUNER UI를 사용하면 처음부터 모든 설정을 다시 입력해야하는 번거로움이 있습니다.

fashion_mnist_model.ipynb
# from fashion_mnist_model.ipynb        ...        parser.add_argument('--node_amount', required=False, type=int, default=128)        parser.add_argument('--epoch', required=False, type=int, default=10)                parser.add_argument('--dropout_rate', required=False, type=float, default=0.2)        ...
        ...                    validation_data=(x_test, y_test),                    epochs=args.epoch,                    callbacks=[LoggingTrain(),        ...    

renew_trial renew_objective
renew_hp

  • add epoch template
trial_template_epoch.yaml
apiVersion: batch/v1kind: Jobspec:  template:    metadata:      annotations:        sidecar.istio.io/inject: "false"         spec:      containers:        - name: training-container          image: yourID/fashion-mnist-tuner:yourTAG # fairing으로 만들어진 자신의 이미지           command:            - "python"            - "/app/fashion_mnist_tuner.py"            - "--node_amount=${trialParameters.node_amount}"            - "--dropout_rate=${trialParameters.dropout_rate}"            - "--optimizer=${trialParameters.optimizer}"            - "--epoch=${trialParameters.epoch}"                  restartPolicy: Never 

renew_ref

변경이 완료되면 다시 탐색을 시작합시다!

epoch_30 epoch_30_result

총 30번의 시도에 절반정도가 Ealry Stopping이 적용되었고 미세하게 개선되었음을 알 수 있습니다.

과제

신경망의 층 수와 신경망의 activation 함수도 수정해보며 90%를 넘겨봅시다!


YAML을 이용하여 튜닝하기#

UI를 이용한 튜닝에는 한가지 단점이 있습니다. Tuner를 실행할때 마다 처음부터 새로 입력해야 한다는 점입니다.
간단한 수정사항이 있어도 처음부터 재작성 해야하는 어려움이 있습니다.
이 점을 해결하기 위해 실행한 Tuner의 YAML을 제공합니다.
YAML만을 이용해 UI의 8 Step을 거치지 않고 한번에 실행이 가능합니다.


기존의 Tuner 템플릿 가져오기#

아까 실행한 fashion-mnist-tuner의 상세화면으로 이동해봅시다.
그래프 하단에 YAML tab을 누르면 Tuner의 YAML을 확인할 수 있습니다.

tuner_yaml

이 YAML을 복사한 후 메모장으로 옮깁니다. YAML의 기본 구조는 4가지의 필드로 구성되어 있습니다.

tuner.yaml
apiVersion:kind:metadata:spec:

복사해온 YAML에서는 apiVersion, kind가 빠져있기 때문에 아래의 코드를 제일 상단에 추가합니다.

apiVersion: kubeflow.org/v1beta1kind: Experiment

metadata 필드내의 name와 namespace를 제외하고는 기존 Tuner의 상태 정보이기 때문에 삭제합니다.
그리고 status 이하 필드 또한 실행된 Tuner의 상태 정보이기 때문에 지우도록 하겠습니다.

수정된 전체 YAML은 아래와 같습니다.
05.tuner.yaml

apiVersion: kubeflow.org/v1beta1kind: Experimentmetadata:  name: fashion-mnist-tuner  namespace: cap-devspec:  parameters:    - name: node_amount      parameterType: categorical      feasibleSpace:        list:          - '64'          - '128'          - '256'          - '512'    - name: dropout_rate      parameterType: double      feasibleSpace:        max: '0.9'        min: '0.1'        step: '0.1'    - name: optimizer      parameterType: categorical      feasibleSpace:        list:          - sgd          - adam          - nadam          - rmsprop  objective:    type: maximize    goal: 0.99    objectiveMetricName: Validation-accuracy    additionalMetricNames:      - accuracy      - loss      - Validation-loss    metricStrategies:      - name: Validation-accuracy        value: max      - name: accuracy        value: max      - name: loss        value: min      - name: Validation-loss        value: min  algorithm:    algorithmName: random  trialTemplate:    trialSpec:      apiVersion: batch/v1      kind: Job      spec:        template:          metadata:            annotations:              sidecar.istio.io/inject: 'false'          spec:            containers:              - command:                  - python                  - /app/fashion_mnist_tuner.py                  - '--node_amount=${trialParameters.node_amount}'                  - '--optimizer=${trialParameters.optimizer}'                  - '--dropout_rate=${trialParameters.dropout_rate}'                  - '--epoch=${trialParameters.epoch}'                image: yourID/fashion-mnist-tuner:yourTAG # 자신의 fairing 이미지                name: training-container            restartPolicy: Never    trialParameters:      - name: node_amount        reference: node_amount      - name: dropout_rate        reference: dropout_rate      - name: optimizer        reference: optimizer      - name: epoch        reference: epoch    primaryContainerName: training-container    successCondition: status.conditions.#(type=="Complete")#|#(status=="True")#    failureCondition: status.conditions.#(type=="Failed")#|#(status=="True")#  parallelTrialCount: 3  maxTrialCount: 12  maxFailedTrialCount: 3  metricsCollectorSpec:    collector:      kind: StdOut  resumePolicy: LongRunning

YAML로 실행하기#

Tuner 생성 화면 제일 하단에 OPEN YAML이란 버튼이 있습니다. 그 버튼을 누르면 YAML을 편집할 수 있는 편집공간이 나옵니다. 기본 템플릿이 들어있으니, 이전에 작성한 YAML을 이름만 수정해서 넣고 CREATE를 실행하면 똑같은 설정의 다른 이름의 Tuner를 실행할 수 있습니다.
edit_yaml


노트북에서 SDK를 이용하여 튜닝하기#

CAP은 노트북에서 Tuner를 사용할 수 있는 SDK를 제공합니다. 먼저 tuner.ipynb라는 이름의 빈 노트북을 생성합니다. CAP에서 제공되는 노트북 이미지에는 기본적으로 SDK가 설치되어 있지만, 만약 설치되어 있지 않다면
!pip install kubeflow-katib 를 명령어로 설치를 진행해주세요.

check_sdk
!pip freeze | grep katibkubeflow-katib==0.11.1 # 이와같이 출력이 되지 않는다면
!pip install kubeflow-katib # <-를 실행합니다.

Tuner 리스트 조회해보기#

SDK를성활용하여 현재 실행된 Tuner를 조회해 보겠습니다. SDK를 사용하기 위해서는 client를 먼저 생성합니다.

get_list
from kubeflow import katibfrom kubeflow.katib import KatibClient
kclient = KatibClient()kclient.list_experiments()

sdk_list

아까 실행한 Tuner의 리스트가 나오면 성공입니다.


노트북에서 Tuner 상세 정보 조회하기#

get_experiment
kclient.get_experiment('fashion-mnist-tuner') # 리스트를 조회해서 나온 Tuner의 이름을 넣어주세요

sdk_view


노트북에서 Tuner의 결과 조회하기#

Tuner가 찾은 최적의 결과를 조회합니다.

get_result
kclient.get_optimal_hyperparameters('YOUR_TUNER_NAME') # 리스트를 조회해서 나온 Tuner의 이름을 넣어주세요

sdk_optimal

모든 결과는 dict 형태로 반환됩니다.


노트북에서 SDK로 Tuner 생성하기#

이제 Tuner를 생성해보겠습니다. UI로 만든 fashion-mnist-tuner와 동일한 기능을 하는 코드를 작성하겠습니다.
Tuner SDK는 python 코드를 Tuner YAML변환하여 Tuner를 실행시키기 때문에 코드로 YAML의 필드들을 구현합니다.
YAML의 기본 구조인 api, kind, metadata, spec을 똑같이 python 코드로 구현하겠습니다.

tuner.ipynb
from kubernetes.client import V1ObjectMetafrom kubeflow.katib import V1beta1Experimentfrom kubeflow.katib import V1beta1AlgorithmSpecfrom kubeflow.katib import V1beta1ObjectiveSpecfrom kubeflow.katib import V1beta1FeasibleSpacefrom kubeflow.katib import V1beta1ExperimentSpecfrom kubeflow.katib import V1beta1ObjectiveSpecfrom kubeflow.katib import V1beta1ParameterSpecfrom kubeflow.katib import V1beta1TrialTemplatefrom kubeflow.katib import V1beta1TrialParameterSpec
experiment_name = "fashion-mnist-tuner-sdk"
metadata = V1ObjectMeta(    name=experiment_name)

algorithm_spec=V1beta1AlgorithmSpec(    algorithm_name="random")
objective_spec=V1beta1ObjectiveSpec(    type="maximize",    goal= 0.99,    objective_metric_name="Validation-accuracy",    additional_metric_names=["Validation-loss", "accuracy", "loss"])
parameters=[    V1beta1ParameterSpec(        name="node_amount",        parameter_type="categorical",        feasible_space=V1beta1FeasibleSpace(            list=["64", "128", "256", "521"],        ),    ),    V1beta1ParameterSpec(        name="dropout_rate",        parameter_type="double",        feasible_space=V1beta1FeasibleSpace(            min="0.1",            max="0.9"        ),    ),    V1beta1ParameterSpec(        name="optimizer",        parameter_type="categorical",        feasible_space=V1beta1FeasibleSpace(            list=["sgd", "adam", "nadam", "rmsprop"],        ),    ),    V1beta1ParameterSpec(        name="epoch",        parameter_type="int",        feasible_space=V1beta1FeasibleSpace(           min="10",           max="30"        ),    ),    ]
# JSON template specification for the Trial's Worker Kubernetes Job.trial_spec = {    "apiVersion": "batch/v1",    "kind": "Job",    "spec": {        "template": {            "metadata": {                "annotations": {                    "sidecar.istio.io/inject": "false"                }            },            "spec": {                "containers": [                    {                        "name": "training-container",                        "image": "YOURID/fashion-mnist-tuner:YOURTAG",                         "command": [                            "python",                            "/app/fashion_mnist_tuner.py",                            "--node_amount=${trialParameters.node_amount}",                            "--dropout_rate=${trialParameters.dropout_rate}",                            "--optimizer=${trialParameters.optimizer}",                            "--epoch=${trialParameters.epoch}"                        ]                    }                ],                "restartPolicy": "Never"            }        }    }}

# Configure parameters for the Trial template.trial_template=V1beta1TrialTemplate(    primary_container_name="training-container",    trial_spec=trial_spec,        trial_parameters=[        V1beta1TrialParameterSpec(            name="node_amount",            description="Layer neuron amount",            reference="node_amount"        ),                V1beta1TrialParameterSpec(            name="dropout_rate",            description="dropout_rate for the training model",            reference="dropout_rate"        ),        V1beta1TrialParameterSpec(            name="optimizer",            description="optimizer for the training model",            reference="optimizer"        ),        V1beta1TrialParameterSpec(            name="epoch",            description="epoch for the training model",            reference="epoch"        )    ])

# Experiment object.experiment = V1beta1Experiment(    api_version="kubeflow.org/v1beta1",    kind="Experiment",    metadata=metadata,    spec=V1beta1ExperimentSpec(        max_trial_count=12,        parallel_trial_count=3,        max_failed_trial_count=3,        algorithm=algorithm_spec,        objective=objective_spec,        parameters=parameters,        trial_template=trial_template,    ))

Tuner의 experiment 설정이 완료되면 클라이언트로 실행해보겠습니다.
아래 코드가 오류없이 실행이 되면 노트북에서 Tuner로 이동할 수 있는 링크가 제공됩니다.

run_tuner_by_sdk_client
kclient.create_experiment(experiment)

sdk_create


Tuner 탐색 상태 조회하기#

fashion-mnist-tuner-sdk 란 이름의 Tuner가 실행되고 있습니다.
SDK를 이용해 현재 Tuner의 상태를 확인하겠습니다.
실행중이라면 Running 정상적으로 탐색을 종료하였다면 Succeeded란 메시지를 출력합니다.

get_status
kclient.get_experiment_status("fashion-mnist-tuner-sdk")

tuner_status