您现在的位置是:首页 > 编程

kubeflow 使用教程

编程作者:chenli日期:2022-01-10 11:40:48点击:448

Introduction


可以看到新版的kubeflow多了很多功能。

这里按模块介绍下 Kubeflow 的几个核心组件。

  • Notebook Servers,作为一个管理线上交互实验的记录工具,可以帮助算法人员快速完成算法实验,同时notebook server 提供了统一的文档管理能力。
  • AutoML,提供自动化的服务,对特征处理、特征选择、模型选择、模型参数的配置、模型训练和评估等方面,实现了全自动建模,降低算法人员手动实验次数。
  • Pipeline,提供一个算法流水线的工程化工具,将算法各流程模块以拓扑图的形式组合起来,同时结合 argo 可以实现 MLOps。
  • Serverless,将模型直接发布成一个对外的服务,缩短从实验到生产的路径。

Notebook Servers

notebook 可以说是做机器学习最喜欢用到的工具了,完美的将动态语言的交互性发挥出来,kubeflow 提供了 jupyter notebook 来快速构建云上的实验环境,这里以一个我们自定义的镜像为例:

我们创建了一个test-for-jupyter名字的镜像,配置了一个 tensorflow 的镜像,点击启动,我们可以看到在kubeflow-user-example-com命名空间下已经创建我们的应用了:

  1. kubectl get po -nkubeflow-user-example-com
  2. NAME READY STATUS RESTARTS AGE
  3. ml-pipeline-ui-artifact-6d7ffcc4b6-9kxkk 2/2 Running 0 48m
  4. ml-pipeline-visualizationserver-84d577b989-5hl46 2/2 Running 0 48m
  5. test-for-jupyter-0 0/2 PodInitializing 0 44s

创建完成后点击 connect 就可以进入我们创建的应用界面中了


在 jupyterlab 环境中开发人员可以很方便的进行算法实验,同时由于运行在云上利用 k8s api甚至可以很方便构建k8s资源,比如通过 kfserving 创建一个ML服务。

AutoML

AutoML 是机器学习比较热的领域,主要用来模型自动优化和超参数调整,这里其实是用的 Katib来实现的,一个基于k8s的 AutoML 项目,详细见https://github.com/kubeflow/katib。

Katib 主要提供了 超参数调整(Hyperparameter Tuning),早停法(Early Stopping)和神经网络架构搜索(Neural Architecture Search)

这里以一个随机搜索算法为例:

  1. apiVersion: "kubeflow.org/v1beta1"
  2. kind: Experiment
  3. metadata:
  4. namespace: kubeflow-user-example-com
  5. name: random-example
  6. spec:
  7. objective:
  8. type: maximize
  9. goal: 0.99
  10. objectiveMetricName: Validation-accuracy
  11. additionalMetricNames:
  12. - Train-accuracy
  13. algorithm:
  14. algorithmName: random
  15. parallelTrialCount: 3
  16. maxTrialCount: 12
  17. maxFailedTrialCount: 3
  18. parameters:
  19. - name: lr
  20. parameterType: double
  21. feasibleSpace:
  22. min: "0.01"
  23. max: "0.03"
  24. - name: num-layers
  25. parameterType: int
  26. feasibleSpace:
  27. min: "2"
  28. max: "5"
  29. - name: optimizer
  30. parameterType: categorical
  31. feasibleSpace:
  32. list:
  33. - sgd
  34. - adam
  35. - ftrl
  36. trialTemplate:
  37. primaryContainerName: training-container
  38. trialParameters:
  39. - name: learningRate
  40. description: Learning rate for the training model
  41. reference: lr
  42. - name: numberLayers
  43. description: Number of training model layers
  44. reference: num-layers
  45. - name: optimizer
  46. description: Training model optimizer (sdg, adam or ftrl)
  47. reference: optimizer
  48. trialSpec:
  49. apiVersion: batch/v1
  50. kind: Job
  51. spec:
  52. template:
  53. spec:
  54. containers:
  55. - name: training-container
  56. image: docker.io/kubeflowkatib/mxnet-mnist:v1beta1-45c5727
  57. command:
  58. - "python3"
  59. - "/opt/mxnet-mnist/mnist.py"
  60. - "--batch-size=64"
  61. - "--lr=${trialParameters.learningRate}"
  62. - "--num-layers=${trialParameters.numberLayers}"
  63. - "--optimizer=${trialParameters.optimizer}"
  64. restartPolicy: Never

