100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > cube云原生机器学习平台-架构(五)

cube云原生机器学习平台-架构(五)

时间:2024-06-26 03:13:54

相关推荐

cube云原生机器学习平台-架构(五)

全栈工程师开发手册 (作者:栾鹏)

一站式云原生机器学习平台

前言: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:/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。

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

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

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

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

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

apiVersion: /v1alpha3kind: Experimentmetadata:name:namespace: katibExperimentSpec:parallelTrialCount: 并行测试数目maxTrialCount: 最大测试数目maxFailedTrialCount: 最大失败数目nas_config: parameterspec: 要搜索的超参配置objective: 要搜索的目标函数配置goal: 0.99objectiveMetricName: xxtype: maximizealgorithm: 搜索算法algorithmName: randommetricsCollectorSpec: 测试结果的采集方案collector:kind: StdOuttrial_template: 测试用例的写法goTemplate:rawTemplate: 字符串格式,k8s 各种job资源,yaml书写格式的字符串形式。

其中超参搜索算法支持:

Random SearchTree of Parzen Estimators (TPE)Grid SearchHyperbandBayesian OptimizationCMA Evolution Strategy

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

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

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

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

trialTemplate:goTemplate:rawTemplate: |-apiVersion: batch/v1kind: Jobmetadata:name: {{.Trial}}namespace: {{.NameSpace}}spec:template:spec:containers:- name: {{.Trial}}image: docker.io/kubeflowkatib/mxnet-mnistcommand:- "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

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

# Experiment 跑实例测试experiment = V1alpha3Experiment(api_version="/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中根据目标函数筛选目标函数最大或者最小时对应的超参取值。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。