cube studio 开源一站式云原生机器学习平台-架构(五)

全栈工程师开发手册 (作者:栾鹏)
一站式云原生机器学习平台


前言:cube是开源的云原生机器学习平台,目前包含特征平台,支持在/离线特征;数据源管理,支持结构数据和媒体标注数据管理;在线开发,在线的vscode/jupyter代码开发;在线镜像调试,支持免dockerfile,增量构建;任务流编排,在线拖拉拽;开放的模板框架,支持tf/pytorch/spark/ray/horovod/kaldi等分布式训练任务;task的单节点debug,分布式任务的批量优先级调度,聚合日志;任务运行资源监控,报警;定时调度,支持补录,忽略,重试,依赖,并发限制,定时任务算力的智能修正;nni,katib,ray的超参搜索;多集群多资源组,算力统筹,联邦调度;tf/pytorch/onnx模型的推理服务,serverless流量管控,tensorrt gpu推理加速,依据gpu利用率/qps等指标的 hpa能力,虚拟化gpu,虚拟显存等服务化能力。 目前开源到github:https://github.com/tencentmusic/cube-studio

katib超参搜索

机器学习平台依赖Katib实现超参数搜索系统。katib提供了超参搜索和网络结构搜索,本文先介绍超参搜索。

先来看看目前超参搜索解决方案的对比。katib是对 Google Vizier 的开源实现,Google Vizier 是 Google 内部的机器学习超参数训练系统的一个子系统。

在这里插入图片描述

katib组件

在官方自带的界面上,用户使用起来是这样的。

在这里插入图片描述

在这个产品背后支撑的是下面的几个组件

katib-ui: katib的web产品界面,也就是用户看到的这个web界面。注意由于katib包括较少的产品使用逻辑控制,所以没有专门后端来控制产品的使用。

katib-mysql:元数据存储,目前只有一个table:observation_logs。会存储Trial和Experiment,以及Trial的训练指标。

katib-db-manager:DB的grpc接口,它是数据库接口。提供了对Katib DB的操作(包括前端查询数据使用,以及业务容器sidecar采集日志后写入数据使用),同时充当Suggestion与Experiment之间的代理。

katib-controller:katib定义的crd的控制器。是核心模块,如果在使用的过程中出现问题,基本都可以在这里排查。

katib crd

使用katib,主要就是使用好katib定义的几个crd。

experiments.kubeflow.org:一次搜索实验,用户配置好目标函数,搜索空间,搜索算法以及worker任务

suggestions.kubeflow.org:实验创建后,会根据搜索算法产生一个解决方案,可以称呼他为建议器或者学习器,用来迭代产生新的超参选值。

trials.kubeflow.org:优化过程的一次迭代,根据给定的超参选值,进行业务代码计算,并输出计算效果。

Job:负责一次迭代的任务。非分布式的k8s-job,分布式的tf-job/pytorch-job/xgb-job。

experiments.kubeflow.org

我们只需要掌握experiments.kubeflow.org,其他的自定义资源是由系统自己生成控制的。下面是一个配置示例

apiVersion: kubeflow.org/v1alpha3
kind: Experiment
metadata:
  name:
  namespace: katib
ExperimentSpec:
    parallelTrialCount:   并行测试数目
    maxTrialCount:        最大测试数目
    maxFailedTrialCount:  最大失败数目
    nas_config:  
    parameterspec:        要搜索的超参配置
    objective:            要搜索的目标函数配置
      goal: 0.99
      objectiveMetricName: xx
      type: maximize
    algorithm:            搜索算法
      algorithmName: random
    metricsCollectorSpec: 测试结果的采集方案
      collector:
        kind: StdOut
    trial_template:       测试用例的写法
      goTemplate:
        rawTemplate: 字符串格式,k8s 各种job资源,yaml书写格式的字符串形式。

其中超参搜索算法支持:

  • Random Search
  • Tree of Parzen Estimators (TPE)
  • Grid Search
  • Hyperband
  • Bayesian Optimization
  • CMA Evolution Strategy

采集系统主要以业务容器系统输出流或TensorFlowEvent的train目录为采集对象。

超参的配置parameterspec类似下面。支持的超参类型只包含double、int、categorical三种。在网格搜索时需要填写step参数。

parameters:
- name: --lr
  parameterType: double   # type,支持double、int、categorical 三种
  feasibleSpace:
    min: "0.01"           # double、int类型必填min和max。max必须大于min
    max: "0.03"
    step: "0.01"          # grid 搜索算法时,需要提供采样步长,random时不需要
- name: --num-layers
  parameterType: int
  feasibleSpace:
    min: "2"
    max: "5"
    step: "1"
- name: --optimizer
  parameterType: categorical
  feasibleSpace:
    list:
    - sgd
    - adam
    - ftrl

rawTemplate为字符串,不过需要包含超参作为输入参数。如下,这样才能将建议器计算出来的超参取值传递给job。

  trialTemplate:
    goTemplate:
        rawTemplate: |-
          apiVersion: batch/v1
          kind: Job
          metadata:
            name: {{.Trial}}
            namespace: {{.NameSpace}}
          spec:
            template:
              spec:
                containers:
                - name: {{.Trial}}
                  image: docker.io/kubeflowkatib/mxnet-mnist
                  command:
                  - "python3"
                  - "/opt/mxnet-mnist/mnist.py"
                  - "--batch-size=64"
                  {{- with .HyperParameters}}
                  {{- range .}}
                  - "{{.Name}}={{.Value}}"
                  {{- end}}
                  {{- end}}
                restartPolicy: Never

katib架构和原理

katib架构如下图所示

在这里插入图片描述

Experiment Controller:提供对Experiment CRD的生命周期管理,在katib-controller组件中。

