Automl框架katib浅析

时间:2022-07-26
本文章向大家介绍Automl框架katib浅析,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

| 导语   AutoML是一种能将机器学习模型中特征工程、模型选择、超参选择等问题自动化解决的一种方案,使得机器学习模型无需人工干预即可被应用。而katib是一个基于kubernetes生态、简单且可扩展性强的AutoML的一种开源实现。腾讯内部的太极机器学习平台借鉴了katib的一些设计思想,使得AutoML能力集成到训练平台中。 本文将剖析katib框架,对其基本概念、框架和流程进行简要介绍。

一 、AutoML和katib介绍

AutoML

我们知道,机器学习的本质其实是针对某一种学习模型,搜索一组最优参数,使得预设的loss function最少。在这些模型参数之上,还有一组所谓超参数的东西,例如神经网络的层数、学习率、优化算法等,与普通参数不同的是,这些超参数都是在跑某组实验时事先固定好的,并不会在训练过程中调整。

为了避免每次训练都需要人工干预来调整超参数的情况,AutoML应运而生,AutoML将这些与特征、模型、优化、评价有关的重要步骤进行自动化地学习,使得机器学习模型无需人工干预即可被应用。

katib

对于现代机器学习,特别是深度学习而言,使用一组合适的算法训练一组实验需要大量的资源—无论是算力(cpu+gpu)还是存储。kubernetes作为当前资源容器化管理平台的王者,已成为业界机器学习平台的首选。

katib就是基于kubernetes生态的AutoML的一种开源实现,katib隶属于kubeflow社区,实现了一套云原生的超参数搜索与模型结构搜索系统,复用 Kubernetes 对 GPU 等资源的管理能力,同时保证系统的可扩展性。

二 、katib框架剖析

1. 三种crd

katib中有3种概念,分别是experiment、suggestion、trial,分别对应了三种crd,这三种crd相互配合,完成了AutoML对超参数的搜索。 experiment是AutoML的主体对象,用户首先需要构建一个experiment,experiment controller会根据experiment对象创建相应的suggestion对象,即搜索算法,之后根据suggestion对象的输出(即一组超参数),创建一系列的trial对象,即正在的训练实验。三种关系如下:

首先介绍这三种crd:

experiment

experiment表示一个AutoML的实验,当一个experiment完成之后,我们应该能得到这个AutoML搜索出来的最优超参数。一个典型的experiment的yaml如下:

apiVersion: "kubeflow.org/v1alpha2"

kind: Experiment metadata:  namespace: kubeflow  name: bayesianoptimization-experiment spec:  parallelTrialCount: 3  maxTrialCount: 12  maxFailedTrialCount: 3  objective:    type: maximize    goal: 0.99    objectiveMetricName: Validation-accuracy    additionalMetricNames:      - accuracy  algorithm:    algorithmName: bayesianoptimization  trialTemplate:    goTemplate:        rawTemplate: |-          apiVersion: batch/v1          kind: Job          metadata:            name: {{.Trial}}            namespace: {{.NameSpace}}          spec:            template:              spec:                containers:                - name: {{.Trial}}                  image: katib/mxnet-mnist-example                  command:                  - "python"                  - "/mxnet/example/image-classification/train_mnist.py"                  - "--batch-size=64"                  {{- with .HyperParameters}}                  {{- range .}}                  - "{{.Name}}={{.Value}}"                  {{- end}}                  {{- end}}                restartPolicy: Never  parameters:    - name: --lr      parameterType: double      feasibleSpace:        min: "0.01"        max: "0.03"    - name: --num-layers      parameterType: int      feasibleSpace:        min: "2"        max: "5"    - name: --optimizer      parameterType: categorical      feasibleSpace:        list:        - sgd        - adam        - ftrl

该yaml表示了一个experiment需要搜索3种超参数,分别是

  • --lr学习率,搜索范围从0.01-0.03;
  • --num-layers网络层数,范围是2-5;
  • --optimizer优化算法,候选者是sgd,adam,ftrl。

采用的搜索算法是bayesianoptimization,搜索目标是Validation-accuracy,并且在Validation-accuracy大于0.99时停止搜索。

同时该experiment设定了最多跑12组实验,一次并行最多跑3组,如果超过3组实验失败了则停止。

suggestion

suggestion表示的是AutoML中的搜索算法,katib并没有实现某种特定的算法,而是给出了算法需要遵循的规范。搜索算法真正的实现是通过跑一个容器,并且该容器需要尊徐katib的一些通信规范实现的。一个典型的suggestion yaml如下:

apiVersion: kubeflow.org/v1beta1

kind: Suggestion
metadata:
  labels:
    controller-tools.k8s.io: "1.0"
  name: bayesianoptimization-example
  namespace: kubeflow
  ownerReferences:
  - apiVersion: kubeflow.org/v1beta1
    blockOwnerDeletion: true
    controller: true
    kind: Experiment
    name: bayesianoptimization-example
    uid: c14270f4-d81f-4991-a049-00f0beb32770
spec:
  algorithmName: bayesianoptimization
  requests: 12
  resumePolicy: LongRunning
status:
  suggestionCount: 12
  suggestions:
  - name: bayesianoptimization-example-9xms9qr9
    parameterAssignments:
    - name: lr
      value: "0.013988097299564232"
    - name: num-layers
      value: "4"
    - name: optimizer
      value: ftrl
  - name: bayesianoptimization-example-9pk89ks2
    parameterAssignments:
    - name: lr
      value: "0.01858578989212678"
    - name: num-layers
      value: "4"
    - name: optimizer
      value: ftrl
  - name: bayesianoptimization-example-z7vftq6w
    parameterAssignments:
    - name: lr
      value: "0.013979382191901278"
    - name: num-layers
      value: "5"
    - name: optimizer
      value: adam

这个yaml表示使用bayesianoptimization这个算法,从configmap中可以看出bayesianoptimization实际是一个docker镜像:

$ kubectl get configmaps  -n kubeflow  katib-config -o yaml

apiVersion: v1
data:
...
  suggestion: |-
    {
      "hyperband": {
        "image": "gcr.io/kubeflow-images-public/katib/v1beta1/suggestion-hyperband"
      },
      "bayesianoptimization": {
        "image": "gcr.io/kubeflow-images-public/katib/v1beta1/suggestion-skopt"
      }
    }
...

当bayesianoptimization这个算法跑起来之后,suggestion controller会创建suggestion-skopt这个容器,会随着容器的运行产生新的超参数,并且写到status中,例如第一轮产生的超参数是--lr=0.013988097299564232,--num-layers=4,--optimizer=ftrl。这些超参数将会传递给trial跑一轮实验。

trial

trial表示的是在AutoML中的搜索算法给出一组超参后,真正使用这组超参跑一个真实的ML实验。一个典型的trial yaml中如下:

apiVersion: kubeflow.org/v1beta1

kind: Trial
metadata:
  creationTimestamp: "2020-09-25T12:46:49Z"
  finalizers:
  - clean-metrics-in-db
  generation: 1
  labels:
    controller-tools.k8s.io: "1.0"
    experiment: bayesianoptimization-example
  name: bayesianoptimization-example-4w96gvjb
  namespace: kubeflow
  ownerReferences:
  - apiVersion: kubeflow.org/v1beta1
    blockOwnerDeletion: true
    controller: true
    kind: Experiment
    name: bayesianoptimization-example
    uid: c14270f4-d81f-4991-a049-00f0beb32770
  resourceVersion: "1242374"
  uid: c1e395c9-27ea-4b3b-9e3b-933fb0130336
spec:
  metricsCollector:
    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
  parameterAssignments:
  - name: lr
    value: "0.018575758156150434"
  - name: num-layers
    value: "2"
  - name: optimizer
    value: adam
  runSpec:
    apiVersion: batch/v1
    kind: Job
    metadata:
      name: random-example-4w96gvjb
      namespace: kubeflow
    spec:
      template:
        spec:
          containers:
          - command:
            - python3
            - /opt/mxnet-mnist/mnist.py
            - --batch-size=64
            - --lr=0.018575758156150434
            - --num-layers=2
            - --optimizer=adam
            image: docker.io/kubeflowkatib/mxnet-mnist
            name: training-container
          restartPolicy: Never
status:
  completionTime: "2020-09-25T12:38:19Z"
  observation:
    metrics:
    - latest: "0.939988"
      max: "0.948447"
      min: "0.927249"
      name: Validation-accuracy
    - latest: "0.947745"
      max: "0.947745"
      min: "0.910914"
      name: Train-accuracy
  startTime: "2020-09-25T12:37:18Z"

这个trial使用bayesianoptimization算法产生的超参数--lr=0.018575758156150434,--num-layers=2,--optimizer=adam来跑mxnet-mnist实验。实验结果是Train-accuracy=0.948447,Validation-accuracy=0.948447。experiment将拿这组实验结果来选取最优的超参数。