这里以一个简单的神经网络为例,该程序具有三个参数 lr, num-layers, optimizer,采用的算法是随机搜索,目标是最大化准确率(accuracy)。

可以直接在界面中填上yaml文件,然后提交,完成后会生成一张各参数和准确率的关系图和训练列表:

Experiments and Pipelines

experiments 为我们提供了一个可以创建实验空间功能, pipeline 定义了算法组合的模板,通过 pipeline 我们可以将算法中各处理模块按特定的拓扑图的方式组合起来。

这里可以看看官方提供的几个 pipeline 例子:

kubeflow pipeline 本质是基于 argo workflow 实现,由于我们的kubeflow是基于kind上构建的,容器运行时用的containerd,而workflow默认的pipeline执行器是docker,因此有些特性不兼容,这块可以见 argo workflow 官方说明:https://argoproj.github.io/argo-workflows/workflow-executors/。
这里我是把 workflow 的 containerRuntimeExecutor 改成了 k8sapi。但 k8sapi 由于在 workflow 是二级公民,因此有些功能不能用,比如 kubeflow pipeline 在 input/output 的 artifacts 需要用到 docker cp 命令,可以参考这个issue: https://github.com/argoproj/argo-workflows/issues/2685#issuecomment-613632304

由于以上原因 kubeflow 默认给的几个案例并没有用 volumes 是无法在 kind 中运行起来,这里我们基于 argo workflow 语法自己实现一个 pipeline

基于pipeline构建一个的工作流水

第一步,构建一个 workflow pipeline 文件:

  1. apiVersion: argoproj.io/v1alpha1
  2. kind: Workflow
  3. metadata:
  4. generateName: kubeflow-test-
  5. spec:
  6. entrypoint: kubeflow-test
  7. templates:
  8. - name: kubeflow-test
  9. dag:
  10. tasks:
  11. - name: print-text
  12. template: print-text
  13. dependencies: [repeat-line]
  14. - {name: repeat-line, template: repeat-line}
  15. - name: repeat-line
  16. container:
  17. args: [--line, Hello, --count, '15', --output-text, /gotest/outputs/output_text/data]
  18. command:
  19. - sh
  20. - -ec
  21. - |
  22. program_path=$(mktemp)
  23. printf "%s" "$0" > "$program_path"
  24. python3 -u "$program_path" "$@"
  25. - |
  26. def _make_parent_dirs_and_return_path(file_path: str):
  27. import os
  28. os.makedirs(os.path.dirname(file_path), exist_ok=True)
  29. return file_path
  30. def repeat_line(line, output_text_path, count = 10):
  31. '''Repeat the line specified number of times'''
  32. with open(output_text_path, 'w') as writer:
  33. for i in range(count):
  34. writer.write(line + '\n')
  35. import argparse
  36. _parser = argparse.ArgumentParser(prog='Repeat line', description='Repeat the line specified number of times')
  37. _parser.add_argument("--line", dest="line", type=str, required=True, default=argparse.SUPPRESS)
  38. _parser.add_argument("--count", dest="count", type=int, required=False, default=argparse.SUPPRESS)
  39. _parser.add_argument("--output-text", dest="output_text_path", type=_make_parent_dirs_and_return_path, required=True, default=argparse.SUPPRESS)
  40. _parsed_args = vars(_parser.parse_args())
  41. _outputs = repeat_line(**_parsed_args)
  42. image: python:3.7
  43. volumeMounts:
  44. - name: workdir
  45. mountPath: /gotest/outputs/output_text/
  46. volumes:
  47. - name: workdir
  48. persistentVolumeClaim:
  49. claimName: kubeflow-test-pv
  50. metadata:
  51. annotations:
  52. - name: print-text
  53. container:
  54. args: [--text, /gotest/outputs/output_text/data]
  55. command:
  56. - sh
  57. - -ec
  58. - |
  59. program_path=$(mktemp)
  60. printf "%s" "$0" > "$program_path"
  61. python3 -u "$program_path" "$@"
  62. - |
  63. def print_text(text_path): # The "text" input is untyped so that any data can be printed
  64. '''Print text'''
  65. with open(text_path, 'r') as reader:
  66. for line in reader:
  67. print(line, end = '')
  68. import argparse
  69. _parser = argparse.ArgumentParser(prog='Print text', description='Print text')
  70. _parser.add_argument("--text", dest="text_path", type=str, required=True, default=argparse.SUPPRESS)
  71. _parsed_args = vars(_parser.parse_args())
  72. _outputs = print_text(**_parsed_args)
  73. image: python:3.7
  74. volumeMounts:
  75. - name: workdir
  76. mountPath: /gotest/outputs/output_text/
  77. volumes:
  78. - name: workdir
  79. persistentVolumeClaim:
  80. claimName: kubeflow-test-pv
  81. metadata:
  82. annotations:

