机器学习和人工智能领域的最新进步令人惊叹!几乎每天都会出现新的突破性进展,从自动驾驶汽车到人工智能学习复杂的游戏。为了给公司带来真正的价值,数据科学家必须在公司的数据管线和基础设施上部署模型,不能仅限于在电脑上展示模型。
此外,数据科学家应该在改善机器学习应用上投入更多的精力,他们不需要花大量的时间手动更新应用,以应对不断变化的生产数据;也不需要在追溯和跟踪反常的过往行为中浪费时间。
Docker*和 Pachyderm*有助于数据科学家在生产集群上创建、部署和更新机器学习应用,在大数据集之间分配处理以及在数据管线中跟踪输入和输出数据。本文将展示如何利用英特尔® Nervana™ 技术、neon*和 Pachyderm设置生产就绪型机器学习工作流程。
英特尔® Nervana™ 技术和 neon*
包含 neon 的英特尔 Nervana 技术是“世界上速度最快的深度学习框架。”它是基于 Python* 的开源代码(请查看 GitHub*),包含一套用于深度学习模型开发的实用工具。
git clone https://github.com/NervanaSystems/neon.git cd neon; make
然后尝试创建 一些示例。
Pachyderm*
Pachyderm 是一个开源框架,提供基于容器(尤其是 Docker 容器)的数据版本和数据管线。Pachyderm 支持创建与语言无关的数据管线,Pachyderm 还控制每个管线阶段的输入和输出版本;类似于面向数据的 Git。您可以查看数据的 diff,利用 Pachyderm 的查询量和分支与团队成员开展合作。此外,如果数据管线生成了意外的结果,可以调试或验证结果(甚至完全复制结果),前提是了解结果产生的历史处理步骤。
仅仅通过向构成 Pachyderm 管线的每个容器展示一个数据子集,Pachyderm 便可以轻松地并行化计算。单个节点能看到每个文件的片段(map 任务)或整个文件(reduce 任务)。数据被放置于选中的对象存储中(如 S3),Pachyderm 将需要处理的各个数据片段智能地分配到不同的容器中。
Pachyderm 集群可以运行于任何云,您也可以尝试在本地运行 Pachyderm。安装了 Pachyderm CLI 工具(Pachctl)以及安装并运行了 Minikube*以后,可以利用单行命令在本地安装 Pachyderm:
pachctl deploy local
使用 Docker 化的 neon
为了在生产 Pachyderm 集群中利用 Neon(或仅仅为了轻松部署),需要 Docker 化 Neon。Docker 支持将机器学习应用打包成便携式映像,可以在安装了 Docker 的系统上以容器的形式运行该映像。因此,机器学习应用具有了便携性。
值得庆幸的是,可以公开获取面向 neon 的 Docker 映像,我们看一下映像是怎么运行的。假设您已经安装了 Docker并且只运行 CPU,通过调取以下映像(得到 neon 团队的认可)获得 Docker 化的 neon:
docker pull kaixhin/neon
为了在 Docker 内部交互地试验 neon,运行以下命令:
docker run -it kaixhin/neon /bin/bash
该命令将在 neon 映像(或容器)的运行例程中打开一个 bash shell,您可以在 bash shell 中创建并运行利用 neon 的 Python 程序。您也可以转到 Neon `示例
` (examples) 目录,在 Docker 内部运行 neon 示例模型。
如果我们已经有了一个利用 neon 的 Python 程序 `mymodel.py
`,并且想在 Docker 内部运行这个程序,需要创建一个包含本程序的定制 Docker 映像。如欲创建映像,只需在 `mymodel.py
` 脚本中创建一个名为 `Dockerfile
` 的文件:
my_project_directory ├── mymodel.py └── Dockerfile
`Dockerfile
` 将告知 Docker 如何创建一个的定制映像,该映像包含 neon 和基于 neon 的定制脚本。由于本示例中 `mymodel.py
` 只利用 Neon 和 Python 标准库,`Dockerfile
` 非常简单:
FROM kaixhin/neon ADD mymodel.py /
运行以下命令,创建定制 Docker 映像:
docker build -t mycustomimage .
在项目的根目录下运行。创建完成后,利用以下命令,在 Docker 运行的任意设备上运行 neon 模型:
docker run -it mycustomimage python /mymodel.py
在生产集群上分配 Docker 化 neon
按照上述步骤运行 Docker 化 neon 有助于提升便携性,但是没有必要为了部署单个模型例程,手动登录生产设备。我们需要将 neon 模型集成至在生成集群上运行的分布式数据管线上,并确保模型能在大型数据集上扩展。Pachyderm 能帮助我们实现上述目标。
下面将在可持续的生产就绪型数据管线上实施模型训练和推断。利用示例 LSTM 模型展示这个过程,该模型基于来自 IMDB 的训练数据集预测电影评论中的情感。获取该模型的更多信息。
训练
利用 Pachyderm,我们能够在处理阶段利用 Docker 容器创建数据管线。这些容器化的处理阶段将数据存储库中的版本化数据作为输入,输出至相应的数据存储库。因此,在 Pachyderm 中对每个处理阶段的输入/输出数据实行版本化。
为了训练 LSTM 模型,需要设置一个管线阶段。这个模型管线阶段将以带有标签的训练数据集 `labeledTrainData.tsv
` 作为输入,并持续输出(或保存于磁盘)经过训练的模型版本,输出的形式为一系列模型参数 imdb.p
` 和一个模型 vocab `imdb.vocab
`。利用 python 脚本 `train.py
` 处理这个阶段,该脚本已经包含在 公用 kaixhin/neon Docker 映像中。
为了创建上述管线,首先需要创建一个训练数据存储库,该存储库将输入模型管线阶段:
pachctl create-repo training
利用以下命令确认存储库已成功创建:
pachctl list-repo
为了处理训练存储库中的数据,需要创建模型管线阶段。为了创建模型管线阶段,向 Pachyderm 提供 JSON 管线规范,用于告知 Pachyderm 如何处理数据。本示例的 JSON 规范如下所示:
{"pipeline":{"name":"model" },"transform":{"image":"kaixhin/neon","cmd":["python","examples/imdb/train.py","-f","/pfs/training/labeledTrainData.tsv","-e","2","-eval","1","-s","/pfs/out/imdb.p","--vocab_file","/pfs/out/imdb.vocab" ] },"inputs":[ {"repo":{"name":"training" },"glob":"/" } ] }
规范看起来很复杂,实际上只包含几项说明。(1)创建名为模型 (model) 的管线阶段,(2)在管线阶段中利用 kaixhin/neon Docker 映像,(3)运行给出的 Python cmd以处理数据,(4)处理输入存储库训练 (training) 中的任何数据。目前,我们忽略了其他选择,但是在 Pachyderm 文档中全部涵盖。
获得 JSON 文件(保存于 `train.json
`)后,在生产就绪型 Pachyderm 集群上创建管线变得非常简单,命令如下所示:
pachctl create-pipeline -f train.json
现在,Pachyderm 将执行上述处理,在本示例中,Pachyderm 将利用训练存储库中的训练数据训练 neon 模型。事实上,由于 Pachyderm 进行数据版本化并且能够辨别新的数据,Pachyderm 将保持模型输出(在 Pachyderm 创建的相应的模型存储库中实行版本化)与训练数据的最新更新之间的同步。新的训练数据被提交至训练存储库后,Pachyderm 将在模型存储库中自动更新经过训练的永久性模型。
但是,我们还没有在训练存储库中添加任何数据,需要先完成这个操作。尤其需要将文件 `labeledTrainData.tsv
` 放入训练存储库的 master分支(再次利用类似 Git 的语义):
pachctl put-file training master labeledTrainData.tsv -c -f labeledTrainData.tsv
运行 pachctl list-repo
` 时,您将发现数据已经添加至训练存储库。此外,运行 `pachctl list-job
` 时,您会看到 Pachyderm 开始处理训练数据,并将永久性模型输出至模型存储库。这个任务结束后,模型训练完毕。通过向训练存储库输入新的训练数据或在模型管线阶段利用新映像更新管线,可以重新训练生产模型。
如果 Pachyderm 面向管线阶段在输出数据存储库中创建了 `imdb.p
` 和 `imdb.vocab
`,可以确认模型已被训练:
pachctl list-file model master
需要指出的是,将文件保存在 Pachyderm 的 `/pfs/out
` 目录(该目录指定与处理阶段相应的输出存储库)中,可以告知 Pachyderm 在存储库中编写的内容。
预测/推断
然后,将推断阶段添加至利用版本化、永久性模型的生产管线。推断阶段将在模型输入之前收集新的电影评论,推测出这些电影评论中的情感,并利用持久性模型输出。推断再次运行利用 neon 的 Python 脚本 `auto_inference.py
`。
为了创建推断管线阶段,首先需要创建对输入评论进行存储和版本化的 Pachyderm 存储库:
pachctl create-repo reviews
然后创建另一个 JSON 日志,该日志将告知 Pachyderm 如何执行推断阶段的处理:
{"pipeline":{"name":"inference" },"transform":{"image":"dwhitena/neon-inference","cmd":["python","examples/imdb/auto_inference.py","--model_weights","/pfs/model/imdb.p","--vocab_file","/pfs/model/imdb.vocab","--review_files","/pfs/reviews","--output_dir","/pfs/out" ] },"parallelism_spec":{"strategy":"CONSTANT","constant":"1" },"inputs":[ {"repo":{"name":"reviews" },"glob":"/*" }, {"repo":{"name":"model" },"glob":"/" } ] }
它和上一个 JSON 规范相似,只是本示例包含两个输入存储库(评论和 模型),我们使用了包含 `auto_inference.py
` 的另一种 Docker 映像。访问此处获取面向本映像的 Dockerfile。
只需运行以下命令,即可创建推断阶段:
pachctl create-pipeline -f infer.json
将新评论添加至评论 (reviews) 存储库后,Pachyderm 将看到新评论,执行推断并将推断结果输出至相应的推断 (inference) 目录。
事实上,我们已经向评论目录添加了 100 万条评论。如果在存储库中添加一条评论,Pachyderm 知道这是一条新评论后,只面向新评论更新结果。因为 Pachyderm 能够感知 diff ,保持处理与最新数据变化的同步,没有必要重新处理全部数据。
事实上,推断管线发挥批量和流推断管线的作用。您可以定期将许多评论添加至评论目录,在多个批次的评论中执行批量推断。您也可以创建个人评论后直接添加至存储库。无论使用哪种方式,Pachyderm 在新评论中自动执行推断并输出结果。
影响
将训练和推断结合到处理版本化数据的数据管线中,有助于我们利用价值极高的功能。数据科学家或工程师可以随时更新模型使用的训练数据集,在模型目录中创建永久性、版本化的全新模型。更新模型后,可以利用该模型处理进入评论存储库的任何新评论。
此外,利用更新模型可以重新计算之前的预测,或利用先前的版本化输入测试新模型。无需手动更新历史结果,更无需担心在生产中更换模型!
此外,尽管我们跳过了这个步骤,可以借助 并行规范对 Pachyderm 管线中的每个管线阶段进行单独扩展。如果一次性收到数万份评论,可以调整推断管线阶段的并行性,具体设置方法如下所示:
"parallelism_spec":{"strategy":"CONSTANT","constant":"10" }
或者将常量设置为大于 1 的任何数字。上述设置将告知 Pachyderm 启动多个 worker,以执行推断(上例需要 10 个 worker),Pachyderm 将在并行处理的 worker 之间自动划分评论数据。
我们可以重点关注开发和改善模型,Pachyderm 负责分配生产集群上的推断,还有助于确保实施的简单与可读性。可以将本地设备上开发的 Python/neon 脚本扩展为生产规模数据,无需考虑数据分片,利用 Dask* 等框架增加代码的复杂性,甚至面向生产使用将模型转换成其他语言或框架。
优化
尽管 Pachyderm 处理数据分片、并行性和协调分段,该管线为用户提供了几个出色的优化。
首先,训练和推断阶段都运行了导入 Neon 的 Python。我们可以利用 英特尔® Python 分发包* 进一步优化处理,无需修改任何代码。Python 分发包将强大的英特尔® 数学核心函数库(英特尔® MKL)、英特尔® 数据分析加速卡(英特尔® DAAL)与 pyDAAL、英特尔® MPI 库以及英特尔® 线程构建模块(英特尔® TBB)自动集成至内核 Python 分发包,包括 NumPy*、SciPy* 和 pandas*。
为了在 Pachyderm 中利用英特尔优化的 Python,只需将现有的 Neon 映像替换为基于某个公用英特尔 Python 映像的定制 Docker 映像。该映像的示例可以 由Dockerfile创建。您只需将您选取的 Python 脚本添加至映像(如 此处所示),将映像上传至 DockerHub(或另一个注册表),并在 Pachyderm 管线规范中修改参考映像的名称。
此外,我们可以将管线部署于 英特尔® 至强融核™ 处理器架构上,该架构自动提升机器学习工作流程的速度。面向深度学习训练和推断中的各类处理对芯片进一步优化。
结论/资源
我们能够在 neon 中方便快捷地实施深度学习,并将它部署到生产集群上,还能在集群上分配处理,无需担心分片数据或代码并行性。生产管线将跟踪模型的版本,使处理与数据更新保持同步。
上述数据管线的全部代码和配置可在此处获取。
Pachyderm 资源:
- 请加入 Pachyderm Slack team提问以及获取帮助。
- 请在 Twitter 上关注Pachyderm并
- 利用几行命令启用 Pachyderm,亲自尝试这个管线。
包含 Neon 的英特尔 Nervana 技术资源:
关于作者
Daniel (@dwhitena) 是一名拥有博士学位的数据科学家,目前就职于 Pachyderm (@pachydermIO)。Daniel 开发了创新型、分布式数据管线,包含预测模型、数据可视化、统计分析等。他在全球各大会议上发表演讲(ODSC、Spark 峰会、Datapalooza、DevFest Siberia、GopherCon等),在 Ardan 研究院 (@ardanlabs) 教授数据科学/工程,面向 Jupyter 维护 Go 内核,并积极支持各种开源数据科学项目的筹办。