Trial Controller:提供对Trial CRD的生命周期管理,在katib-controller组件中。

Suggestions:以Deployment的方式部署,用Service方式暴露服务,提供超参数搜索服务。目前有随机搜索,网格搜索,贝叶斯优化等。

在这里插入图片描述

Experiment本身是k8s的crd对象,k8s的所有crd记录都存储在k8s依赖的etcd数据库中。当一个Experiment被创建的时候,Experiment Controller会先通过Katib Manager在Katib DB中创建一个Experiment对象,并且打上Finalizer表明这一对象使用了外部资源(etcd数据库)。随后,Experiment Controller会根据自身的状态和关于并行的定义,通过Katib Manager提供的GRPC接口,让Manager通过 Suggestion提供的GRPC接口获取超参数取值,然后再转发给Experiment Controller。在这个过程中,Katib Manager是一个代理的角色,它代理了Experiment Controller对Suggestion的请求。拿到超参数取值后,Experiment Controller会根据Trial Template和超参数的取值,构造出Trial的定义,然后在集群中创建它。

Trial被创建后,与Experiment Controller的行为类似,Trial Controller同样会通过Katib Manager在Katib DB中创建一个Trial对象。随后会构造出期望的Job(如batchv1 Job,TFJob,PyTorchJob等)和Metrics Collector Job,然后在集群上创建出来。这些Job运行结束后,Trial Controller会更新Trial的状态,进而Experiment Controller会更新Experiment的状态。 然后Experiment会继续下一轮的迭代。之前的Trial已经被训练完成,而且训练的指标已经被收集起来了。Experiment会根据配置,判断是否要再创建新的Trial,如果需要则再重复之前的流程。

python sdk

了解了experiments.kubeflow.org资源的格式和架构流程,kubeflow还提供了katib的python sdk,可以让我们在代码中更加方便的生成创建experiments。代码中只是按照yaml的层次封装了Experiment对象,并且提供了create_experiment函数直接创建自定义对象。

# Experiment 跑实例测试
experiment = V1alpha3Experiment(
    api_version="kubeflow.org/v1alpha3",
    kind="Experiment",
    metadata=V1ObjectMeta(name="tfjob-example",namespace="default"),
    spec=V1alpha3ExperimentSpec(
         algorithm = algorithm,               # 自己定义
         max_failed_trial_count=3,
         max_trial_count=12,
         metrics_collector_spec= metrics_collector_spec,      # 自己定义
         objective = objective,               # 自己定义
         parallel_trial_count=4,
         parameters = parameters ,             # 自己定义
         trial_template = trial_template ,     # 自己定义
    )
)

kclient = kc.KatibClient(config_file=None)
kclient.create_experiment(experiment,your_namespace)

katib运行跟踪

通过python sdk或者kubectl或者katib ui创建了experiment,正常情况就不需要我们关心了,只需要我们进行debug即可。我们可以通过k8s dashboard查看pod运行情况,或者通过katib ui查看当前系统experiment的采集结果。

在这里插入图片描述

在创建experiment后,会先启动Suggestions容器和service。Suggestions的名称为experiment名称+搜索算法名称。Suggestion会根据用户配置的超参取值范围和搜索算法迭代的产生参数可取值,并发产生执行job。(注意一个执行job并不一定是一个pod,比如一个tfjob可能是多个worker容器)。每个执行job的pod会包含业务容器和采集容器,像下面

在这里插入图片描述

我们可以通过查看job的配置来理解运行机制。

在这里插入图片描述

这是一个执行pod的启动配置,可以看到业务容器的超参–lr,–num-layers,–optimizer都已经赋予了选值,并且在原有参数的基础上添加了参数1>/var/log/katib/metric.log 2>&1,也就是说会将业务容器的系统输出流重定向到metric.log文件。并且添加了启动命令 echo completed > /var/log/katib/$$$$.pid,来实现sidecar容器的完成通知。

在采集容器中,将metric文件的地址和业务容器的名称,要匹配的目标指标名,以及katib manager服务的信息都做为参数传递给采集容器。采集容器会跟踪metric.log文件,跟踪日志信息,匹配包含目标指标名,匹配符合一定规则的日志记录行,将该行的数据提取出来,然后通过katib manager 写入到db的observation_logs表中。observation_logs表记录的格式示例如下

在这里插入图片描述

所以这就要求业务容器在打印日志的时候希望被采集的日志内容的书写格式要符合一定规范。用户代码需要进行日志输出(需要包含时间,目标函数名=目标值)

可以按照下面的格式来编写

import logging
# Use this format (%Y-%m-%dT%H:%M:%SZ) to record timestamp of the metrics
# 放在全局最外层
logging.basicConfig(
    format="%(asctime)s %(levelname)-8s %(message)s",
    datefmt="%Y-%m-%dT%H:%M:%SZ",
    level=logging.DEBUG)
...
def fun_name():
    ...
    logging.info('Validation-accuracy=%s'%str(random.random()))
    ...
...

那打印的日志应该像下面这样,比如目标函数为Validation-accuracy。

在这里插入图片描述

当一次trial的多次迭代日志被采集后,那么一次trial中迭代的时间和目标函数值就存储在数据库中了,那么该次trial的绘图就可以在katib ui上看到了,比如下图(下图是包含两个目标函数的情况)

在这里插入图片描述

当多次trial执行完成,我们就可以在katib ui上看到trials的运行情况

在这里插入图片描述

并且实时能看到已经完成的trials的参数取值和目标函数值。当整个experiment完成,我们就可以在ui上看到最终的取值效果了

在这里插入图片描述

我们可以在折线图或者table list中根据目标函数筛选目标函数最大或者最小时对应的超参取值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

腾讯AI架构师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值