argo workflow 的语法可以参考:https://argoproj.github.io/argo-workflows/variables/

这里我们定义了两个任务 repeat-line 和 print-text, repeat-line 任务会将生产结果写入 kubeflow-test-pv 的 PVC 中, print-text 会从 PVC 中读取数据输出到 stdout。

这里由于用到 PVC,我们需要先在集群中创建一个kubeflow-test-pv的PVC:

  1. apiVersion: v1
  2. kind: PersistentVolumeClaim
  3. metadata:
  4. name: kubeflow-test-pv
  5. namespace: kubeflow-user-example-com
  6. spec:
  7. accessModes:
  8. - ReadWriteOnce
  9. resources:
  10. requests:
  11. storage: 128Mi

第二步,定义好 pipeline 文件后可以创建pipeline:

第三步,启动一个pipeline:

启动 pipeline 除了单次运行模式 one-off,也支持定时器循环模式 Recurring,这块可以根据自己的需求确定。

查看运行结果:

运行完后,可以将实验进行归档(Archived)。

关于 MLOps 的一点思考

我们来看一个简单的 ML 运作流程:

这是一个 google 提供的 level 1 级别的机器学习流水线自动化,整个流水线包括以下几部分:

  • 构建快速算法实验的环境(experimentation),这里的步骤已经过编排,各个步骤之间的转换是自动执行的,这样可以快速迭代实验,并更好地准备将整个流水线移至生产环境,在这个环境中算法研究员只进行模块内部的工作。
  • 构建可复用的生产环境流水线,组件的源代码模块化,实验环境模块化流水线可以直接在 staging 环境和 production 环境中使用。
  • 持续交付模型,生产环境中的机器学习流水线会向使用新数据进行训练的新模型持续交付预测服务。

基于上述功能描述我们其实可以基于 kubeflow 的 pipelinekfserving 功能轻松实现一个简单的 MLOps 流水线发布流程。不过,值得注意的是,DevOps 本身并不仅仅是一种技术,同时是一种工程文化,所以在实践落地中需要团队各方的协同分阶段的落地。这块可以参考《MLOps: Continuous delivery and automation pipelines in machine learning》《Hidden Technical Debt in Machine Learning Systems》

参考文献

原文来自:https://github.com/shikanon/kubeflow-manifests/blob/master/docs/introduction.md

文章评论