2. 主要组件

katib主要由以下几个组件组成:

  • katib controllers:katib的主逻辑部分,分为以下三个controller:
    • experiment controller:根据experiment创建suggestion和trials,同时根据trials的状态,从suggestion中获取hyper parameters,创建新的trials。也就是说experiment是suggestion和trials的桥梁。
    • suggestion controller:AutoML的算法控制器,接受trials和experiment,输出hyper parameters。
    • trial controller:训练实验控制器,根据suggestion产生的hyper parameters,构建真正的训练程序,并实时更新训练状态。
  • db-manager: 一个gRPC server,用于接受用户存储db数据和获取db数据的请求。
  • pod webhook:拦截automl mpijob创建的pod,并且在pod中增加一个metrics sidecar container。这个metrics container会收集pod的训练日志,并上报给db-manager。
  • experiment webhook:主要用于校验用户的experiment。

3. 框架图

katib的几个组件之间的关系如下所示:

4. 流程

下面简单介绍一下,一个用户从创建katib AutoML任务到获得结果之间,katib都做了哪些步骤,以mpijob为例:

1) 创建任务(experiment)

云原生用户提交experiment yaml给apiserver。apiserver创建experiment object。

2) 创建算法(suggestion)

  • experiment controller观察到有新的experiment object产生,根据experiment创建一个suggestion object。
  • suggestion controller观察到有新的suggestion创建,产生相应的suggestion pod,该pod拉取用户的算法镜像(要求该镜像实现一个grpc服务,并且监听指定端口、遵循平台协议)。
  • 该pod接受experiment的请求并回复算法产生的hyper parameters,更新suggestion object。

3)创建训练实例(trial)

  • experiment controller创建完算法后,由于刚开始没有任何trial,experiment controller会更新suggestion object的request,要求suggestion产生hyper paramters,并根据新的hyper paramters创建trials。trials controller会根据trials object创建mpijob
  • 同时mpijob webhook会截取到该mpijob的创建请求,访问ts校验额度,创建相应实例。

4)训练实例的状态更新

  • 创建状态->训练状态:mpijob训练实例产生后,会产生相应pod,并运行训练程序。pod webhook截取该pod的创建请求,增加metrics sidecar容器。metrics sidecar会读取用户的训练结果(要求用户训练程序将训练结构以指定格式写到写到指定文件),上报给db-manager存储。
  • 训练状态->结束状态:mpijob训练完成后,trial会watch到,并从db-manger中获取训练结构、更新trial object状态。trial object状态变化会反映到experiment controller, 以促成下一轮hyper parameters的产生。即转到step 3的逻辑

5) 实验结束

  • 当experiment观察到某一个trial的训练结果达到目标或者运行了指定数目的trial之后,实验结束并更新experiment状态。

三、如何开发自己的搜索算法

1.如果用户想要新开发一些automl调参算法,需要创建一个grpc服务,并监听指定端口(由环境变量KATIB_SUGGESTION_PORT指定)

2. grpc的请求格式为:

type GetSuggestionsRequest struct {
   Experiment    *Experiment `protobuf:"bytes,1,opt,name=experiment"
 json:"experiment,omitempty"`
   Trials        []*Trial    `protobuf:"bytes,2,rep,name=trials"
json:"trials,omitempty"`
   RequestNumber int32
 `protobuf:"varint,3,opt,name=request_number,json=requestNumber"
json:"request_number,omitempty"`
}

3. grpc的回复格式为:

type GetSuggestionsReply struct {
   ParameterAssignments []*GetSuggestionsReply_ParameterAssignments
`protobuf:"bytes,1,rep,name=parameter_assignments,json=parameterAssignments"
json:"parameter_assignments,omitempty"`
   Algorithm            *AlgorithmSpec
`protobuf:"bytes,2,opt,name=algorithm" json:"algorithm,omitempty"`
}

四、总结

katib是基于kubernetes生态,在kubeflow社区下的一种AutoML开源框架。它有3个概念,分别是experiment,suggestiontrial。experiment创建suggestion,suggestion根据当前trial给出新的超参数,并且由experiment使用超参数创建新的trial,最终从众多trial中选择结果最好的一组trial,使用该组trial的超参数作为最终的超参。

如何有效地进行代码 Review?

如何让视频会议在小程序上开起来

浅析硬盘Media Error