Pachyderm-可复现的数据科学-全-
Pachyderm 可复现的数据科学(全)
原文:
annas-archive.org/md5/daa8f16fb595e16a266512112b9ef347译者:飞龙
前言
Pachyderm 是一个分布式版本控制平台,用于构建端到端的数据科学工作流。自 2016 年创建以来,Pachyderm 已经成为大小组织的首选解决方案。Pachyderm 的核心功能是开源的,并且围绕它有一个活跃的工程师社区。本书带你走过 Pachyderm 使用的基础和高级示例,帮助你快速上手并将可靠的数据科学解决方案集成到你的基础设施中。
使用 Pachyderm 实现可重复的数据科学 提供了对 Pachyderm 的清晰概述,以及如何在云中安装和运行 Pachyderm 的说明,还介绍了如何使用 Pachyderm 的软件即服务(SaaS)版本——Pachyderm Hub。本书包含了在 Pachyderm 集群上运行的数据科学技术的实际示例。
这本书的适用人群
本书适用于希望为数据科学项目构建可扩展基础设施的初学者和有经验的数据科学家及机器学习工程师。具备基本的 Python 编程和 Kubernetes 知识将有所帮助,熟悉 GoLang 者优先。
本书涵盖内容
第一章,数据可重复性问题,讨论了现代科学和数据科学中可重复性的问题,以及它如何与 Pachyderm 的使命相一致。
第二章,Pachyderm 基础,介绍了 Pachyderm 的基本概念和原语。
第三章,Pachyderm 管道规范,提供了 Pachyderm 规范文件的详细概述,这是 Pachyderm 管道的主要配置文件。
第四章,在本地安装 Pachyderm,带你了解如何在本地计算机上安装 Pachyderm。
第五章,在云平台上安装 Pachyderm,介绍了如何在三个主要的云平台上安装 Pachyderm:Amazon Elastic Kubernetes Service(EKS)、Google Kubernetes Engine(GKE)和 Microsoft Azure Kubernetes Service(AKS)。
第六章,创建您的第一个管道,介绍了如何创建一个简单的处理图像的管道。
第七章,Pachyderm 操作,介绍了最常用的操作。
第八章,创建端到端的机器学习工作流,展示了如何在一个示例自然语言处理(NLP)管道上部署端到端的机器学习工作流。
第九章,使用 Pachyderm 进行分布式超参数调优,介绍了如何使用命名实体识别(NER)管道进行分布式超参数调优。
第十章,巨兽语言客户端,带你了解使用 Pachyderm Python 和 Golang 客户端的最常见示例。
第十一章,使用 Pachyderm 笔记本,讨论了 Pachyderm Hub,Pachyderm 的软件即服务(SaaS)平台,并且你将了解 Pachyderm 笔记本,这是一个为数据科学家设计的集成开发环境(IDE)。
为了最大限度地发挥本书的效果
你需要在电脑上安装最新版本的 Pachyderm。本书中的所有操作均在 macOS 的 Pachyderm 2.0 版本上进行测试。不过,这些操作也应该适用于未来版本的发布。如果你使用的是 Windows,所有操作必须在Windows 子系统 Linux(WSL)中执行。

你需要申请 Pachyderm 的企业版才能使用 Pachyderm 控制台。Pachyderm 为首次用户提供免费的试用许可。然而,大多数示例在没有企业许可的情况下也可以正常工作。为了测试第十一章,使用 Pachyderm 笔记本,你需要创建一个 Pachyderm Hub 账户。
如果你正在使用本书的电子版,我们建议你自己输入代码,或访问本书 GitHub 仓库中的代码(下一节会提供链接)。这样做可以帮助你避免因复制粘贴代码而可能出现的错误。
下载示例代码文件
你可以从 GitHub 下载本书的示例代码文件,链接:github.com/PacktPublishing/Reproducible-Data-Science-with-Pachyderm。如果代码有更新,GitHub 仓库中的代码也会随之更新。
我们还提供了其他来自我们丰富书籍和视频目录的代码包,网址:github.com/PacktPublishing/。快来看看吧!
下载彩色图像
我们还提供了一份 PDF 文件,包含本书中使用的截图和图表的彩色图像。你可以在此下载:static.packt-cdn.com/downloads/9781801074483_ColorImages.pdf。
使用的约定
本书中使用了一些文本约定。
文本中的代码:表示文本中的代码词、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟网址、用户输入和 Twitter 用户名。示例如下:“将下载的WebStorm-10*.dmg磁盘映像文件挂载为系统中的另一个磁盘。”
代码块如下所示:
image = displacy.render(textfile, style='dep', options={"compact": True, "distance": 70})
f = open('/pfs/out/pos-tag-dependency.svg', "w")
f.write(image)
f.close()
任何命令行输入或输出均以以下形式呈现:
$ minikube start
粗体:表示一个新术语、一个重要的词,或者你在屏幕上看到的词。例如,菜单或对话框中的文字通常以粗体显示。示例如下:“从管理面板中选择系统信息。”
提示或重要说明
如下所示。
联系我们
我们始终欢迎读者的反馈。
一般反馈:如果你对本书的任何方面有疑问,请发送电子邮件至 customercare@packtpub.com,并在邮件主题中注明书名。
勘误:虽然我们已尽力确保内容的准确性,但错误仍然可能发生。如果你在本书中发现错误,我们将不胜感激你能向我们报告。请访问 www.packtpub.com/support/errata 并填写表格。
盗版:如果你在互联网上发现任何形式的非法复制我们的作品,我们将非常感激你能提供该材料的位置地址或网站名称。请通过电子邮件联系我们,邮箱地址为 copyright@packt.com,并附上相关链接。
如果你有兴趣成为作者:如果你在某个领域有专业知识,并且有意撰写或参与编写书籍,请访问 authors.packtpub.com。
分享你的想法
一旦你读完了 Reproducible Data Science with Pachyderm,我们非常希望听到你的想法!请 点击这里直接前往亚马逊评论页面 分享你的反馈。
你的评价对我们和技术社区都非常重要,能帮助我们确保提供高质量的内容。
第一部分:Pachyderm 简介与可重现的数据科学
本节介绍了 Pachyderm 的基础知识,并描述了数据可重现性对企业级数据科学平台的重要性。你将了解 Pachyderm 解决方案的主要支柱,包括仓库、数据单元、任务,以及其中最重要的——管道。本章还简要讨论了 AI 的伦理问题,特别是在可重现性方面。
本节包含以下章节:
-
第一章,数据可重现性的问题
-
第二章,Pachyderm 基础
-
第三章,Pachyderm 管道规范
第一章:第一章:数据可复现性问题
如今,机器学习算法无处不在。它们已融入我们的日常生活中,我们使用它们时往往没有察觉。当我们匆忙赶去工作、规划假期或去看医生时,模型正在运行,甚至有时在为我们做出重要决策。如果我们不清楚模型在做什么以及它如何做出决策,我们如何能确保它的决策是公平公正的呢?Pachyderm 深刻关注数据科学实验的可复现性,并将数据血统、可复现性和版本控制作为核心。 但在继续之前,让我们先讨论一下为什么可复现性如此重要。
本章解释了可复现性、伦理人工智能(AI)和机器学习操作(MLOps)的概念,并概述了现有的数据科学平台以及它们与Pachyderm的比较。
在这一章中,我们将讨论以下主要话题:
-
为什么可复现性如此重要?
-
科学中的可复现性危机
-
解密 MLOps
-
数据科学平台的类型
-
解释伦理 AI
为什么可复现性如此重要?
首先,让我们定义一下 AI、ML 和数据科学。
数据科学是一个研究领域,涉及收集和准备大量数据,以提取知识并生成洞察。
人工智能(AI)是一个总括性的术语,指的是使机器能够模仿人类行为的技术。机器学习(ML)是 AI 的一个子集,基于这样的理念:算法可以通过过去的经验进行学习。
现在,让我们来定义一下可复现性。如果其他数据科学家能够在类似的数据集和问题上重复实验并得到类似的结果,那么这个数据科学实验就被认为是可复现的。虽然可复现性几十年来一直是科学研究的支柱,但它直到最近才成为数据科学领域的重要话题。
一个可复现的实验不仅更可能没有错误,而且还可以推动实验进一步发展,并允许其他人基于该实验进行构建,促进知识的转移并加速未来的发现。
数据科学已成为过去十年里最热门的话题之一,这一点毫不意外。许多大型科技公司开设了数十个高薪的数据科学家、数据工程师和数据分析师职位。因此,加入这个行业的需求正在迅速增加。根据斯坦福大学人类中心人工智能研究院(HAI)发布的《AI 指数 2019 年年报》,过去 20 年中,AI 论文数量增长了三倍。你可以在斯坦福大学 HAI 网站上阅读更多关于该报告的内容:hai.stanford.edu/blog/introducing-ai-index-2019-report。

图 1.1 – AI 出版物趋势,来自 AI 指数 2019 年年度报告(第 5 页)
几乎每个平台和大学现在都提供数据科学或 AI 课程,这些课程从不缺少学生。成千上万来自各行各业的人,从软件开发者到 CEO,都在参加机器学习(ML)课程,以跟上迅速发展的行业。
AI 会议的数量也在稳步增长。即使在疫情期间,面对面活动变得不可能,AI 社区依然以虚拟形式继续举行会议。像神经信息处理系统(NeurIPS)和国际机器学习会议(ICML)等旗舰会议,通常吸引超过 10,000 名参会者,仍然在线举行,并有大量参与者。
根据一些预测,到 2025 年,AI 市场规模将超过 3500 亿美元。仅在 2020 年至 2021 年间,市场从 120 亿美元增长到 580 亿美元。硅谷的科技巨头们正在激烈争夺在这一领域的主导地位,而较小的公司也在崭露头角,争取市场份额。全球 AI 初创企业的数量稳步增长,每年都有数十亿资金注入其中。
以下图表展示了近年来 AI 相关初创企业的增长:

图 1.2 – 全球 AI 相关初创企业的总私人投资,来自 AI 指数 2019 年年度报告(第 88 页)
AI 初创企业的总私人投资在过去 10 年中增长了超过 30 倍。
同一来源的另一个有趣指标是 2015 至 2018 年间发布的 AI 专利数量:

图 1.3 – AI 专利总数(2015-2018 年),来自 AI 指数 2019 年年度报告(第 32 页)
美国在专利发布数量上领先于其他国家。
这些趋势促进了经济和产业的发展,但不可避免地影响了提交的 AI 论文、流程、实践和实验的质量。这就是为什么需要一个适当的过程来确保数据科学模型的验证。实验的重复性是数据科学模型质量控制的重要组成部分。
接下来,让我们了解什么是模型。
什么是模型?
让我们定义一下什么是模型。数据科学或人工智能模型是对一个过程的简化表示,并且可以预测可能的结果。无论是天气预测算法还是网站访问量计算器,模型都会提供最可能的结果,并帮助我们做出明智的决策。当数据科学家创建模型时,他们需要决定模型中必须包含哪些关键参数,因为他们不可能涵盖所有内容。因此,模型是一个简化的过程版本。而在这过程中,数据科学家或组织会根据成功的定义做出一些取舍。
以下图表展示了一个数据模型:

图 1.4 – 数据科学模型
每个模型都需要持续的数据流来进行改进并确保正确执行。以亚马逊 Go 商店为例,商店内通过多台摄像头分析顾客的行为。确保商店安全的模型会不断基于现实中的顾客行为进行训练。这些模型必须学习到顾客有时会拿起某个商品然后改变主意再放回去;有时顾客可能会把商品掉到地上,导致产品损坏,等等。亚马逊 Go 商店的模型之所以优秀,是因为它能访问大量的真实数据,并且随着时间的推移不断改进。然而,并非所有模型都能访问真实数据,这时候可以使用合成数据集。
合成数据集是由计算机人工生成的数据集。合成数据的问题在于,它的质量仅与生成它的算法相关。通常,这种数据无法准确反映现实世界。在某些情况下,比如当用户隐私问题阻止数据科学家使用真实数据时,使用合成数据集是合理的;而在其他情况下,它可能会导致负面结果。
IBM 的 Watson 是一个雄心勃勃的项目,承诺通过在几秒钟内根据提供的症状列表诊断患者,从而革新医疗保健。这项发明能够极大地加快诊断过程。在地球上一些无法获得医疗服务的地方,像这样的系统能够挽救许多生命。不幸的是,由于最初的承诺是取代医生,Watson 只不过是一个能够辅助诊断的推荐系统,仅此而已。原因之一是 Watson 使用了合成数据集进行训练,而非真实数据。
有些情况下,检测训练模型中的问题尤其困难。以华盛顿大学开发的一个图像识别算法为例,该算法用于识别图像中是否出现了哈士奇或狼。该模型看似运行得很好,预测的准确率接近 90%。然而,当科学家们深入研究算法和数据时,他们发现模型是基于背景进行预测的。大多数包含哈士奇的图像背景是草地,而大多数包含狼的图像背景则是雪地。
可重复性的主要原则
如何确保你公司中的数据科学流程遵循可重复性原则?以下是可重复性原则的主要内容:
-
使用开放数据:用于训练模型的数据不应是一个黑箱。它必须以未修改的状态对其他数据科学家开放。
-
对大量样本进行训练:关于实验和训练样本数量的信息必须可以供审查。
-
严格记录过程:数据修改、统计失败和实验表现的过程必须彻底记录,以便作者和其他数据科学家可以在未来复现该实验。
让我们考虑一些例子,其中可重复性、协作和开放数据原则并未融入实验过程中。
几年前,一组来自杜克大学的科学家因提出了一个雄心勃勃的预测肺癌发展趋势的研究而广受关注。该研究基于从患者身上收集的数据,预测了肺癌的进程,医学界对这一发现充满了期待。然而,来自休斯顿MD 安德森癌症中心的另一组科学家在尝试复现原始结果时发现了该研究中的严重错误。他们发现化疗预测模型中存在标签错误、基因与基因表达数据的不匹配等问题,这些问题使得基于模型计算得出的正确治疗建议的可能性大大降低。尽管这些缺陷最终被揭示出来,但研究人员花费了近三年的时间和超过 2000 个工作小时才揭开真相,而这些问题本可以通过最初就建立适当的研究实践来避免。
现在让我们通过一个聊天机器人例子来看一下AI是如何出错的。你可能还记得微软那个臭名昭著的聊天机器人泰(Tay)。泰是一个可以从与互联网用户的对话中学习的机器人。当泰上线时,最初的对话是友好的,但一夜之间他的语言发生了变化,开始发布有害、种族歧视和不当的回应。他从教他粗鲁语言的用户那里学习,而由于该机器人被设计成模仿人类行为,他做了他被创造的事情。你可能会问,为什么他一开始不是种族歧视的?答案是他是在清洁、精挑细选的数据上进行训练的,这些数据没有包含粗俗和侮辱性语言。但我们无法控制互联网和人们发布的内容,而且这个机器人没有被编程任何道德感。这个实验引发了许多关于 AI 伦理的问题,以及我们如何确保我们构建的 AI 不会有一天反过来伤害我们。
新一代聊天机器人基于最近发布的GPT-3库。这些聊天机器人通过神经网络进行训练,在训练过程中创建了无法打破的关联。尽管这些聊天机器人背后使用了比其前身看似更先进的技术,但它们仍然可能根据训练数据的不同而变得种族歧视和充满仇恨。如果一个机器人在性别歧视和仇恨的对话中进行训练,它会变得冒犯性,并且可能会做出不当回应。
正如你所看到的,数据科学、AI 和机器学习是帮助我们解决许多困难问题的强大技术,但与此同时,它们也可能危害用户,并产生毁灭性后果。数据科学界需要努力制定更好的方法,减少不良后果,通过建立适当的标准和流程来确保数据科学实验和 AI 软件的质量。
既然我们已经了解了可重复性为何如此重要,那么让我们看看它对科学界和数据科学带来了哪些后果。
科学中的可重复性危机
可重复性危机是一个存在了十多年之久的问题。由于数据科学与科学学科关系密切,回顾过去许多科学家提出的问题,并将其与数据科学领域今天面临的类似问题联系起来是非常重要的。
最重要的问题之一是可重复性——复制科学实验结果的能力一直是良好研究的基石。换句话说,如果一个实验可以被重复,那么它是有效的;如果不能,那么它可能只是一次性的事件,不代表真实现象。不幸的是,近年来,越来越多的社会学、医学、生物学及其他领域的研究论文无法经受住对更多样本进行重测的考验,即便这些论文已发表在知名且可信的科学杂志上,例如Nature。这种趋势可能导致公众对科学及其分支 AI 产生不信任。
如前所述,由于 AI 行业的流行和发展,AI 论文的数量增加了数倍。不幸的是,这些论文的质量并未随着数量的增加而提升。
Nature杂志最近对科学家进行了一项调查,询问他们是否认为科学界存在可重复性危机。大多数科学家认为,由于频繁发表结果的压力,假阳性结果确实存在。研究人员需要资助,赞助商需要看到结果以便进一步投资研究,这导致许多已发表的论文信誉度下降。最终,争夺资助和官僚主义常常被认为是实验室中缺乏可重复性过程的主要原因。
被质疑完整性的研究论文具有以下共同特点:
-
没有公开共享代码或数据供其他研究人员尝试复制结果。
-
尝试复制结果的科学家未能完全或部分地按照提供的说明进行实验。
即使是诺贝尔奖得主发布的论文,有时也会因无法复制结果而受到质疑。例如,2014 年,Science杂志撤回了诺贝尔奖得主、免疫学家布鲁斯·贝特勒(Bruce Beutler)发表的一篇论文。这篇论文讲述了人类基因组中病毒样生物体对病原体的反应。在撤回前,这篇论文已被引用超过 50 次。
当 COVID-19 成为 2020 年的主要话题时,发布了多篇相关论文。根据Retraction Watch,一个追踪撤回科研论文的在线博客,截至 2021 年 3 月,已有超过 86 篇论文被撤回。
2019 年,超过 1400 篇科学论文被多个出版商撤回。这个数字非常庞大,且稳步增长,而 2000 年初仅有 50 篇论文被撤回。这引起了人们对所谓科学可重复性危机的关注。虽然并非所有被撤回的论文都是因为这个原因,但很多时候确实是由于此原因。
数据钓鱼
数据钓鱼或数据开采是一种通过多次运行计算来达到统计学上显著的实验结果的方法,直到得到预期结果,然后只报告这些结果,忽略那些不便的结果。有时,科学家无意中进行数据开采,以获得他们认为最可能的结果并确认假设。也有可能发生更为险恶的情况——科学家可能故意篡改实验结果,以达成预定结论。
这种数据分析误用的一个例子是,如果你决定证明香蕉消费与 10 岁及以上儿童智商水平提高之间的相关性。这是一个完全虚构的例子,但假设你想要建立这种联系。你需要获取一个足够大的样本群体中,孩子们的智商水平和香蕉消费情况——假设是 5,000 名孩子。
然后,你可以进行一些测试,例如:吃香蕉并锻炼的孩子是否比仅仅锻炼的孩子拥有更高的智商?看电视并吃香蕉的孩子是否比不看电视的孩子智商更高? 在进行了足够多次测试后,你很可能会得到某种相关性。然而,这个结果并不显著,且使用数据开采技术被科学界认为是极不道德的。在数据科学领域,类似的问题也时有发生。
在没有进行全面调查的情况下,检测数据开采可能会很困难。可以考虑以下几个可能的因素:
-
这项研究是由一个声誉良好的机构或科学家小组进行的吗?
-
其他类似领域的研究有什么建议?
-
是否涉及财务利益?
-
该声明是否耸人听闻?
没有适当流程的情况下,数据开采和不可靠的研究者将继续被发表。最近,自然杂志对约 1,500 名来自不同领域的研究人员进行了调查,超过 50%的受访者表示他们曾尝试并未能成功复制过去研究的结果。更令人震惊的是,在许多情况下,他们未能复制自己实验的结果。
在所有受访者中,只有 24%的人能够成功发布他们的复制尝试,而大多数人从未接到要求复制他人研究的请求。
当然,提高实验的可重复性是一个高成本的问题,可能会使实验所需的时间翻倍,这对于许多研究实验室来说可能是无法承受的。但如果将其加入到原本计划中的研究时间,并且有合适的流程,它就不应该像在研究生命周期中途加入那么困难或严格。
更糟的是,在论文发布后撤回论文可能是一项繁琐的任务。有些出版商甚至会在论文被撤回时向研究人员收取大量费用。这种做法实在令人沮丧。
所有这些都会对全球研究产生负面影响,导致对科学的信任度下降。各组织必须采取措施改善其科学部门的流程,科学期刊必须提高发布研究的标准。
既然我们已经了解了数据捕捞,接下来让我们回顾更好的可重复性指南。
更好的科学研究可重复性指南
开放科学中心(COS),一个专注于支持和促进开放科学倡议、可重复性和科学研究诚信的非营利组织,发布了《期刊政策和实践中的透明性和开放性推广指南(TOP)》,或称为TOP 指南。这些指南强调了已发表研究论文中透明性的重要性。研究人员可以利用这些指南为公开共享研究成果的必要性提供依据,以避免关于其研究完整性的任何质疑。
TOP 指南的主要原则包括以下几点:
-
正确引用和给予原作者信用:所有属于其他作者的文本、代码和数据成果,必须在论文中明确列出,并根据需要给予适当的信用。
-
数据、方法论和研究材料透明性:论文的作者必须在一个公开可访问的位置共享已编写的代码、方法论和研究材料,并提供如何访问和使用它们的说明。
-
设计和分析透明性:作者应尽可能透明地展示其方法论,尽管这可能会根据行业不同而有所不同。至少,他们必须披露在研究过程中应用的标准。
-
研究和分析计划的预注册:即使研究未发表,预注册也能使其更容易被发现。
-
获得结果的可重复性:作者必须包括足够的细节,说明如何重复原始结果。
这些指标应用于所有这三种级别:
-
未实施—报告中未包含相关信息
-
1 级—按需提供
-
2 级—发布前可访问
-
3 级—发布前验证
3 级是透明度可以达到的最高水平。拥有这种透明度就能为提交的研究质量提供充分的证明。COS 通过TOP 因子来评定期刊在确保透明度方面的努力,最终评定所发布研究的质量。
除了数据和代码的可复现性外,研究过程中使用的环境和软件往往起着重要作用。新技术,如容器、虚拟环境和云环境,使得在研究中实现统一变得更加容易。当然,如果我们考虑到生物化学或其他需要更精确实验室条件的行业,达到统一性可能会更加复杂。
现在让我们了解一些有助于提高复现性的常见做法。
提高复现性的常见做法
得益于复现性倡导者的努力,以及近年来该问题在科学社区的广泛讨论,似乎有一些提高复现性的积极趋势正在出现。这些实践包括以下内容:
-
请求同事再现你的工作。
-
开发详尽的文档。
-
标准化研究方法。
-
在发表前预注册你的研究,以避免数据挑选。
有些科学小组将复现并通知研究人员论文中的错误作为他们的使命。他们的典型流程是尝试再现论文中的结果,并向研究人员或实验室发信请求更正或撤回。有些研究人员愿意合作并纠正论文中的错误,但在其他情况下,情况不明确且困难。某些小组已识别出他们分析的 25 篇论文中的以下问题:
-
缺乏有关应将反馈意见提交给谁的流程或联系人。科学期刊并未明确说明是否可以将反馈提交给主编,或者是否有某种反馈提交表格。
-
科学期刊编辑通常不愿意接受并处理提交的意见。在某些情况下,即便是来自知名机构的批评性反馈,也可能需要长达一年的时间才能在论文上发布警告。
-
一些出版商要求你支付费用,如果你想发表更正信函,并且会延迟撤回。
-
原始数据并不总是公开可用。在许多情况下,出版商没有围绕研究中使用的原始数据设立统一的流程或共享位置。如果你必须直接联系作者,你可能无法获得所请求的信息,而且这可能会显著延迟进程。此外,他们还可以简单地拒绝此类请求。
提交更正和研究论文撤回缺乏标准化,导致整体复现性危机和知识共享的困境。那些利用数据挖掘和其他手段操控结果的论文,将成为未来研究者的信息来源,进一步加剧整体的错误信息和混乱。研究人员、出版商和编辑应共同努力,建立统一的出版后审查指南,鼓励其他科学家参与测试并提供反馈。
我们已经了解了可重复性如何影响研究质量。现在,让我们回顾一下组织如何建立一个流程,以确保他们的数据科学实验遵循最佳行业实践,以确保高标准。
解密 MLOps
本节定义了机器学习操作(MLOps),并描述了为什么在数据科学部门内建立一个可靠的 MLOps 过程至关重要。
在许多组织中,数据科学部门是最近几年才成立的。数据科学家这一职业也相对较新。因此,许多部门必须找到一种方法将其融入现有的企业流程,并制定确保数据科学成果的可靠性和可扩展性的方法。
在许多情况下,构建合适的基础设施的责任落在数据科学家身上,而他们往往对最新的基础设施趋势不太熟悉。另一个问题是如何在不同的语言、平台和环境中使其正常运行。最终,数据科学家在构建基础设施上花费的时间远多于在模型本身上工作。这就是新兴学科的出现,它帮助弥合数据科学与基础设施之间的差距。
MLOps 是一个生命周期过程,它识别机器学习操作的各个阶段,确保数据科学过程的可靠性。MLOps 是一套定义机器学习开发过程的实践。尽管这一术语是最近才提出的,但大多数数据科学家一致认为,成功的 MLOps 过程应该遵循以下原则:
-
协作: 这一原则意味着开发机器学习模型的所有内容必须在数据科学家之间共享,以保留知识。
-
可重复性: 这一原则意味着不仅代码,数据集、元数据和参数也应该版本化,并且对于所有生产模型都应具有可重复性。
-
连续性: 这一原则意味着模型的生命周期是一个持续的过程,意味着生命周期阶段的重复和每次迭代时模型的改进。
-
可测试性: 这一原则意味着组织实施机器学习测试和监控实践,以确保模型的质量。
在我们深入了解 MLOps 过程阶段之前,让我们先来看一下更为成熟的软件开发实践。DevOps 是一种在许多企业级软件项目中使用的软件开发实践。一个典型的 DevOps 生命周期包括以下几个阶段,这些阶段会不断重复,以确保产品的改进:
-
规划: 在这一阶段,会制定软件的总体愿景,并设计更为详细的方案。
-
开发: 在这一阶段,编写代码并实现计划的功能。代码通过版本控制系统(如 Git)进行共享,从而确保软件开发人员之间的协作。
-
测试: 在这个阶段,开发的代码通过自动化或手动过程进行缺陷测试。
-
部署: 在这个阶段,代码被发布到生产服务器,用户有机会进行测试并提供反馈。
-
监控: 在这个阶段,DevOps 工程师专注于软件性能和故障原因,识别可能的改进领域。
-
运维: 这个阶段确保软件更新的自动发布。
以下图示展示了 DevOps 生命周期:

图 1.5 – DevOps 生命周期
所有这些阶段都会不断重复,从而实现部门之间的沟通和客户反馈循环。这一做法为企业带来了更快的开发周期、更好的产品和持续的创新等好处。部门之间密切关系促进了更好的团队合作,而这正是这一过程高效的关键因素之一。
数据科学家应当拥有一个同样具有可靠性的过程。企业数据科学面临的最大问题之一是,极少有机器学习模型能够投入生产。许多公司刚刚开始采用数据科学,而新设立的部门面临前所未有的挑战。团队通常缺乏对需要实施的工作流程的理解,而这些工作流程是确保企业级数据科学正常运作的关键。
另一个重要的挑战是,与传统的软件开发不同,数据科学家不仅操作代码,还需要操作数据和参数。数据来自现实世界,而代码则在办公室中精确开发。两者唯一的交集是在数据模型中结合时。
所有数据科学部门面临的挑战包括以下几点:
-
不一致或完全缺失的数据科学过程
-
无法跟踪数据变化并重现过去的结果
-
性能缓慢
在许多企业中,数据科学部门仍然较小,并且在创建可靠的工作流程方面面临困难。构建这样的过程需要一定的专业知识,例如理解传统的软件实践(如 DevOps),并与理解数据科学挑战相结合。这就是 MLOps 开始出现的地方,它将数据科学与最佳软件开发实践相结合。
如果我们尝试将类似的 DevOps 实践应用于数据科学,可能会看到以下情况:
-
设计: 在这一阶段,数据科学家负责获取数据并设计数据管道,也叫做提取、转换、加载(ETL)管道。数据管道是数据经过的一系列转化步骤,最终产生输出结果。
-
开发: 在这个阶段,数据科学家负责编写先前开发的数据管道的算法代码。
-
训练:在此阶段,模型使用选择的或自动生成的数据进行训练。在此阶段,可以使用超参数调优等技术。
-
验证:在此阶段,经过训练的数据会经过验证,以确保它能够与其余的数据管道兼容。
-
部署:在此阶段,经过训练和验证的模型会被部署到生产环境中。
-
监控:在此阶段,模型会持续监控其性能和可能存在的缺陷,并将反馈直接传递给数据科学家进行进一步改进。
与 DevOps 类似,MLOps 的各个阶段会不断重复。以下图表展示了 MLOps 的各个阶段:

图 1.6 – MLOps 生命周期
正如你所看到的,这两种实践非常相似,后者借鉴了前者的主要概念。将 MLOps 应用于实践为企业级数据科学带来了以下优势:
-
更快的市场交付:数据科学模型只有在成功部署到生产环境中时才具有价值。由于许多公司在其数据科学部门中实施正确流程时遇到困难,MLOps 解决方案确实能够带来改变。
-
跨团队协作与沟通:将软件开发实践应用于数据科学为开发人员、数据科学家和 IT 运维人员提供了一个共同的基础,促使他们能够一起合作并使用相同的语言。
-
可重复性和知识转移:保持代码、数据集和变更历史对于提高整体模型质量起着重要作用,并使数据科学家能够从彼此的示例中学习,从而促进创新和功能开发。
-
自动化:自动化数据管道有助于在多个发布版本中保持流程一致,并加速 概念验证(POC)模型向生产级管道的推广。
在本节中,我们了解了 MLOps 流程中的重要阶段。在下一节中,我们将学习更多关于数据科学平台的种类,这些平台可以帮助你在组织中实施 MLOps。
数据科学平台的种类
本节将带你了解当前开放源代码世界和市场上可用的数据科学平台,并帮助你理解它们之间的区别。
随着 AI 和机器学习领域的不断发展,越来越多的工程师在寻找解决数据科学问题的新方法,并为更好、更快速的 AI 采用构建基础设施。有些平台提供从数据仓库到生产环境的端到端能力,而其他平台则提供部分功能并与其他工具结合使用。通常,没有一种解决方案适用于所有用例,当然也不是每个预算都能承受。
然而,所有这些解决方案都完全或部分地促进了数据科学生命周期的以下阶段:
-
数据工程
-
数据获取与转换
-
数据训练
-
模型部署
-
监控与改进
以下图示展示了数据科学工具的类型:

图 1.7 – 数据科学工具的类型
让我们来看一看现有的可以帮助你构建大规模数据科学工作流的数据科学平台。
端到端平台
一个端到端的数据科学解决方案应该能够提供所有机器学习生命周期阶段所需的工具,如前一节所列。然而,在某些使用场景中,端到端工作流的定义可能会有所不同,可能主要集中在机器学习流程和项目上,排除了数据工程部分。由于定义可能仍在变化,随着领域的发展,端到端工具可能会继续提供不同的功能。
如果存在这样的平台,它应当带来以下好处:
-
一个统一的用户界面,消除了将多个界面拼接在一起的需求
-
为所有相关人员(包括数据科学家、数据工程师和 IT 运维人员)提供协作
-
将基础设施支持的便利性交由解决方案提供商,能够为团队提供额外的时间,专注于数据模型而非基础设施问题
然而,你可能会发现端到端平台的以下缺点与你组织的目标不一致:
-
可移植性:这样的平台可能是专有的,迁移到其他平台将会很困难。
-
价格:端到端平台可能是基于订阅的,许多数据科学部门可能负担不起。如果涉及到基于 GPU 的工作流,价格会进一步上涨。
-
偏差:当你使用提供内置流程的专有解决方案时,你的模型必然会从这些自动化工具中继承偏差。问题在于,偏差可能在自动化机器学习解决方案中难以识别和解决,这可能对你的业务产生负面影响。
既然我们已经了解了端到端数据科学平台的优缺点,让我们来看看目前市场上有哪些平台。由于人工智能领域发展迅速,每年都会有新平台出现。我们将研究其中排名前五的平台。
大型科技巨头,如微软、谷歌和亚马逊,都提供自动化机器学习功能,许多用户可能会觉得这些功能非常有用。谷歌的 AI 平台提供Kubeflow流水线来帮助管理机器学习工作流。亚马逊提供辅助超参数调优和标注的工具。微软提供支持GPU工作流的Azure 机器学习服务,其功能类似于亚马逊的服务。
然而,正如之前所提到的,所有这些可解释人工智能(XAI)功能都容易受到偏见的影响,需要数据科学团队构建额外的工具来验证模型的性能和可靠性。对于许多组织来说,自动化机器学习并不是正确的答案。另一个问题是供应商锁定,因为你将不得不将所有数据保存在底层的云存储中。
Databricks解决方案提供了更灵活的方式,因为它可以部署在任何云平台上。Databricks 基于 Apache Spark,这是人工智能和机器学习工作流中最受欢迎的工具之一,并通过名为MLflow的平台提供端到端的机器学习管道管理。MLflow 使数据科学家能够跟踪从模型开发到部署再到生产的管道进展。许多用户喜欢其内建的笔记本界面。一个缺点是缺乏数据可视化工具,未来可能会添加该功能。
Algorithmia是另一种专有解决方案,可以部署在任何云平台上,提供端到端的机器学习工作流,涵盖模型训练、部署、版本管理和其他内建功能。它支持批量处理并且可以与 GitHub Actions 集成。虽然 Algorithmia 是一个很棒的工具,但它内建了一些传统的软件开发工具,可能会让某些工程团队觉得冗余。
可插拔解决方案
尽管端到端平台听起来像是数据科学部门的理想解决方案,但实际上并非总是如此。大公司通常有一些端到端平台无法满足的需求。这些需求可能包括以下内容:
-
数据安全:一些公司可能对将数据存储在云端有隐私限制。这些限制也适用于自动化机器学习功能的使用。
-
管道输出:通常,管道的最终产物是一个库,这个库被打包并用于组织内其他项目中。
-
现有基础设施约束:一些现有的基础设施组件可能会阻碍端到端平台的集成。某些基础设施部分可能已经存在并满足用户需求。
可插拔解决方案为数据基础设施团队提供了构建自定义解决方案的灵活性,但这也带来了支持该解决方案的需求。然而,大多数大公司最终都会这样做。
可插拔解决方案可以分为以下几类:
-
数据摄取工具
-
数据转换工具
-
数据服务工具
-
数据可视化与监控工具
让我们考虑一些这些工具,它们可以组合在一起构建数据科学解决方案。
数据摄取工具
数据摄取是从公司所有来源收集数据的过程,例如数据库、社交媒体和其他平台,将其集中到一个位置,供机器学习管道和其他人工智能过程进一步使用。
最流行的开源数据摄取工具之一是Apache NiFi,它可以将数据摄取到Apache Kafka,这是一个开源流媒体平台。从那里,数据管道可以消耗这些数据进行处理。
在商业云托管平台中,我们可以提到 Wavefront,它不仅支持数据的摄取,还支持数据处理。Wavefront 因其可扩展性和支持高查询负载的能力而著名。
数据转换工具
数据转换是将代码应用于你拥有的数据的过程。这包括将数据作为数据管道的一部分进行训练和测试。该工具应能够从一个集中的位置消耗数据。像TensorFlow和Keras这样的工具为这类操作提供了扩展功能。
Pachyderm也是一个数据转换和管道工具,尽管它的主要价值在于大型数据集的版本控制。与其他转换工具不同,Pachyderm 让数据科学家有自由定义自己管道的空间,并支持任何语言和库。
如果你参加过数据科学课程,那么很可能你已经使用过MATLAB或Octave来进行模型训练。这些工具为你提供了一个很好的起点来探索机器学习。然而,当涉及到需要持续训练、协作、版本控制和模型产品化的生产级数据科学时,这些工具可能并不是最佳选择。MATLAB 和 Octave 主要用于学术目的的数值计算。MATLAB 等平台的另一个问题是,它们通常使用专有语言,而像 Pachyderm 这样的工具支持任何语言,包括数据科学社区中最流行的语言。
模型服务工具
在你训练好模型并且获得令人满意的结果后,你需要考虑将该模型投入生产,通常可以通过 REST API 的形式或将其数据表导入到数据库中来实现这一目标。根据你在模型中使用的语言,提供REST API可能和使用 Flask 等 Web 框架一样简单。
然而,还有一些更高级的工具可以为数据科学家提供端到端的机器学习过程控制。一个这样的开源工具是Seldon。Seldon 将 REST API 端点转化为生产级微服务,在这里你可以轻松地将每个模型版本从开发环境推广到生产环境。
另一个提供类似功能的工具是KFServing。这两种解决方案都使用 Kubernetes 的自定义资源定义(CRD)来定义模型服务的部署类。
在大公司中,通常不同的团队负责模型训练和模型服务,因此,决策可能会根据团队对某一解决方案的熟悉度和偏好做出。
数据监控工具
在模型部署到生产环境后,数据科学家需要继续获取关于模型性能、潜在偏差和其他指标的反馈。例如,如果您拥有一个电商网站,并且推荐系统根据用户的历史选择推荐当前订单的购买商品,您需要确保该系统仍然紧跟最新的时尚潮流。您可能不了解潮流趋势,但反馈循环应能在模型性能下降时发出信号。
企业往往未能为机器学习工作流实施有效的监控解决方案,这可能对您的业务产生潜在的毁灭性后果。Seldon Alibi 是其中一种提供模型检查功能的工具,使数据科学家能够监控在生产环境中运行的模型,并识别需要改进的地方。Seldon Alibi 提供了异常值检测,帮助发现异常;漂移检测,帮助监控输入数据与输出数据之间的相关性变化;以及对抗性检测,揭示原始数据输入中的恶意变化。
Fiddler 是另一个流行的工具,用于监控生产模型的完整性、偏差、性能和异常值。
汇总全部内容
如您所见,创建一个生产级数据科学解决方案有多种方法,并且可能没有“一刀切”的解决方案。虽然端到端的解决方案提供了使用单一供应商的便利,但它们也有多重缺点,并且相比可插拔工具,通常配备的领域功能较弱。另一方面,可插拔工具需要您的组织具备一定的专业知识和文化,这将使得不同部门(如 DevOps 工程师)能够与数据科学家合作,共同构建最佳的解决方案和工作流。
下一节将带我们了解困扰现代人工智能应用的伦理问题,这些问题如何影响您的业务,以及您可以采取的应对措施。
解释伦理 AI
本节描述了人工智能中的伦理问题以及组织在构建人工智能应用时需要注意的事项。
随着 AI 和机器学习技术变得越来越普及和被接受,我们很容易忽视数据及决策过程的来源。当 AI 算法根据你最近的搜索建议购买哪一双鞋时,这可能并不是什么大事。但假设 AI 算法被用来决定你是否符合某个工作岗位的要求,你是否有犯罪倾向,或者你是否符合房贷批准标准。那么,了解这个算法是如何创建的、使用了哪些数据进行训练、数据集中包含了什么,更重要的是,数据集中没有包含什么,将变得至关重要。至少,我们需要质疑是否存在一个适当的过程来验证用于生成模型的数据。这不仅是正确的做法,而且还可以帮助你的组织避免不必要的法律后果。
虽然 AI 应用带来了一定的优势并提升了我们的生活质量,但它们有时也会犯错,这些错误有时会对人们的生活产生不利甚至毁灭性的影响。这些趋势促使领先的 AI 公司和大型科技公司出现了伦理 AI 团队和伦理 AI 倡导者。
伦理 AI 在过去几年中已成为数据科学社区中越来越多讨论的话题。根据《人工智能指数报告 2019》,伦理已成为 AI 会议中 AI 论文数量的一个持续增长的关键词。

图 1.8 – 自 1970 年以来提及伦理的 AI 会议论文数量,摘自《AI Index 2019 年度报告》(第 44 页)
让我们考虑一下最广受批评的 AI 技术之一——面部识别。面部识别应用可以识别图像或视频中的一个人。近年来,这项技术已经广泛应用,现在被用于家庭安全、身份验证和其他领域。在 2018 至 2019 年,全球超过 1000 篇新闻文章提到了面部识别和数据隐私。亚马逊开发的一种名为Rekognition的基于云的面部识别技术,被一些州的警察部门使用。执法部门使用该软件在数据库中搜寻嫌疑人,在视频监控分析中,包括警察佩戴的身体摄像头画面。独立研究显示,当从 120 名国会议员中识别时,软件将其中 28 人识别为潜在罪犯。所有这些人都有较深的肤色。该工具在识别有色人种女性时尤其表现不佳。
这个以及其他面部识别技术的问题在于,它是基于一个不具包容性的数据库进行训练的,该数据库主要包含白人男性的照片。此类结果很难预测,但这正是伦理 AI 正在努力解决的问题。在公共场所实施这样的监控系统会对成千上万的人产生负面影响。AI 的进步使得面部识别技术能够在几乎不需要人工干预的情况下进行身份识别。这就引发了完全控制和隐私的问题。虽然这样的系统可以帮助识别罪犯、预防犯罪并使我们的社会更安全,但它需要经过彻底审计,以防止潜在的错误和滥用。能力越大,责任越大。
另一个有趣的例子是使用自然语言处理(NLP)应用。NLP 是一种机器学习技术,使得机器能够自动解读和翻译一种人类语言所写的文本为另一种语言。近年来,NLP 应用取得了重大进展。像 Google Translate 这样的工具解决了 20 年前仍无法解决的问题。NLP 将句子分解为若干部分,并尝试在这些部分之间建立联系,以提供有意义的解释。NLP 应用不仅仅处理翻译,还能总结长篇研究论文中的内容或将文本转换为语音。
但这些应用也可能会犯错。一个例子是在土耳其语到英语的翻译中发现的。在土耳其语中,只有一个人称代词 o,可以表示 她/她的 或 他/他的。人们发现 Google Translate 存在基于性别的歧视,降低了女性的角色,这种歧视通常来源于常见的刻板印象。例如,它会将 She is a secretary 翻译为 她是秘书,而 He is a doctor 翻译为 他是医生,尽管在土耳其语中,这两句话都可以描述男性或女性。
从这些例子中可以看出,偏见是 AI 应用中的最大问题之一。偏见数据集是指没有包含足够样本的研究现象数据集,从而导致无法输出客观结果。例如在面部识别的例子中,数据集没有足够的有色人种代表,无法做出正确的预测。
虽然许多公司已经意识到数据集中的偏见可能带来的负面影响和风险,但很少有公司采取措施来减轻这些潜在的负面后果。根据《人工智能指数报告 2019》,只有 13% 的受访组织正在努力改善所使用数据集的公平性和公正性:

图 1.9 – 采取措施减轻 AI 风险的组织类型,来自《AI Index 2019 年度报告》(第 102 页)
另一个偏见的方面是财务不平等。众所周知,来自经济条件不利的背景的人们比那些来自更有利条件背景的人们更难获得信贷交易。信用报告已知存在错误,导致借款利率更高。
其业务是创建客户画像或个性化的公司更进一步,从公共记录、信用卡交易、抽奖活动及其他来源收集用户行为的详细信息。这些报告可以出售给营销人员甚至执法机构。个人会根据其性别、年龄、婚姻状况、财富、健康状况和其他因素进行分类。有时这些报告会包含关于犯罪记录等过时信息。曾经有一个案例,一位老太太因为被逮捕而无法进入养老院。然而,尽管她被逮捕,但那是她的伴侣家庭暴力的案件,她从未被起诉过。她能够纠正她的警方记录,但无法更正由画像公司创建的报告。纠正这些公司报告中的错误极为困难,它们可能会影响人们的生活数十年。
有时候,人们因为误认的档案被标记。想象一下,你申请工作被拒绝,因为你过去曾因盗窃或入室盗窃而受到起诉。这可能会让人震惊,可能一点也不合理,但是像这样的情况在一些常见姓名的人中并非没有。要纠正这样的错误,你需要一个愿意花时间为你纠正这些错误的人的干预。但你经常遇到这样的人吗?
现在机器学习被用于客户画像,许多数据隐私倡导者对这些算法中使用的方法提出了质疑。因为这些算法从过去的经验中学习,根据它们的说法,你过去做过的任何事情未来可能会重复。根据这些算法,罪犯将会再犯,穷人将会更穷。在他们的现实中没有错误的余地。这意味着有前科的人很可能会再次被逮捕,这为法律执行提供了歧视的基础。相反的情况也成立:那些来自良好社区的无犯罪记录者不太可能犯罪。这听起来并不公平。
关于累犯模型的问题在于大多数模型都是专有的黑盒子。黑盒模型是一种端到端模型,由算法直接根据提供的数据创建,即使数据科学家也无法解释它如何做出决策。由于人工智能算法的学习方式与人类类似,随着时间的推移,它们学习与我们相同的偏见。

图 1.10 - 黑盒模型
让我们继续下一节!
可信的人工智能
几年前,道德人工智能只是一些独立倡导者和学者的工作领域,而如今越来越多的大型科技公司已建立道德人工智能部门,以保护公司免受声誉和法律风险。
建立可信赖的人工智能模型标准是一项雄心勃勃的任务,且没有“通用法则”。然而,以下原则适用于大多数情况:
-
创建一个道德人工智能委员会,负责讨论与人工智能相关的风险,并与公司整体战略保持一致。
-
提高对非透明机器学习算法及其可能对社会和组织带来的潜在风险的认识。
-
创建识别、沟通和评估偏见模型及隐私问题的流程。例如,在医疗领域,保护患者个人信息至关重要。围绕产品管理部门的道德风险创建责任制。
-
建立一个通知用户其数据使用方式的流程,并用通俗易懂的语言解释偏见风险及其他概念。用户越早意识到使用你的应用程序可能带来的影响,未来的法律风险就会越小。
-
在公司内部建立一种文化,表彰促进道德项目和倡议的努力,以激励员工为这些努力做出贡献。鼓励来自不同部门的员工,包括工程、数据科学、产品管理等,参与这些工作。
根据《2019 年人工智能指数报告》,人工智能伦理的主要挑战包括公平性、可解释性和透明性。
下图展示了道德人工智能领域中存在的更完整的挑战清单:

图 1.11 - 道德人工智能挑战,摘自《人工智能指数 2019 年年报》(第 149 页)
以下是非透明机器学习算法可能引发的一些问题:
-
经济和金融机会的不均衡传播,包括信贷歧视以及基于预定购买习惯的不平等折扣和促销机会。
-
信息和社交圈的访问,例如基于社会经济群体推荐新闻,或建议加入特定群体或社交圈的算法。
-
就业歧视,包括根据候选人的种族、宗教或性别筛选候选人的算法。
-
不平等使用警力和处罚,包括基于社会地位和种族预测个人未来犯罪可能性的算法。
-
住房歧视,包括拒绝为有色人种、LGBT 群体和其他少数群体提供平等的租赁和按揭机会。
AI 给我们的社会带来了前所未有的好处,类似于工业革命带来的影响。但是,尽管有这些好处,我们也应该意识到这些好处所带来的社会变革。如果未来的交通方式是自动驾驶汽车,这意味着作为职业的驾驶工作将在可预见的未来消失。许多其他行业将受到影响并消失。这并不意味着进步不应该发生,但它需要以受控的方式进行。
软件的完美程度与其创造者一样,新的 AI 驱动产品中的缺陷是不可避免的。但如果这些新应用是关于人类生命和命运决策过程中的第一道关卡,就必须确保我们尽量减少潜在的有害后果。因此,深入理解我们的模型至关重要。部分原因就在于可复制性,这是最小化 AI 负面后果的关键因素之一。
总结
在本章中,我们讨论了许多重要概念,帮助我们明确了为什么可复制性很重要,以及为什么它应该成为成功的数据科学流程的一部分。
我们已经了解到,数据科学模型用于分析历史数据作为输入,目标是计算出最可能和最成功的结果。我们还确认了复制性,即能够重现科学实验结果的能力,是良好研究的基本原则之一,并且它是确保团队减少模型偏差的最佳方法之一。偏差可能会从训练数据集中由于数据的不准确呈现而渗入计算中。这种偏差通常反映了历史和社会现实以及社会中被接受的规范。减少训练数据中偏差的另一种方法是拥有一个多元化的团队,团队成员包括各种性别、种族和背景的代表。
我们了解到,数据挖掘(也叫钓鱼)是一种不道德的技术,一些数据科学家通过挑选实验结果中的某些结果来证明预先定义的假设,只选择能够证明预期结果的结果,忽略任何不符合的趋势。
我们还了解了 MLOps 方法论,它是机器学习应用程序的生命周期,原理上类似于 DevOps 软件生命周期技术。MLOps 包括以下主要阶段:规划、开发、训练、验证、部署和监控。所有这些阶段都被持续重复,从规划到开发、测试、生产再到后期生产阶段,形成一个确保实验管理无缝衔接的反馈循环。
我们还回顾了一些道德 AI 的最重要方面,道德 AI 是数据科学的一个分支,专注于人工智能、机器人学和数据科学的伦理问题。如果在组织中未能实施道德 AI 流程,可能会导致不良的法律后果,尤其是当部署的生产模型被发现具有歧视性时。
在下一章,我们将学习 Pachyderm 版本控制系统的主要概念,它能帮助你解决本章中提到的许多问题。
进一步阅读
- Raymond Perrault, Yoav Shoham, Erik Brynjolfsson, Jack Clark, John Etchemendy, Barbara Grosz, Terah Lyons, James Manyika, Saurabh Mishra 和 Juan Carlos Niebles,AI Index 2019 年年报,AI Index 指导委员会,Stanford 大学人类中心人工智能研究所,斯坦福,加利福尼亚州,2019 年 12 月:
hai.stanford.edu/sites/default/files/ai_index_2019_report.pdf
图 1.1,1.2,1.3,1.8,1.9 和 1.11 来自 AI Index 2019 年年报。
-
Liu, D., & Salganik, M. (2019 年 3 月 15 日)。计算可重复性中的成功与挑战:来自脆弱家庭挑战的经验教训。
doi.org/10.1177/2378023119849803 -
透明度与开放性推广(TOP)指南 v1.0.1:
osf.io/ud578/ -
可重复性:一场错误的悲剧:
www.nature.com/news/reproducibility-a-tragedy-of-errors-1.19264 -
神经信息处理系统(NeurIPS)会议:
nips.cc -
国际机器学习会议(ICML):
icml.cc
第二章:第二章:Pachyderm 基础
Pachyderm是一个数据科学平台,使数据科学家能够创建端到端的机器学习工作流,涵盖机器学习生命周期中最重要的阶段,从数据摄取到生产部署。
如果你熟悉Git,一个用于代码的版本控制和生命周期管理系统,你会发现 Git 和 Pachyderm 的最重要概念之间有许多相似之处。像 Git 及其托管版本GitHub这样的版本控制系统,已成为全球成千上万开发者的行业标准。Git 使你能够保存代码更改的历史,并在需要时回溯。数据科学家需要一个平台,能够跟踪实验的版本,必要时重现结果,并调查和纠正可能在数据科学生命周期的某一阶段出现的偏差。Pachyderm 提供了类似于 Git 的好处,使数据科学家能够重现实验并轻松管理数据科学工作流的完整生命周期。
本章旨在描述 Pachyderm 架构的基础知识及其主要概念。我们将涵盖以下主题:
-
回顾 Pachyderm 架构
-
学习版本控制原语
-
发现管道元素
回顾 Pachyderm 架构
本节将带你了解分布式 Pachyderm 架构以及 Pachyderm 解决方案的内部原理。但在深入探讨 Pachyderm 基础设施的细节之前,让我们先回答你们在阅读简介后可能会有的问题——为什么我不能使用 Git 或任何其他版本控制系统? 我们将以 Git 为例来回答这个问题,因为它是最流行和广泛使用的软件版本控制系统,但所有的论点都适用于任何其他类似的源代码版本控制系统。在回顾 Pachyderm 如何与 Git 不同及相似之后,我们将回顾 Pachyderm 的内部原理、Kubernetes 和容器运行时。
为什么我不能使用 Git 来管理我的数据管道?
那么,如果 Pachyderm 与 Git 类似,为什么我不能将所有内容都存储在 Git 中,而 是要使用我需要学习和支持的多个工具呢?,你可能会问。
虽然 Git 是软件工程师常用的开源技术,但它并不专门解决数据科学中的可重现性问题。这主要是因为 Git 被设计用来跟踪文件版本,而不是建立数据、代码和参数之间的联系——这些是每个数据模型的核心部分。
虽然你可以将代码文件保存在 Git 中,但由于以下原因,将训练数据保存在 Git 中是不可能的:
-
文件格式支持:Git 非常适合源代码管理,例如文本文件、脚本等,但它不支持非二进制文件的版本控制,如图片或视频文件。Git 会检测到二进制文件的变化,但不会像文本文件那样提供详细的变更信息。此外,Git 会替换整个二进制文件,这使得在更新时你的仓库体积剧增。
-
文件大小支持:通常,图片和视频文件非常大,而 Git 对每个文件有 100MB 的大小限制。为了获得最佳性能,Git 建议将仓库大小保持在 1GB 以下,而这对于某些机器学习和深度学习项目可能并不足够。
-
克隆一个大型 Git 仓库以及每个文件的所有历史记录可能会成为问题,并且需要较长的时间。
在计划机器学习项目的工具时,请考虑这些限制。
除了标准的 Git 仓库,Git 还提供了大型文件存储功能,称为Git 大型文件存储(LFS)。然而,这个选项可能也无法提供所需的功能。Git LFS 在机器学习项目中有以下缺点:
-
Git LFS 需要一个服务器。你需要设置并维护自己的 Git LFS 服务器,或者将其存储在第三方在线平台上。托管自己的服务器存在问题,需要额外的支持,并且你的首选云服务提供商可能不被支持。
-
在线 Git LFS 服务器有一个有限的免费版。对于使用高分辨率图片或视频的项目,这通常意味着很快就会达到限制,需要升级到付费版。
-
Git LFS 设计初衷是面向营销部门的用途,似乎是一个不错的解决方案,适合营销部门存储资产。其他人则更倾向于在非机器学习项目中使用标准 Git。
现在你已经知道为什么源代码版本控制系统并不是处理数据的最佳解决方案,让我们来回顾一下 Pachyderm 架构。
Pachyderm 架构图
下图展示了 Pachyderm 架构:

图 2.1 – Pachyderm 架构
让我们逐一回顾一下这个图中的所有组件。
Kubernetes
Kubernetes,一个开源分布式工作流调度系统,是 Pachyderm 的核心。如果你不熟悉 Kubernetes,下面是一个简要概述。
Kubernetes 是基础设施演进的最新阶段,最早起源于传统硬件部署,在那里数据中心操作员将所有应用程序部署在一台物理服务器上。这些应用程序会争夺资源,导致某些应用程序性能差。这种方式扩展性差,且管理困难。后来,我们看到了虚拟机技术的兴起,它使得物理服务器的管理变得更容易,并允许我们在一台物理服务器上运行多个应用程序,且具备更好的可扩展性。许多数据中心至今仍在运行大量虚拟机。容器,Kubernetes 所基于的技术,通过允许容器共享操作系统组件并去除相同软件部分的冗余副本,使得基础设施变得更加精简。容器可以轻松地从一个云平台迁移到另一个平台,提供更好的资源分配,并且整体上更易于管理和支持。
Kubernetes 的功能是管理容器及其集合,称为Pods。如今,Kubernetes 已成为开源世界中主导的容器技术。大科技公司可能有自己的调度程序类型——例如,谷歌有一个叫做 Borg 的项目,但大多数其他公司都在使用某一版本的 Kubernetes。
亚马逊、微软和谷歌等公司提供了分别被称为AWS 弹性 Kubernetes 服务(EKS)、微软 Azure Kubernetes 服务(AKS)和谷歌 Kubernetes 引擎(GKE)的托管 Kubernetes 版本。
一些公司,如 DigitalOcean,提供一个 Kubernetes 安装和管理系统,可以将 Kubernetes 部署到您选择的云平台上。
现在我们知道了 Kubernetes 的基本概念,接下来让我们回顾一下 Pachyderm 如何利用 Kubernetes 提供可扩展、可重复的数据科学解决方案。
Helm
部署 Pachyderm 的工具是 values.yaml,您可以使用它与 Pachyderm Helm Chart 一起进行本地 Pachyderm 安装,详情请见 github.com/pachyderm/pachyderm/blob/master/doc/docs/master/reference/helm_values.md。
在 values.yaml 文件中,您可以定义所有希望与 Pachyderm 集群一起部署的内容。例如,您可以选择部署名为 Console 的 Pachyderm 用户界面,也可以不部署;您可以在云服务提供商中配置存储桶;您可以指定要安装的 Pachyderm 版本,等等。
Helm Charts 存储在 Artifact Hub,网址为 artifacthub.io/。你可以在 artifacthub.io/packages/helm/pachyderm/pachyderm 找到 Pachyderm。我们将在 第五章 中更详细地讨论 Pachyderm Helm Chart,在云平台上安装 Pachyderm。
Pachyderm 内部结构
当你在本地或所选云平台上部署 Pachyderm 时,底层的 Kubernetes 调度器会部署以下组件:
-
Pachyderm Console(UI):Pachyderm 浏览器内的 用户界面(UI),提供基本的 Pachyderm 功能。 -
Pachd:Pachyderm 守护进程容器,负责管理所有主要的 Pachyderm 逻辑操作。 -
postgress:Pachyderm 需要一个 PostgreSQL 实例来存储元数据。PostgreSQL 是一个广泛应用于许多开源和商业解决方案的关系型数据库。虽然在测试时,Pachyderm 构建中自带了一个 PostgreSQL 实例,但对于生产部署和工作负载,强烈建议使用单独的基于云的实例。 -
etcd:在旧版本的 Pachyderm 中,etcd是存储节点信息和管理元数据的键值存储。在 Pachyderm 2.0.0 及更高版本中,etcd只存储一小部分元数据,其余的元数据存储在 PostgreSQL 中。
这些组件中的每一个都作为 Kubernetes Pod 部署——Kubernetes 的最小部署单元,可以包含一个或多个容器。与其他应用程序不同,在 Pachyderm 中,每个 Pod 只有一个容器。
除了在安装过程中部署的这些容器外,每个 Pachyderm 管道(一个训练模型的计算组件)都作为单独的 Kubernetes Pod 部署。这些 Pod 被称为 工作节点(workers)。你可以在 Pachyderm 集群中部署无限数量的管道,并为每个 Pod 分配自定义数量的资源。Pod 彼此完全隔离。
其他组件
图 2.1 包含以下我们尚未列出的组件:
-
负载均衡器或入口控制器:Kubernetes 的网络组件,负责将 HTTP/HTTPS 路由从集群暴露到外部世界。默认情况下,Kubernetes 提供ClusterIP 服务,使集群内部的服务可以相互通信,但无法从外部世界访问集群服务。在生产环境中,如云平台上,你需要部署入口控制器或负载均衡器才能通过互联网访问你的 Pachyderm 集群。在本地测试部署中,Pachyderm 使用端口转发。NodePort 是另一种配置外部访问的方式,但不推荐用于生产环境,因此在当前描述中已被省略。Pachyderm 提供了一种通过 Helm Chart 安装的 Traefik 入口选项。
-
pachctl是 Pachyderm 的命令行界面(CLI),使用户能够执行与 Pachyderm 管道相关的高级操作,并根据需要配置基础设施。 -
API:Pachyderm 支持通过多种语言客户端进行编程访问,包括 Python、Go 等。许多用户会发现,使用支持的客户端之一或甚至构建自己的客户端非常有用。
-
元数据存储:etcd 收集管理元数据,这些元数据必须存储在本地磁盘或 Kubernetes 的持久化卷(PV)中,可以存储在云平台或任何其他平台上。
-
对象存储:用于存储Pachyderm 文件系统(PFS)和与管道相关的文件。Pachyderm 支持 S3 对象存储,如 MinIO、Google S3、Azure Blob 存储和 Amazon S3。
在图 2.1中,用户通过负载均衡器或入口控制器访问 Pachyderm 集群,可以使用 Pachyderm 仪表板、pachctl,或通过 API 使用语言客户端进行访问。用户的请求被发送到 pachd,pachd 处理请求并相应地更新管道和 etcd 的状态。管道运行后,将结果输出到配置的存储位置,其他第三方应用程序可以从该位置访问该结果。
容器运行时
容器运行时是执行容器内代码的软件。有许多开源容器运行时,如 Docker、container、CRI-O 等。Pachyderm 支持最流行的容器运行时——Docker。Pachyderm 仅支持一种容器运行时,并不意味着功能有限。大多数用户会发现,Docker 容器已足够满足他们的所有需求。
要运行容器,你需要有一个容器镜像以及一个存储它的地方。容器镜像是一个包含程序不可变代码的文件,可以由容器运行时执行。容器镜像存储在容器注册表中,这些是存储或托管容器镜像的库或仓库。部分容器注册表是公开的,另一些则是私有的。所有 Pachyderm 组件都打包为容器镜像,并存储在Docker Hub中,这是一种公共容器注册表,任何人都可以免费下载这些镜像。
所有的 Pachyderm 管道都需要打包成 Docker 容器并存储在容器注册表中。你的组织可能要求你将包存储在私有容器注册表中,以保护管道的知识产权。但如果你是在做开源或学生项目,你可以免费将容器镜像存储在 Docker Hub 中。
现在我们已经回顾了 Pachyderm 架构,让我们来看看 Pachyderm 版本控制的基本原理,这对于理解 Pachyderm 的工作原理至关重要。
学习版本控制原语
正如我们在前面的章节中看到的,Pachyderm 与名为 Git 的代码版本控制软件有相似之处。如果你曾参与过开源项目的开发,你可能通过使用托管的 Git 版本(如 GitHub、GitLab 或 Gerrit)而熟悉 Git。
像使用 Git 一样,你将数据存储在仓库中,通过提交上传数据,并且可以在仓库中拥有多个分支。Pachyderm 存储了你的提交历史,并允许你追溯数据的变化或历史,直至其最初的状态。
Pachyderm 版本控制原语使你能够回溯到过去,并使用管道对先前版本的更改进行处理。这在跟踪偏差和错误(这些可能会悄然进入你的管道更改中)时非常有用。
让我们更详细地了解这些概念。
仓库
Pachyderm 的仓库是一个文件系统,你在其中存储数据并保存数据的不同版本。Pachyderm 区分了输入仓库和输出仓库。
输入仓库是你创建的文件系统,用于上传数据以供进一步处理,可以通过 CLI、UI 或通过 API 自动上传。
输出仓库是 Pachyderm 自动创建的文件系统,其名称与管道相同。这里是 Pachyderm 输出计算结果的地方,也是可以从这里导出结果以供作为模型使用的地方。
与 Git 仓库的一个重要区别是,Pachyderm 仓库历史被存储在一个集中位置,这消除了合并冲突的风险。因此,Pachyderm 没有类似.git历史文件的东西。
以下图示展示了内部和外部仓库在管道中的工作方式:

图 2.2 – Pachyderm 输入和输出仓库
上述图示展示了一个仅包含一个管道的简单用例。然而,您的工作流可能会更加复杂,多个管道可能会交织在一起共同工作,以实现所需的结果。
分支
分支是 Pachyderm 中的一个开发线,用于跟踪仓库中的一组变更。默认情况下,仓库没有分支。我们在本书中使用的主分支只是一个示例,用于说明如何在 Pachyderm 中命名您的主分支,并不强制要求。通常,在向仓库上传初始数据时,您会在仓库上创建一个分支。您可以创建多个分支来组织您的工作,但通常不会像在 Git 中那样广泛使用它们。通常,只用一个分支就足够完成所有工作了。您也可以为不同的实验创建一个单独的分支。所有分支对所有用户可见,因此您不能像在 Git 中那样拥有一个本地分支,在其中进行实验,再与主分支合并。
要创建分支,请运行以下命令:
pachctl create branch <repo>@<branch>
必须在创建分支之前先存在仓库。
要确认分支是否已创建,请运行以下命令:
pachctl list branch <repo>
本节的最后部分将讨论提交概念。
提交
提交是您数据的一个不可更改的变更集。例如,当从流媒体平台(如Kafka)接收新数据时,它会作为一个新提交写入到 Pachyderm 仓库,并附带一个唯一的哈希标识符。
下图展示了 Pachyderm 中分支提交概念的示意图:

图 2.3 – 显示 Pachyderm 提交的示意图
数据变更会存储在仓库历史记录中。每当向仓库提交新提交时,分支的HEAD提交会移动。一旦新数据提交,管道会根据这些最新的更改运行代码,除非明确配置了不同的行为。
现在我们已经了解了最重要的 Pachyderm 版本控制原语,接下来让我们更详细地了解 Pachyderm 管道。
探索管道元素
本节将引导您了解 Pachyderm 管道的主要概念。Pachyderm 管道系统(PPS)是 Pachyderm 功能的核心。
Pachyderm 管道是数据在输出最终结果之前经过的一系列计算任务。例如,它可以是一系列图像处理任务,如为每个图像加标签或应用滤镜。也可以是两个数据集的比较或查找相似性任务。
一个管道执行以下三个步骤:
-
从指定位置下载数据。
-
应用您代码中指定的转换步骤。
-
将结果输出到指定位置。
下图展示了 Pachyderm 管道的工作原理:

图 2.4 – Pachyderm 管道
每个 Pachyderm 管道都有输入和输出仓库。输入仓库是一个文件系统,数据从外部源传入 Pachyderm。它位于管道 Pod 内的 /pfs 目录下。数据可以通过管道拉取,也可以由数据源系统推送到输入仓库。数据经过转换处理后,会被放入输出 Pachyderm 仓库,该仓库位于 /pfs/out 目录下。之后,输出仓库中的结果可以被第三方应用或其他管道进一步使用。
每次新数据到达输入仓库时,Pachyderm 会启动一个管道任务。该任务处理新到的数据并将结果放入输出仓库。
管道类型
机器学习管道持续执行数据科学家对新数据编写的任务。例如,您可能希望比较或合并两种类型的文件,或对它们应用特定的参数。为了简化这些任务,Pachyderm 提供了预定义的管道,可以自动完成这些工作。
Pachyderm 提供以下类型的管道:
-
标准管道
-
Cron 管道
-
Spout 管道
-
服务管道
要创建管道,您需要编写一个管道规范。管道规范是一个文件,采用YAML 不是标记语言(YAML)或JavaScript 对象表示法(JSON)格式,描述管道需要执行的任务。我们将在下一章详细讨论管道规范。
标准管道
标准管道,简称管道,是在 Pachyderm 集群中调度工作的最直接方式。此类管道在新数据进入 Pachyderm 输入仓库时触发。管道启动或恢复一个 Kubernetes Pod 来运行您的代码,并针对新到的数据生成输出结果,结果将存放在输出仓库中。输出仓库会自动创建,并与管道同名。
最简单的标准管道必须包含以下组件:
-
name:管道的描述性名称。为管道命名时,最好选择一个能反映其完成任务的名称。例如,如果您的代码分析社交媒体上用户的情感,您可能希望将其命名为sentiment-analysis或类似名称。 -
transform:管道的转换部分包含有关管道需要拉取和使用的 Docker 镜像以及在管道容器中运行的代码的信息。例如,如果您正在进行情感分析,您可能会使用自然语言处理(NLP)工具,如自然语言工具包(NLTK)或斯坦福 CoreNLP。因此,您可以使用已有的 Docker 镜像,或者构建自己的定制镜像。 -
input:一个输入存储库,管道从中获取数据进行处理。您需要通过 CLI、UI 或 API 将数据上传到输入存储库。
下面的文本是执行情感分析的管道规范示例。该管道称为sentiment-analyzer,使用名为ntlk-image的 Docker 镜像,从名为feed的输入存储库下载数据,然后运行存储在名为transform_code.py的文件中的代码:
# sentiment-analyzer.yml
---
pipeline:
name: sentiment-analyzer
transform:
image: nltk-image
cmd:
- python3
- "/transform_code.py"
input:
pfs:
repo: feed
glob: "/"
glob参数定义如何将数据分解为可在多个 Pachyderm 工作节点上处理的可处理块,以提高性能。我们将在下一节详细讨论此参数。
重要提示
您可以像上面的示例中那样将转换代码放在文件中,也可以直接在cmd字段中指定。有关更多信息,请参阅第三章,Pachyderm 管道规范。
Cron 管道
Cron管道或 cron 是定期运行特定任务的管道。如果您熟悉 UNIX 软件实用程序 cron,则 Cron 管道使用类似的逻辑——它按照指定的时间表定期运行,并每次执行相同的任务。与标准管道不同,标准管道在输入存储库中有新数据到达时运行,Cron 管道则按照时间表运行。您可能希望使用此管道定期抓取网站或表。
Cron 管道规范看起来与标准管道非常相似,除了输入部分。您需要在管道的输入部分指定时间间隔。
下面的文本是以 YAML 格式呈现的 Cron 管道示例,每天午夜定时抓取名为my-website的网站:
# scrape-my-website.yml
---
pipeline:
name: scrape-my-website
transform:
image: web-scraper
cmd:
- python3
- "/scraper.py"
input:
cron:
repo: mywebsite
spec: "@daily"
所有有关网站 URL 的信息将放入您的scraper.py文件中。
喷口管道
s****pout管道或 spout 顾名思义,旨在从外部源(例如发布/订阅消息系统)流式传输数据。在您的基础设施中,您可能有多个消息队列系统。通过 Pachyderm 喷口,您可以将所有这些系统的输入整合到 Pachyderm 喷口管道中。喷口代码不受任何事件触发;相反,它连续运行,监听新消息的到来。
与标准管道或 Cron 管道不同,喷口没有输入存储库,而是在指定地址上侦听。端口和主机可以在管道规范的env变量中或容器内部指定。
常见情况下,一个喷口与 Pachyderm 服务管道一起使用,用于暴露管道的结果,因为喷口输出存储库中的数据无法通过标准的 Pachyderm 命令访问。
下面的文本是以 YAML 格式呈现的喷口管道示例,连接到 Amazon myscript.py,用于处理消息:
---
pipeline:
name: spout-pipeline
spout: {}
transform:
cmd:
- python3
- myscript.py
image: 'myimage'
env:
HOST: sqs-host
TOPIC: mytopic
PORT: '1111'
spout部分为空,但这是你可以将喷口与服务管道结合,向外界暴露管道结果的地方。
服务管道
服务管道,或称服务,是一种可以将输出仓库暴露给外部世界的管道。与其他管道不同,它不会对数据进行任何修改。此管道的唯一功能是通过 API 为你的管道结果提供服务,例如以仪表板的形式。服务管道通常与喷口管道结合使用,有时被称为喷口服务。然而,它可以使用来自任何其他管道输出仓库的结果作为其输入仓库来暴露这些结果。
该管道的管道规范缺少转换部分。以下文本是一个服务管道的 YAML 格式示例:
---
pipeline:
name: expose-service
input:
pfs:
glob: "/"
repo: final-results
service:
external_port: 31111
internal_port: 8888
接下来,我们将看看 Pachyderm 如何处理数据项。
数据项
管道规范中的glob参数。Pachyderm 会独立处理每个数据项。如果你有多个工作节点运行管道,Pachyderm 可以将数据项调度到不同的工作节点上进行更快速的处理,最终所有数据项将在输出仓库中合并。
数据项
这是 Pachyderm 团队使用的术语。是的,通常复数形式是 data,但数据项在 Pachyderm 的文档中是这样出现的!
将数据拆分成多个数据项带来以下优势:
-
通过将管道扩展到多个 Pachyderm 工作节点来提高性能
-
使你能够仅处理特定的文件和文件夹
例如,假设你有一个具有以下文件夹结构的仓库:
data
├── folder1
│ ├── file1
│ ├── file2
│ └── file3
├── folder2
│ ├── file1
│ └── subfolder1
│ └── file1
└── folder3
├── subfolder1
│ ├── file1
│ └── file2
└── subfolder2
├── file1
└── file2
对于此文件夹结构,你可以设置以下几种类型的 glob 模式:
-
/:将所有文件和文件夹作为单一的数据项进行处理。这个单一的数据项包括/目录中的所有文件和文件夹。 -
/*:将每个文件夹作为单独的数据项进行处理。结果的数据项数为三个,包括以下内容:/folder1 /folder2 /folder3 -
/*/*:将/*/*级别上的每个文件系统对象作为单独的数据项进行处理。结果的数据项数为七个,包括以下内容:/folder1/file1 /folder1/file2 /folder1/file3 /folder2/file1 /folder2/subfolder1 /folder3/subfolder1 /folder3/subfolder2 -
/*/*/*:将第三级的每个文件系统对象作为单独的数据项进行处理。结果的数据项数为五个,包括以下内容:/folder2/subfolder1/file1 /folder3/subfolder1/file1 /folder3/subfolder1/file2 /folder3/subfolder2/file1 /folder3/subfolder2/file2 -
/**:将每个文件、文件夹和子文件夹作为单独的数据项进行处理。结果是 15,包括以下代码提取中的所有文件和文件夹:/folder1/ /folder1/file1 /folder1/file2 /folder1/file3 /folder2/ /folder2/file1/ /folder2/subfolder1/ ... -
/<filesystem>/*:仅处理与命名模式匹配的文件和文件夹。例如,如果你只想处理folder1中的数据,你将设置 glob 模式为/folder1/*。类似地,你可以仅将目录名的前几个字母作为 glob 模式。
这些是最常用的 glob 模式。Pachyderm 的 ohmyglob 库提供了扩展的 glob 模式。更多信息请参见 github.com/pachyderm/ohmyglob。
通过数据项扩展管道
将数据分成多个数据项的最大优势之一是可以将工作扩展到多个管道工作节点,从而显著提高管道的性能和处理时间。默认情况下,Pachyderm 为每个管道部署一个工作节点,但你可以根据需要通过在管道规范中指定 parallelism_spec 参数来增加节点数量。
以下图示展示了数据项如何在多个工作节点之间扩展:

图 2.5 – 扩展管道
在前面的图示中,输入数据被拆分到三个工作节点上,它们同时开始处理。在所有数据项处理完成后,它们会合并为最终的输出结果。需要强调的是,数据项仅存在于 Pachyderm 管道内部,不能以任何方式访问、挂载或修改。
Pachyderm 输入
在 Pachyderm 中,你可能会创建多个仓库来存储训练数据、测试数据和参数。Pachyderm 提供了一种自动化的方法,通过使用 输入 将不同仓库中的文件结合在一起,在管道中一起处理。如果你以前使用过 SQL,可能会发现这些输入类似于 SQL 操作符。然而,有一个主要的区别将 SQL 操作符与 Pachyderm 输入区分开来。在 SQL 中,你可以在每个表中创建匹配的行对,而 Pachyderm 输入仅在文件级别上工作。这意味着你只能根据文件的名称而不是文件的内容,将 Pachyderm 仓库中的文件或目录结合在一起。
重要提示
本节提供了如何创建各种 Pachyderm 输入的示例。这些示例仅供参考,你可能会在安装和配置 Pachyderm 后在未来的工作中使用其中的一些。我们将在 第三章的 本地安装 Pachyderm 和 在云平台上部署 Pachyderm 部分中介绍安装和配置。
交叉输入
cross 输入,或称交叉输入,是一种将一个仓库中的每个文件与另一个仓库中的文件进行结合的输入。匹配文件的集合由全局模式决定,在管道运行时,所有数据都对管道代码可见。
你的管道文件中的输入部分(YAML 格式)可能如下所示:
…
input:
cross:
- pfs:
glob: "/*"
repo: data
- pfs:
glob: "/"
repo: parameters
…
例如,你有两个 Pachyderm 仓库,data 和 parameters,其结构和文件如下:
data
├── image1.png
├── image2.png
├── image3.png
└── image4.png
parameters
├── param1.csv
└── param2.csv
如果你创建一个管道,该管道通过设置全局模式 /* 来创建这些仓库的笛卡尔积,你将总共得到八个数据项——data 仓库中的每个文件将与 parameters 仓库中的每个文件结合。这些文件将按以下方式处理:
data@4e5897...:/image1.png, parameters@d1a0da...:/param1.csv
data@4e5897...:/image2.png, parameters@d1a0da...:/param1.csv
data@4e5897...:/image3.png, parameters@d1a0da...:/param1.csv
data@4e5897...:/image4.png, parameters@d1a0da...:/param1.csv
data@4e5897...:/image1.png, parameters@d1a0da...:/param2.csv
data@4e5897...:/image2.png, parameters@d1a0da...:/param2.csv
data@4e5897...:/image3.png, parameters@d1a0da...:/param2.csv
data@4e5897...:/image4.png, parameters@d1a0da...:/param2.csv
在前面的输出中,每对文件和每一行代表一个数据项。
联合输入
一个联合输入(或称为 union)是一个允许你将一个仓库中的数据项与另一个仓库中的数据项合并的输入。数据项的总数是所有仓库中数据项的总和。如果我们采用与交叉输入部分描述相同的仓库结构,并且不是生成交叉积,而是使用 union 输入将它们相加,我们将得到五个数据项的总数。
您的管道文件中的 input 部分在 YAML 格式中可能如下所示:
…
input:
union:
- pfs:
glob: "/*"
repo: data
- pfs:
glob: "/"
repo: parameters
…
以下输出演示了设置了 /* 通配符模式的两个仓库的管道数据项列表:
data@4e58978ca1304f16a0a5dfe3715363b4:/image1.png
data@4e58978ca1304f16a0a5dfe3715363b4:/image2.png
data@4e58978ca1304f16a0a5dfe3715363b4:/image3.png
data@4e58978ca1304f16a0a5dfe3715363b4:/image4.png
model@1de402b7be004a289f6d7185b2329b21:/
您的代码会单独处理每个文件,并且每次运行时只会识别一个文件,忽略其他所有文件。
连接输入
您的 Pachyderm 管道中的 join_on 参数。
Pachyderm 区分 内部连接 和 外部连接。它们之间的区别在于,内部连接匹配文件对,跳过不符合指定模式的文件。外部连接与内部连接的行为相同,但还包括那些不符合模式的文件在管道运行中。如果这听起来有些混淆,下面的示例应该可以帮助澄清管道的工作方式。
假设您有两个仓库,data 和 parameters,并且 parameters 仓库具有以下结构:
NAME TYPE SIZE
/param-0101-2021.txt file 4B
/param-0102-2021.txt file 4B
/param-0103-2021.txt file 4B
/param-0104-2021.txt file 4B
/param-0105-2021.txt file 4B
data 仓库具有以下结构:
NAME TYPE SIZE
/data-0101-2021.txt file 2B
/data-0102-2021.txt file 2B
/data-0103-2021.txt file 2B
/data-0104-2021.txt file 2B
/data-0105-2021.txt file 2B
/data-0106-2021.txt file 2B
/data-0107-2021.txt file 2B
在您的管道中,您可能希望按日期匹配文件。为此,您需要指定捕获组 $1 和通配符模式 /。以下是一个在 YAML 格式中匹配这些文件路径的管道规范示例:
---
pipeline:
name: describe
input:
join:
- pfs:
glob: "/data-(*).txt"
repo: data
join_on: "$1"
- pfs:
glob: "/param-(*).txt"
repo: parameters
join_on: "$1"
transform:
image: mydockerhub/describe
cmd:
- python3
- "/describe.py"
这个捕获组结合 / 通配符模式匹配了五对文件:
data@2c95b1...:/data-0101-2021.txt, parameters@b7acec...:/param-0101-2021.txt
data@2c95b1...:/data-0102-2021.txt, parameters@b7acec...:/param-0102-2021.txt
data@2c95b1...:/data-0103-2021.txt, parameters@b7acec...:/param-0103-2021.txt
data@2c95b1...:/data-0104-2021.txt, parameters@b7acec...:/param-0104-2021.txt
data@2c95b1...:/data-0105-2021.txt, parameters@b7acec...:/param-0105-2021.txt
/data-0106-2021.txt 和 /data-0107-2021.txt 没有匹配的配对,因此 Pachyderm 会在此运行中跳过它们。但是,如果您希望将这些文件包含在管道运行中,可以在 data 仓库输入中指定 outer_join: true,以在没有配对的情况下将这些文件包括在管道运行中。以下抽象展示了如何添加此参数:
…
input:
join:
- pfs:
glob: "/data-(*).txt"
repo: data
join_on: "$1"
outer_join: true
…
然后,您的管道中的数据项列表将如下所示:
data@2c95b1...:/data-0101-2021.txt, parameters@b7acec...:/param-0101-2021.txt
data@2c95b1...:/data-0102-2021.txt, parameters@b7acec...:/param-0102-2021.txt
data@2c95b1...:/data-0103-2021.txt, parameters@b7acec...:/param-0103-2021.txt
data@2c95b1...:/data-0104-2021.txt, parameters@b7acec...:/param-0104-2021.txt
data@2c95b1...:/data-0105-2021.txt, parameters@b7acec...:/param-0105-2021.txt
data@2c95b1...:/data-0106-2021.txt
data@2c95b1...:/data-0107-2021.txt
data-0106-2021.txt 和 data-0107-2021 在管道运行中被包含,但没有配对。
组输入
一个 group_by 管道参数。如果我们采用与内部连接输入示例中相同的管道,并将 join 替换为 group,将 join_on 替换为 group_by,我们将得到与内部连接输入相同的结果。
与连接输入的主要区别包括以下几点:
-
一个组输入会生成一个包含符合命名模式的文件的大数据项,而连接则会交叉匹配两个符合模式的文件,通常会生成更多的数据项。
-
组输入使您能够在单一仓库中匹配文件对,而连接则需要至少两个仓库。
-
组输入在时间序列场景中尤其有用,尤其是在您需要根据时间戳对文件进行分组时。
因此,你可以创建一个带有替换组的 cron 流水线,该替换组匹配特定的时间戳。
例如,假设你有一个数据仓库,其结构如下:
/data-0101-2020.txt file 2B
/data-0101-2021.txt file 2B
/data-0102-2020.txt file 2B
/data-0102-2021.txt file 2B
/data-0103-2020.txt file 2B
/data-0103-2021.txt file 2B
/data-0104-2021.txt file 2B
/data-0105-2021.txt file 2B
/data-0106-2021.txt file 2B
/data-0107-2021.txt file 2B
你可以使用 YAML 格式创建如下的流水线:
---
pipeline:
name: test-group
transform:
cmd:
- python3
- "/test.py"
input:
group:
- pfs:
repo: data
glob: "/data-(*)-(*).txt"
group_by: "$1"
你的流水线中列出了两个替换组。第一个替换组匹配文本文件名称中的月日。例如,在文件 /data-0104-2021.txt 中,它是 0104。第二个替换组匹配时间戳中的年份。在同一个文件中,它是 2021。
如果你在流水线中指定了第一个匹配组,最终的数据列表将包含三对数据,总共七个数据项:
data@...:/data-0101-2020.txt, data@..:/data-0101-2021.txt
data@...:/data-0102-2020.txt, data@...:/data-0102-2021.txt
data@...:/data-0103-2020.txt, data@...:/data-0103-2021.txt
data@...:/data-0104-2021.txt
data@...:/data-0105-2021.txt
data@...:/data-0106-2021.txt
data@...:/data-0107-2021.txt
在前面的输出中,匹配的日期和月份的文件,如 0101,被分组为一个数据项。如果你将 group_by 参数更改为使用第二个替换组,即按年份分组,则数据列表将包含两个数据项,将文件按年份分组:
- data@ecbf241489bf452dbb4531f59d0948ea:/data-0101-2020.txt, data@ecbf241489bf452dbb4531f59d0948ea:/data-0102-2020.txt, data@ecbf241489bf452dbb4531f59d0948ea:/data-0103-2020.txt
- data@ecbf241489bf452dbb4531f59d0948ea:/data-0101-2021.txt, data@ecbf241489bf452dbb4531f59d0948ea:/data-0102-2021.txt, data@ecbf241489bf452dbb4531f59d0948ea:/data-0103-2021.txt, data@ecbf241489bf452dbb4531f59d0948ea:/data-0104-2021.txt, data@ecbf241489bf452dbb4531f59d0948ea:/data-0105-2021.txt, data@ecbf241489bf452dbb4531f59d0948ea:/data-0106-2021.txt, data@ecbf241489bf452dbb4531f59d0948ea:/data-0107-2021.txt
在本节中,我们了解了最重要的 Pachyderm 流水线原语及其相互之间的区别。
摘要
在这一章中,我们了解了最重要的 Pachyderm 版本控制原语,包括仓库、分支和提交。我们回顾了这些与 Git 版本控制系统相似,但也存在一些非常重要的区别。
我们已经了解了 Pachyderm 流水线和输入的类型,以及如何通过使用通配符模式和数据项来扩展和优化流水线。
在下一章中,我们将更详细地回顾 Pachyderm 流水线规范,并学习如何使用各种流水线设置以最有效的方式运行流水线。
进一步阅读
-
Git 文档:
git-scm.com/ -
Kubernetes 文档:
kubernetes.io/docs/home -
Helm 文档:
helm.sh/docs/
第三章:第三章:象皮管道规范
机器学习(ML)管道是一个自动化工作流,它使你能够对不同的数据和参数组合持续执行相同的代码。管道确保每个周期都是自动化的,并且按照相同的步骤顺序执行。在许多其他技术中,像在 Pachyderm 中,机器学习管道是通过一个叫做管道规范(pipeline spec)的配置文件定义的。
Pachyderm 管道规范是 Pachyderm 中最重要的配置,因为它定义了你的管道执行的任务、执行频率、工作如何分配给 Pachyderm 工作节点,以及结果输出的地点。
本章旨在作为管道规范参考,并将带你了解你可以为管道指定的所有参数。为此,我们将讨论以下主题:
-
管道规范概述
-
理解输入
-
探索信息参数
-
探索转换
-
优化你的管道
-
探索服务参数
-
探索输出参数
管道规范概述
通常,当你进行机器学习实验时,涉及多个顺序步骤。在最简单的场景下,你的管道从输入仓库获取输入,应用你的转换代码,并将结果输出到输出仓库。例如,你可能有一组图片,要应用单色滤镜,然后将结果输出到一个与管道同名的输出仓库。这个工作流仅执行一个操作,可以称为单步管道,或者单步工作流。这样管道的图示可能如下所示:

图 3.1 – 单步工作流
这个简单管道的规范,采用 YAML 格式,看起来会像这样:
---
pipeline:
name: apply-photo-filter
transform:
cmd:
- python3
- "/photo-filter.py"
image: myregistry/filter
input:
pfs:
repo: photos
glob: "/"
这是你可以创建的最简单的管道规范。它必须包含以下参数:
-
name:为你的管道指定一个描述性的名称。通常,管道的名称描述了机器学习工作流中的某个步骤。例如,如果这个管道对你的图片应用滤镜,你可以称它为apply-photo-filter。或者,如果它进行模型验证,你可以称它为cross-validation。 -
transform:此参数包括你的转换代码,可以作为对文件的引用或直接内联指定。我们将在下一节详细讨论这个参数。 -
input:该参数指的是一个现有的输入仓库,文件位于该仓库中以供流水线使用。input是你流水线工作节点下的一个文件系统,位于pfs/目录下。例如,如果你的仓库名为photos,它会存储在工作节点的pfs/photos下。输出仓库由流水线自动创建,并存储在pfs/out下。所有输出仓库的名称与流水线名称相同。例如,如果你的流水线名为apply-photo-filter,那么输出仓库会存储为apply-photo-filter,位置在pfs/out/。
这是一个非常简单的流水线示例。在更现实的应用场景中,通常会有多个流水线步骤。在典型的机器学习流水线中,你需要执行数据预处理、训练、交叉验证等步骤。当多个流水线串联在一起时,这被称为 多步骤工作流。例如,如果你正在创建一个自然语言处理(NLP)流水线,可能会有如下结构:

图 3.2 – 多步骤工作流
在前面的示意图中,每个流水线都有一个流水线规范,定义了名称、输入仓库、转换代码以及其他参数。
所有流水线规范必须以 YAML Ain't Markup Language(YAML)或 JavaScript Object Notation(JSON)格式编写。这些格式便于人类阅读和编写,并广泛应用于各类行业中的配置文件中。它比 可扩展标记语言(XML)或其他类似格式更容易编写。
现在我们已经回顾了最基本的流水线规范,并查看了一个更现实的示例,让我们来回顾一下你可以指定的其他参数。
理解输入
我们在第二章《Pachyderm 基础》一章中详细描述了输入,并提供了示例。因此,在本节中,我们只会提到输入定义了流水线的类型。你可以指定以下几种类型的 Pachyderm 输入:
-
PFS 是一个通用参数,用于定义所有多输入流水线中的标准流水线和输入。
-
Cross 是一种输入,它创建两个输入仓库中数据项的笛卡尔积。生成的输出将包含来自输入仓库的所有数据项的所有可能组合。
-
Union 是一种输入,它将一个仓库中的数据项添加到另一个仓库的数据项中。
-
Join 是一种输入,它将具有特定命名模式的数据项匹配起来。
-
Spout 是一种输入,它从第三方来源获取数据,并将数据添加到 Pachyderm 文件系统中以供进一步处理。
-
Group 是一种输入,它根据配置的命名模式将来自多个仓库的数据项组合在一起。
-
Cron 是一种根据指定时间间隔运行的流水线。
-
Git 是一种输入,可以让你从 Git 仓库中导入数据。
对于除 Cron 和 Git 外的所有输入,你可以定义一个 pfs 参数来定义输入。
pfs
pfs 参数,代表 pfs 输入。你需要为所有管道定义一个或多个 pfs 输入,除了 Cron 和 Git。
以下是 pfs 输入的子参数:
-
name:管道的名称。 -
repo:一个 Pachyderm 输入库,数据存储在此处。 -
branch:Pachyderm 输入库中的一个分支,数据存储在此分支中。通常,这将是master分支。 -
glob:一个定义如何将数据分块进行处理的参数。你可以在 第二章,Pachyderm 基础知识 中的 Datums 部分阅读更多关于glob参数的内容。 -
lazy:一个启用较慢、较不激进数据下载的参数。lazy参数在你需要查看数据的一个子集时非常有用。 -
s3:这个参数定义是否在管道中包含 S3 网关 sidecar。当你通过 S3 网关与第三方应用集成时,它确保管道的来源信息被保留。
你可以在 第二章,Pachyderm 基础知识 中阅读更多关于管道和输入类型的信息,并查看示例管道。接下来的部分描述了可以为管道定义的信息性参数。
探索信息性参数
管道信息性参数定义了管道的基本信息。在所有这些参数中,只有 name 参数是任何管道规范中必需的。其他所有参数都是可选的,可以省略。让我们更详细地了解这些参数。
name
name 参数是管道的描述性名称。通常,你会根据管道执行的变换类型来命名管道。例如,如果你的管道执行图像分类,你可能想将其命名为 image-classification。管道名称必须由字母数字字符、短横线和下划线组成,并且不能超过 63 个符号。
以下是 name 参数的 YAML 格式示例:
---
pipeline:
name: image-classification
以下是 name 参数的 JSON 格式示例:
{
"pipeline": {
"name": "image-classification"
},
接下来,我们来看看 description 参数。
description
description 参数提供关于管道的附加信息。虽然它是一个可选参数,但最好为你的管道添加一个简短的描述。例如,如果你的管道执行图像分类,你可以添加以下描述:一个使用 scikit-learn 进行图像分类的管道。
以下是 description 参数的 YAML 格式示例:
description: A pipeline that performs image classification by using scikit-learn.
以下是 description 参数的 JSON 格式示例:
"description": "A pipeline that performs image classification by using scikit-learn.",
接下来,我们了解一下 metadata。
metadata
metadata 参数使您能够指定 Kubernetes 标签或注释。标签通常用于将 Kubernetes 对象分组到某种类别中,帮助简化这些对象的管理。标签可以查询以显示相同类型的对象。
注释则可以用来指定 Kubernetes 中未定义的任何随机键值对,这些键值对可以供外部应用程序使用。您可以使用注释来定义服务的类型,例如 pach_patch 或 pach_spec。在每个流水线规范中,可以指定多个标签和注释。
这是一个如何在 YAML 格式中指定注释的示例:
metadata:
annotations:
annotation: data
以下示例展示了如何在 JSON 格式中指定注释:
"metadata": {
"annotations": {
"annotation": "data"
}
},
以下示例展示了如何在 YAML 格式中指定标签:
metadata:
labels:
label: object
最后,以下示例展示了如何在 JSON 格式中指定标签:
"metadata": {
"labels": {
"label": "object"
}
},
现在我们已经了解了信息性参数,让我们看看 Pachyderm 流水线中的 transformation 部分。
探索转换
transformation 部分是您定义流水线转换代码的地方。它是流水线功能的核心。除非是两个流水线之间的连接器,或者是将结果导出到 Pachyderm 外部的流水线,大多数流水线都必须具有 transformation 部分。
transformation 部分最重要的参数——也是最常用的——是 image 和 cmd 或 stdin、env 和 secrets。
让我们更详细地看看这些参数。
image
image 参数定义了一个 Docker 镜像,您的流水线将在其中运行。一个 Docker 镜像包含了流水线容器中环境的相关信息。例如,如果您运行 Python 代码,您需要在流水线镜像中包含某个版本的 Python。您可以使用许多公开可用的容器来构建您的流水线。
您还可以在该容器中包含您的脚本。除非您的代码只是一个可以通过 stdin 参数内联指定的 Bash 脚本,否则您可能需要构建自己的 Docker 镜像,将代码包含在镜像中,并将其存储在公共或私有容器注册表中。Docker 镜像是通过 Dockerfile 构建的,Dockerfile 描述了容器环境以及您可以在容器中运行的内容。您可以在 docs.docker.com/ 阅读更多关于 Docker 镜像的信息。
重要提示
不要使用 Docker 的 CMD 指令;请改用 RUN。CMD 指令会失败。
以下代码展示了如何在 YAML 格式中指定 Docker image:
metadata:
labels:
label: object
以下代码展示了如何在 JSON 格式中指定 Docker image:
"transform": {
"image": "my-image",
然而,仅仅指定 Docker 镜像是不够的。您必须定义要运行的内容,可以通过 cmd 或 stdin 参数来实现。
cmd
cmd参数定义了管道将对数据运行的代码。你可以在cmd行中做很多灵活的配置。通常,你会指定要运行的命令类型,例如python,或者设置它运行命令行 shell,例如sh或bash,然后在stdin参数中指定你想要运行的命令列表。
这两种方法没有区别或优先之分。唯一的区别是,如果你在cmd参数中指定了文件,你需要构建一个 Docker 镜像并将该文件包含在镜像中。
例如,如果你有一个 Python 3 文件,包含你希望在数据上运行的代码,你可以在 YAML 格式中像这样指定它:
cmd:
- python3
- "/test.py"
另外,你可以在 JSON 格式中指定标签:
"transform": {
"cmd": [ "python3", "/test.py" ],
然而,如果你想在stdin参数中内联指定命令,只需按照cmd参数中指定的格式,如此,在 YAML 格式中:
cmd:
- python3
你也可以使用 JSON 格式来实现相同的功能:
"transform": {
"cmd": [ "python3" ],
请参阅stdin部分,了解如何指定内联代码的示例。
然而,你的cmd字段可能会更复杂。例如,你可以在cmd参数中指定一个脚本。
以下文本是你可以在 YAML 格式的cmd字段中使用的语法示例:
transform:
image: my-image
cmd:
- tree
- "/pfs"
- "&&"
- python
- my-script.py
- "--outdir"
- "/pfs/out"
- "--input"
- "/pfs/data "
以下文本是你可以在 JSON 格式的cmd字段中使用的语法示例:
"transform": {
"image": "my-image",
"cmd": ["tree",
"/pfs",
"&&",
"python",
"my-script.py",
"--outdir", "/pfs/out",
"--input", "/pfs/data "]
},
接下来,让我们回顾一下stdin参数。
stdin
stdin参数类似于 UNIX 标准输入(stdin),它使 Pachyderm 环境与管道工作者之间能够进行通信。这意味着你可以在stdin字段中按cmd命令指定的格式插入代码。你也可以像cmd参数一样指定代码文件的路径。
这种方法不需要你构建 Docker 镜像,允许你通过管道规范完全配置管道。如果你对 Docker 镜像构建过程不熟悉,这种方法可能更具吸引力。然而,对于更复杂的管道,你可能希望将脚本保存为文件,构建 Docker 镜像,并在管道中使用它们。
以下代码展示了你可以在 YAML 格式的stdin字段中使用的语法:
transform:
cmd:
- bash
stdin:
- for f in /pfs/data/*
- do
- filename=$(basename "$f")
- cp /pfs/data/* pfs/out/mypipeline/*
- done
以下是你可以在 JSON 格式的stdin字段中使用的语法示例:
"transform": {
"cmd": ["bash"],
"stdin": [
"for f in /pfs/data/*",
"do",
"filename=$(basename \"$f\")",
"cp /pfs/data/* pfs/out/mypipeline/*",
"done"]
},
由于前面的示例没有引用任何文件,你不需要为它们构建特定的 Docker 镜像并将文件包含在内。
然而,如果你引用了任何文件或任何比 Bash 稍微复杂的环境先决条件,你可能需要一个 Docker 镜像。例如,如果你有一个包含代码的my-script.py文件,你需要构建一个 Docker 镜像,包含该脚本,并且你必须在管道规范中引用它。
err_cmd
err_cmd参数使您能够定义 Pachyderm 如何处理失败的数据项,并最终允许您将失败的数据项视为非关键错误,从而允许包含失败数据项的作业成功,并仅使用健康数据项触发下一个作业。err_cmd不会将任何数据写入输出仓库。err_cmd字段通常与err_stdin字段结合使用,您可以在其中指定实际的错误代码,尽管您也可以引用包含错误代码的文件。如果您希望即使作业包含失败的数据项,您的管道仍然成功,您只需设置"err_cmd": true。
以下是您可以在err_cmd字段中使用的语法,格式为 YAML:
transform:
...
err_cmd:
- bash
- "/my-error-code.sh"
以下是您可以在err_cmd字段中使用的语法,格式为 JSON:
"transform": {
...
"err_cmd": [ "bash", "/my-error-code.sh"],
在下一节中,我们将查看如何将err_cmd与err_stdin结合使用的示例。
err_stdin
err_stdin参数与err_cmd参数结合使用,用于指定针对失败数据项运行的错误代码。类似于stdin参数,您可以指定内联代码来处理失败的数据项。例如,您可能希望检查数据项是否位于特定目录中,如果是,则将该数据项标记为失败。通常,您可以编写一个简单的 Bash 脚本,使用if… then条件来处理此问题。
以下代码显示了您可以在err_stdin与err_cmd字段中结合使用的语法,格式为 YAML:
transform:
...
err_cmd:
- bash
err_stdin:
- if
- "[-a /pfs/repo1]"
- then
- exit 0
- fi
- exit 1
以下代码显示了您可以在err_stdin与err_cmd字段中结合使用的语法,格式为 JSON:
"transform": {
...
"err_cmd": [
"bash"
],
"err_stdin": [
"if",
"[-a /pfs/repo1]",
"then",
"exit 0",
"fi",
"exit 1"
]
接下来,让我们了解env参数。
env
env参数使您能够指定 Pachyderm 环境变量和您需要与其他第三方工具通信的任意变量。这些参数可以包括目录和文件路径、主机名和端口、密钥访问、各种标识符等。
也可以包含 Pachyderm 变量。例如,您可以使用LOG_LEVEL环境变量来指定pachd的日志消息详细程度。另一个例子是,您还可以在env字段中指定 AWS 区域和桶。
以下代码显示了您可以在env字段中使用的语法,格式为 YAML:
transform:
...
env:
AWS_REGION: us-west-2
S3_BUCKET: s3://my-bucket/
以下代码显示了您可以在env字段中使用的语法,格式为 JSON:
"transform": {
...
"env": {
"AWS_REGION": "us-west-2",
"S3_BUCKET": "s3://my-bucket/"
}
},
有关 Pachyderm 变量的完整列表,请参阅 Pachyderm 文档:docs.pachyderm.com/latest/deploy-manage/deploy/environment-variables/。
secrets
secrets字段使您能够指定 Kubernetes 密钥,这些密钥包含敏感信息,如密码或 SSH 公钥。您需要通过使用env_var和key参数或mount_point参数来定义一个密钥。
以下代码显示了您可以在name和mount_path字段中使用的语法,以设置secrets文件的路径,格式为 YAML:
transform:
...
secrets:
name: my-ssh-key
mount_path: "/path/to/file"
以下代码展示了如何以 JSON 格式指定这些参数:
transform:
...
"secrets": {
"name": "my-ssh-key",
"mount_path": "/path/to/file"
}
以下代码展示了你可以在env_var和key参数中使用的语法,用于以 YAML 格式设置秘密:
transform:
...
secrets:
name: my-ssh-key
env_var: MY_KEY
key: "mykey"
以下是如何以 JSON 格式执行相同操作:
"transform": {
...
"secrets": {
"name": "my-ssh-key",
"env_var": "MY_KEY",
"key": "my_key"
}
接下来,我们来了解一下image_pull_secrets。
image_pull_secrets
image_pull_secrets参数使你能够配置 Pachyderm 管道,从私人 Docker 注册表拉取镜像。要指定此参数,你需要创建一个带有 Docker 配置的 Kubernetes 秘密,具体描述请参见 Kubernetes 文档:https://kubernetes.io/docs/concepts/containers/images/#creating-a-secret-with-a-docker-config,然后在管道规范中的image_pull_secrets参数下指定该秘密。你需要使用 Docker 镜像的完整路径,以确保管道能够正确拉取镜像。
以下代码展示了你可以在image_pull_secrets参数中使用的语法,用于启用管道从私人 Docker 注册表拉取镜像的 YAML 格式:
transform:
...
image: my-private-docker-registry.com/my-project/my-image:latest
image_pull_secrets:
- my-secret
这是如何以 JSON 格式编写相同内容:
"transform": {
...
"image": "my-private-docker-registry.com/my-project/my-image",
"image_pull_secrets": ["my-secret"]
接下来,我们将审查的参数是accept_return_code。
accept_return_code
accept_return_code参数使你能够指定一个整数数组,定义管道仍然被视为成功的错误代码。你可以在希望即使某部分失败,代码仍然成功的情况下使用此功能。这个参数类似于err_cmd功能。
以下代码展示了你可以在accept_return_code参数中使用的语法,用于以 YAML 格式指定错误代码:
transform:
...
accept_return_code:
- 256
以下是以 JSON 格式的相同示例:
"transform": {
...
"accept_return_code": [256]
接下来,我们将查看的参数是debug。
debug
debug参数使你能够设置管道日志输出的详细程度。默认启用基本日志记录,但如果你希望包含更多详细的消息,可以将此参数设置为true。默认情况下,此参数为false。
以下是如何在 YAML 格式中启用管道的调试日志记录:
transform:
...
debug: true
这是如何以 JSON 格式启用管道的调试日志记录:
"transform": {
...
"debug": true
接下来,我们来了解如何使用user参数。
user
user参数使你能够定义一个用户和一个组,用来运行容器的代码。这个参数类似于 Docker 的USER指令,你也可以通过Dockerfile来定义它。默认情况下,Pachyderm 首先检查Dockerfile中的内容,并为管道规范中的user参数设置该值。如果在Dockerfile和管道规范中都没有指定,默认使用的参数值是root。只有在使用--no-expose-docker-socket参数部署 Pachyderm 时,必须在管道规范中显式指定用户。
你可以在docs.docker.com/engine/reference/builder/#user上阅读更多关于 Docker USER参数的信息。
以下是如何在 YAML 格式中指定 user 的方式:
transform:
...
user: test-user
以下是如何在 JSON 格式中指定 user 的方式:
"transform": {
...
"user": "test-user"
现在,让我们了解 working_dir 参数。
working_dir
working_dir 参数使您能够为管道容器指定工作目录。此参数类似于 Docker 的 WORKDIR 指令,您也可以通过 Dockerfile 定义它。默认情况下,Pachyderm 会首先检查 Dockerfile 中的内容,并将其值设置为管道规范中的 working_dir 参数。如果 Dockerfile 和管道规范中都没有指定,则使用默认参数,即根目录(/)或 Docker 镜像从基础镜像继承的目录。只有在使用 --no-expose-docker-socket 参数部署 Pachyderm 时,您才需要在管道规范中明确指定工作目录。
您可以在 docs.docker.com/engine/reference/builder/#workdir 阅读更多关于 Docker Workdir 参数的信息。
以下是如何在 YAML 格式中指定 workdir 的方式:
transform:
...
working_dir: /usr/src/test
在 JSON 格式中,相同的参数如下所示:
"transform": {
...
"working_dir": "/usr/src/test"
接下来,我们将了解 dockerfile 参数。
dockerfile
dockerfile 参数使您能够指定 Dockerfile 的路径,用于您的管道。当您使用 Pachyderm 的 pachctl update-pipeline –build -f <pipeline-spec> 来为管道构建新的 Docker 镜像时,这非常有用。默认情况下,Pachyderm 会在与管道规范相同的目录中查找 Dockerfile。但通过 dockerfile 参数,您可以设置任何路径。
以下是如何在 YAML 格式中指定 Dockerfile 路径的方式:
transform:
...
dockerfile: /path/to/dockerfile
您也可以像这样在 JSON 格式中执行相同操作:
"transform": {
...
"dockerfile": "/path/to/dockerfile "
在本节中,我们了解了可以为转换代码指定的所有参数。在下一节中,我们将回顾如何控制管道工作者的性能,并分配资源限制来优化管道。
优化您的管道
本节将带您了解可能帮助您优化管道以提高性能的管道规范参数。由于 Pachyderm 运行在 Kubernetes 上,它是一个高度可扩展的系统,可以帮助您明智地使用底层硬件资源。
Pachyderm 的最大优势之一是您可以为每个管道单独指定资源,以及定义每次运行时管道将生成多少个工作者,以及它们在空闲等待新工作时的行为。
如果您只是测试 Pachyderm,以了解它是否适合您的用例,那么优化参数可能不那么重要。但如果您正在实施一个包含多个管道且大量数据被注入到 Pachyderm 中的企业级数据科学平台,了解如何优化管道将变得至关重要。
在继续之前,您必须理解 Pachyderm 数据项的概念。数据项在管道可扩展性中起着重要作用。如果您还没有阅读第二章,《Pachyderm 基础》一章,建议在继续之前先阅读它。
parallelism_spec
parallelism_spec定义了为您的管道启动的工作节点数量。您可以指定coefficient或constant策略。默认情况下,Pachyderm 会为每个管道部署一个工作节点,使用constant策略,值为1。
coefficient策略意味着 Pachyderm 将根据指定的系数创建多个工作节点。例如,如果您在 Kubernetes 集群中有 50 个节点,并将coefficient策略设置为1,Pachyderm 将使用该集群的所有 50 个节点。如果您使用coefficient策略,您的管道需要访问 Kubernetes 的管理节点。如果您在托管版本的 Kubernetes 上运行 Pachyderm,例如在 AWS 或 GKE 平台上,您可能无法访问这些节点,管道将不断重启。在这种情况下,您将必须使用constant策略。
constant策略使您能够为管道指定确切数量的工作节点,如 3、25 或 100。这些工作节点将在该管道中无限期运行。然而,如果您希望在空闲时动态调整集群规模,您可以设置standby:true参数,以便集群根据工作负载动态调整大小。
以下代码展示了您可以在parallelism_spec参数中使用的语法,用于指定coefficient策略的 YAML 格式:
parallelism_spec:
coefficient: '1'
以下代码展示了您可以在parallelism_spec参数中使用的语法,用于指定coefficient策略的 JSON 格式:
"parallelism_spec": {
"coefficient": "1"
},
这是您可以在 YAML 格式中定义parallelism_spec参数以指定constant策略的方式:
parallelism_spec: until_success
以下代码展示了如何在parallelism_spec参数中使用constant策略的 JSON 格式:
"parallelism_spec": "until_success"
接下来,让我们学习如何使用reprocess_spec。
reprocess_spec
reprocess_spec使您能够强制管道重新处理所有数据项。默认情况下,Pachyderm 会跳过重新处理成功的数据项,但如果您的管道与外部应用程序或系统进行交互,您可能希望重新处理所有数据项。这种行为可以保护管道免受连接和其他错误的影响。
以下是您可以在reprocess_spec中使用的 YAML 格式语法:
reprocess_spec:
constant: '1'
以下是您可以在reprocess_spec中使用的 JSON 格式语法:
"parallelism_spec": {
"constant": "1"
}
接下来,我们将学习如何使用cache_size。
cache_size
cache_size 参数使您能够定义用户和存储容器的缓存内存大小。Pachyderm 会在处理数据之前预先下载数据,增加 cache_size 可以帮助提高下载速度。默认值为 64M,您可以根据需要增加该值来缓存您的数据。这个参数是微调参数,只有在通过 glob 和 parallelism_spec 优化了管道之后才应该使用。
以下是您可以在 cache_size 参数中使用的语法示例,用于以 YAML 格式增加缓存大小:
cache_size: 1G
在 JSON 格式中,相同的参数将如下所示:
"cache_size": "1G",
现在,让我们回顾一下 max_queue_size 参数。
max_queue_size
max_queue_size 参数定义了管道可以同时下载多少数据项。您可以使用 max_queue_size 使管道在处理其他数据项时预先下载下一个数据项。默认情况下,Pachyderm 将 max_queue_size 设置为 1,意味着一次只能下载一个数据项。这是一个微调参数,如果下载时间显著长于处理时间,调整此参数可以提高数据项下载到工作节点的速度。然而,只有在正确配置了 glob 和 parallelism_spec 后,您才应该调整此参数。
以下代码展示了如何使用 max_queue_size 参数以 YAML 格式增加缓存大小:
max_queue_size: 5
在 JSON 格式中,相同的键值对如下所示:
"max_queue_size": "5",
接下来,我们将学习 chunk_spec。
chunk_spec
chunk_spec 参数定义了每个工作节点处理的数据项数量。默认情况下,此参数设置为 1。数据块可以通过 number(数据项数量)或 size_bytes(字节大小)来设置。例如,如果您将 chunk_spec 中的 number 设置为 3,则每个工作节点一次会处理三个数据项。
使用 size_bytes,如果数据项的运行时间与其大小成正比,您可以使数据项大小均匀。如果不是这种情况,请改用 number 参数。
以下代码展示了如何在 chunk_spec 参数中设置 number,以使工作节点一次处理指定数量的数据项,并以 YAML 格式呈现:
chunk_spec:
number: '10'
这是您可以在 chunk_spec 参数中设置 number,使得工作节点一次处理指定数量数据项的 JSON 格式:
"chunk_spec": {
"number": "10"
},
以下代码展示了如何在 chunk_spec 参数中设置 size_bytes(数据项的字节数),使得工作节点一次处理指定数量的数据项,并以 YAML 格式呈现:
chunk_spec:
size_bytes: '1210'
如果您更喜欢使用 JSON 格式,设置 chunk_spec 参数中的 size_bytes,使工作节点一次处理指定数量的数据项,将是如下所示:
"chunk_spec": {
"size_bytes": "1210"
},
接下来,我们将学习如何设置资源限制。
resource_limits
resource_limits 参数使你能够限制 GPU 资源的 type 数量。管道工作者不能使用超过你指定的资源限制。resource_request 参数类似,但如果有足够的资源,工作者可以使用超过请求的资源。你可以在 Kubernetes 文档中阅读更多关于 resource_limits 和 resource_requests 的内容,链接:kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits。
以下代码展示了如何在 YAML 格式中设置 resource_limits 参数以限制 Pachyderm 工作者资源:
resource_limits:
cpu: 1
gpu:
type: nvidia.com/gpu
number: 1
memory: 16G
以下代码展示了如何在 JSON 格式中设置 resource_limits 参数以限制 Pachyderm 工作者资源:
"resource_limits": {
"cpu": 1,
"gpu": {
"type": "nvidia.com/gpu",
"number": 1,
"memory": "16G"
}
},
如果你需要设置特定的云资源类型,例如 Google Kubernetes Engine 中的 TPU,你可以通过配置 pod_patch 来实现。有关更多信息,请参见接下来的 pod_patch 部分。
resource_requests
resource_requests 参数指定管道工作者请求处理一个工作单元所需的资源数量。与 resource_limits 参数不同,如果有更多资源可用,工作者可以使用这些资源。该参数的语法与 resource_limits 相同。
sidecar_resource_limits
该参数类似于 resource_limits,并定义了管道 sidecar 容器的资源。有关一些示例语法,请参见 resource_limits 部分。
scheduling_spec
scheduling_spec 参数使你能够根据指定的 node_selector 或 priority_class 来指定运行管道代码的 Pods。node_selector 允许你指定一组具有相同标签的节点,称为 nodeSelector,而 priority_class 允许你将管道调度到匹配 Kubernetes PriorityClass 的节点组上。scheduling_spec 参数通常用于根据资源调度管道到特定的工作节点。有关这些属性的更多信息,请参见 kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector 和 kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass。
以下代码展示了如何在 YAML 格式中定义 nodeSelector:
scheduling_spec:
node_selector:
kubernetes.io/my-hostname: my-node
以下代码展示了如何在 JSON 格式中定义 nodeSelector:
"scheduling_spec": {
"node_selector": {"kubernetes.io/my-hostname": "my-node"
}
},
要在 YAML 格式中定义 PriorityClass 参数,请使用以下代码:
scheduling_spec:
priority_class: high-priority
kubernetes.io/my-hostname: my-node
或者,如果你更喜欢使用 JSON 格式,请按以下方式设置 PriorityClass:
"scheduling_spec": {
"priority_class": "high-priority"
}
接下来,我们将学习如何为一个作业设置超时。
job_timeout
job_timeout 参数使你能够为 Pachyderm 作业运行设置超时。这意味着如果作业在指定时间内未完成,它将失败。默认情况下,该参数是禁用的,你可以将其设置为你希望的时间值。
以下代码展示了如何在 YAML 格式中定义 job_timeout 参数:
job_timeout: 10m
这是相同示例的 JSON 格式:
"job_timeout": "10m"
接下来,我们将了解 datum_timeout。
datum_timeout
datum_timeout 超时与 job_timeout 类似,唯一的区别是超时设置在数据粒度级别。语法相同。
datum_tries
datum_tries 参数定义了 Pachyderm 在数据失败时重试管道的次数。默认情况下,该参数设置为 3。如果你只希望管道运行一次,不再尝试处理失败的数据,请将此值设置为 1。
以下代码展示了如何在 YAML 格式中定义 job_tries 参数:
datum_tries: 1
如果你更倾向于使用 JSON 格式编写,可以使用以下代码:
"datum_tries": "1"
在本节中,我们学习了如何通过微调管道规范来实现最佳性能。下一节,你将学习如何配置一些辅助管道操作的服务参数。
探索服务参数
现在,让我们来看一下服务参数。服务参数包括那些让你收集数据统计信息以及修补管道 Kubernetes 配置的参数。
enable_stats
enable_stats 参数顾名思义,用于启用管道统计日志记录。默认情况下,该参数是禁用的。为了调试,建议将此参数设置为true。启用统计数据收集后,统计信息将保存在 stats 文件夹中,且无法禁用统计数据收集。
以下代码展示了如何在 YAML 格式中定义 enable_stats 参数:
enable_stats: true
以下代码展示了如何在 JSON 格式中定义 enable_stats 参数:
"enable_stats": true,
接下来,我们将了解pod_patch。
pod_patch
pod_patch 参数使你能够重写管道 Pods 中的任何字段。这对许多场景有用,一个例子是将卷挂载到你的管道中。为了创建 pod_patch,你通常需要使用 JSON patch 构建器,将其转换为一行格式,并添加到管道规范中。
以下代码展示了如何在 YAML 格式中定义 pod_patch 参数:
pod_patch: '[{"op": "add","path": "spec/initContainers/0/resources/limits/my-volume"}]'
以下是相同内容的 JSON 格式:
"pod_patch": "[{\"op\": \"add\",\"path\": \"spec/initContainers/0/resources/limits/my-volume\"}]"
这就是你需要了解的所有服务参数。接下来的章节,我们将介绍一些使你能够配置输出分支并将管道结果写入外部存储的参数。
探索输出参数
输出参数使你能够配置处理后的数据在结果落入输出库后发生的事情。你可以设置它将数据放置在外部 S3 存储库中或配置出口。
s3_out
s3_out参数使您的 Pachyderm 管道能够将输出写入 S3 存储库,而不是标准的pfs/out。此参数需要一个布尔值。要访问输出存储库,您需要使用 S3 协议地址,如s3://<output-repo>。输出存储库仍将与您的管道名称同名。
以下代码展示了如何在 YAML 格式中定义s3_out参数:
s3_out: true
这里是如何在 JSON 格式中做同样的操作:
"s3_out": true
现在,让我们了解一下egress。
egress
egress参数使您能够指定输出数据的外部位置。Pachyderm 支持 Amazon S3(s3://协议)、Google Cloud Storage(gs://协议)和 Azure Blob Storage(wasb://协议)。
以下代码展示了如何在 YAML 格式中定义egress参数:
egress:
URL: gs://mystorage/mydir
这里是相同的示例,但使用的是 JSON 格式:
"egress": {
"URL": "gs://mystorage/mydir"
},
接下来,让我们了解如何在 Pachyderm 中配置输出分支。
output_branch
output_branch参数使您能够将结果写入输出存储库中的一个不同于默认master分支的分支。如果您希望创建一个实验或开发输出,而不希望下游管道拾取它,您可能需要这样做。
以下代码展示了如何在 YAML 格式中定义output_branch参数:
output_branch: test
以下代码展示了如何在 JSON 格式中定义output_branch参数:
"output_branch": "test",
本章概述了 Pachyderm 管道规范的内容。
总结
在本章中,我们了解了您可以在 Pachyderm 管道中指定的所有参数、如何优化管道以及如何配置转换部分。管道规范是您管道中最重要的配置属性,因为您将使用它来创建您的管道。如您所见,管道规范在性能优化方面提供了很大的灵活性。虽然一开始可能很难为您的数据类型找到合适的参数,但 Pachyderm 提供了许多微调选项,帮助您为您的机器学习工作流实现最佳性能。
在下一章中,您将学习如何在本地计算机上安装 Pachyderm。
深入阅读
要了解更多关于本章中所涵盖的主题,请查看以下资源:
-
Pachyderm 环境变量:
docs.pachyderm.com/latest/deploy-manage/deploy/environment-variables/ -
Kubernetes 概念:
kubernetes.io/docs/concepts/ -
Pachyderm 管道规范:
docs.pachyderm.com/latest/reference/pipeline_spec/
第二部分:开始使用 Pachyderm
本节将引导您完成在本地计算机或云环境中安装和配置 Pachyderm 的过程,并介绍如何创建您的第一个数据管道,随后解释如何配置端到端的机器学习工作流。
本节包含以下章节:
-
第四章,本地安装 Pachyderm
-
第五章,在云平台上安装 Pachyderm
-
第六章,创建您的第一个数据管道
-
第七章,Pachyderm 操作
-
第八章,创建端到端的机器学习工作流
-
第九章,使用 Pachyderm 进行分布式超参数调优
第四章:第四章:本地安装 Pachyderm
在前几章中,我们了解了 Pachyderm 的架构、Pachyderm 解决方案的内部工作原理,以及版本控制原语,如仓库、分支和提交。我们回顾了为什么可重复性至关重要,以及它为何应成为成功的数据科学流程的一部分。我们还学习了如何在 macOS、Linux 和 Windows 三大平台上进行操作。
有许多方式和平台可以让你使用 Pachyderm 运行端到端的 机器学习(ML)工作流。我们将从最常见和最容易配置的本地部署方法开始,然后在接下来的章节中回顾在云平台上的部署过程。
本章将引导你完成在本地安装 Pachyderm 的过程,让你能够快速开始并测试 Pachyderm。本章将为你运行第一个 pipeline 做好准备。我们将概述系统要求,并指导你安装运行 Pachyderm 所需的所有前置软件。
本章将涵盖以下主要主题:
-
安装所需工具
-
安装 minikube
-
安装 Docker Desktop
-
安装 Pachyderm 命令行界面(CLI)
-
启用 Pachyderm 的自动补全功能
-
准备 Kubernetes 环境
-
部署 Pachyderm
-
访问 Pachyderm 仪表盘
-
删除现有的 Pachyderm 部署
技术要求
无论你使用的是 macOS、Windows 还是 Linux,都需要安装以下工具:
-
Homebrew
-
Kubernetes 的
kubectl -
Helm
-
minikube
-
Docker Desktop(作为 minikube 的替代方案)
-
Pachyderm CLI;即通过
pachctl -
Windows 子系统 for Linux(WSL)用于 Windows 安装
我们将在本章中详细讲解安装和配置这些工具的具体步骤。如果你已经知道如何操作,可以立即开始设置。
安装所需工具
在本节中,我们将介绍如何安装我们将用于准备环境的系统工具,然后再安装 Pachyderm。
安装 Homebrew(仅限 macOS)
尽管 Linux 发行版有许多包管理选项,但 macOS 用户没有默认的包管理器。brew 填补了这个空白,提供了一种很好的解决方案,可以在 macOS 终端和 Linux shell 中轻松安装和管理软件,作为 Linux 发行版中可用的 apt、yum 或 flatpak 的替代方案。
Homebrew 使用 /user/local/Cellar 目录。你常常会听到的另一个术语是 Tap。Tap 是一个 Formulae 的 Git 仓库。
在本章中,我们将经常使用 brew 来安装 macOS 上的各种软件包。因此,如果你使用的是 macOS,则需要先安装它。我们将在本章中使用的相同 brew 命令也可以在 Linux 上运行,但我们会将 Linux 上的 brew 使用保留为可选项:
-
执行以下命令以在你的计算机上安装 Homebrew:
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" -
执行以下命令以验证 Homebrew 是否已安装,并列出可用的命令:
$ brew commands
以下屏幕截图显示了系统的输出:

图 4.1 – brew 命令列表
-
让我们了解一些你将来可能需要的有用 Homebrew 命令。你可以通过执行以下命令更新 Homebrew 本身:
$ brew update -
执行以下命令查找任何过时的配方:
$ brew outdated -
执行以下命令以升级所有过时的配方:
$ brew upgrade
现在你已经在计算机上安装了 Homebrew 包管理器,接下来我们来安装 kubectl。
安装 Windows 子系统 Linux(仅限 Windows)
WSL 是一个工具,它使 Windows 用户能够在 Windows 中原生运行 Linux 命令和实用程序。如果你使用的是 Windows,可以通过以下步骤在机器上安装 WSL:
-
打开 PowerShell 或 Windows 命令提示符。
-
通过运行以下命令安装 WSL:
wsl --install重要说明
如果你使用的是 Windows,请从 WSL 运行本书中描述的所有 Linux 和 Pachyderm 命令。
有关更多信息,请参见官方微软 Windows 文档:https://docs.microsoft.com/en-us/windows/wsl/install。
安装 Kubernetes 命令行工具
在创建第一个 Kubernetes 集群之前,你需要安装 Kubernetes 命令行工具 kubectl,以便执行对集群的命令。现在,让我们了解如何在计算机上安装 kubectl。
有关更多信息,请参见官方 Kubernetes 文档:https://kubernetes.io/docs/home/。
按照以下步骤操作:
- 执行以下命令以在你的计算机上下载并安装
kubectl:
如果你正在使用 Linux,请运行以下命令:
$ curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl
$ chmod +x ./kubectl && sudo mv ./kubectl /usr/local/bin/kubectl
如果你使用的是 macOS(Intel),请运行以下命令:
$ curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl
$ chmod +x ./kubectl && sudo mv ./kubectl /usr/local/bin/kubectl
如果你使用的是 Windows,以下命令将完成此操作:
curl -LO https://dl.k8s.io/release/v1.22.0/bin/windows/amd64/kubectl.exe
-
通过执行以下命令验证你正在使用的版本,并确保已安装
kubectl:$ kubectl version --short --client
这是系统输出的示例:
Client Version: v1.22.3
为了能够执行以下命令,kubectl 的版本必须为 v1.19 或更高版本。
现在你已在计算机上安装了 kubectl,可以对你的 Kubernetes 集群执行命令,接下来我们来安装 Helm。
安装 Helm v3
Helm 是 Kubernetes 集群的流行包管理器。在使用其 Helm 图表部署 Pachyderm 之前,你需要在环境中安装 Helm 二进制文件,以便能够管理 Helm 图表的生命周期。请按照以下步骤在你的计算机上安装 Helm:
-
执行以下命令以下载并在计算机上安装 Helm:
$ curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/ helm/helm/master/scripts/get-helm-3 $ chmod 700 get_helm.sh $ ./get_helm.sh -
通过执行以下命令验证你正在使用的版本,并确保已安装 Helm:
$ helm version --short
这是系统输出的示例:
V3.7.1+g1d11fcb
接下来,在你部署 Pachyderm 之前,你必须安装必要的工具来准备本地 Kubernetes 集群环境。如果你熟悉 Linux 中的容器,你应该对这些工具也很熟悉。如果你使用 Linux 作为本地计算机,请按照 安装 minikube 部分提供的说明来准备环境。如果你使用的是 macOS,请按照 安装 Docker Desktop 部分提供的说明进行操作。由于简单易用,推荐使用 Docker Desktop。
安装 minikube
Minikube 是一个流行的跨平台且轻量级的 Kubernetes 实现,它帮助用户快速创建单节点的本地 Kubernetes 集群。minikube 支持多种运行时,包括 CRI-O、container 和 Docker。它可以作为 虚拟机(VM)、容器或裸机部署。由于 Pachyderm 仅支持 Docker 运行时,我们将介绍如何使用 Docker 容器运行时并将其部署为容器。有关更多配置细节,你可以参考官方 Docker 文档 minikube.sigs.k8s.io/docs/start/。现在让我们安装最新版本的 minikube:
- 执行以下命令,在你的计算机上安装
minikube。
如果你正在使用 Linux,请运行以下命令:
$ curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
$ sudo install minikube-linux-amd64 /usr/local/bin/minikube
如果你使用的是 Windows(需要 Chocolatey 包管理器),请运行以下命令:
choco install minikube
-
通过执行以下命令,验证你正在使用的
minikube版本,并确保已安装 minikube:$ minikube version
以下是命令响应的示例:
minikube version: v1.22.0
commit: a03fbcf166e6f74ef224d4a63be4277d017bb62e
现在你已经安装了 minikube,接下来让我们安装 Docker Desktop。
安装 Docker Desktop
Docker 通过将应用程序与基础设施及其依赖关系分离,简化了应用程序的开发、交付和运行。Pachyderm 仅支持 Docker 容器运行时;因此,在部署 Pachyderm 之前必须安装 Docker 工具。
Docker 作为原生应用程序运行,使用 macOS 沙盒安全模型,并在你的 macOS 上安装所有 Docker 工具,包括 Docker 引擎、CLI、Docker Compose、Credential Helper、Notary 和 Kubernetes。
如果你还没有安装 Docker Desktop,可以按照下一节提供的说明进行安装。否则,你可以跳到 准备 Kubernetes 环境 部分。你还可以参考官方 Docker 文档 docs.docker.com/get-docker/。
为 macOS 安装 Docker Desktop
按照以下步骤在 macOS 上安装 Docker Desktop。Docker 的最新版本支持 macOS 的最后三个版本。如果你的 macOS 版本比最新三个版本更旧,你需要将其升级到最新版本的 macOS:
-
访问 Docker Hub 下载链接
hub.docker.com/editions/community/docker-ce-desktop-mac/下载 Docker Desktop 安装程序。 -
点击
Docker.dmg文件以在工作站上安装。 -
下载完成后,双击
Docker.dmg文件以打开镜像,并将 Docker 图标从窗口拖动到应用程序文件夹完成安装:

图 4.2 – macOS 上的 Docker Desktop 安装界面
-
在应用程序文件夹中,双击 Docker 图标以启动 Docker Desktop。
-
确认你拥有安装 Docker 组件的权限。
-
如果你是第一次使用 Docker,请按照快速教程操作。否则,点击跳过教程以启动 Docker:

图 4.3 – Docker Desktop 图形用户界面
在 Windows 上安装 Docker Desktop
按照以下步骤在 Windows 计算机上安装 Docker Desktop:
-
点击Docker Desktop for Windows。
-
点击Docker Desktop Installer.exe。
-
按照互动提示安装Docker Desktop。
-
在配置页面,确保选择为 WSL 2 安装所需的 Windows 组件。
-
完成后,点击关闭。
-
通过在 Windows 搜索中找到 Docker Desktop 并接受条款与条件,启动 Docker Desktop。之后,Docker 将自动启动。
现在你已经在机器上安装了 Docker Desktop,让我们安装 Pachyderm CLI,称为 pachctl。
安装 Pachyderm 命令行界面
Pachyderm 的 pachctl 用于部署和与 Pachyderm 集群交互。按照以下步骤安装 pachctl:
-
获取
pachctl的最新版本标签,并将其保存在一个名为PACHYDERMVERSION的变量中:$ PACHYDERMVERSION=$(curl --silent "https://api.github.com/repos/pachyderm/pachyderm/releases/latest" | grep '"tag_name":' | \ sed -E 's/.*"v([^"]+)".*/\1/') -
执行以下命令在计算机上安装
pachctl。
如果你使用的是 macOS,请运行以下命令:
$ brew tap pachyderm/tap && brew install pachyderm/tap/pachctl@${PACHYDERMVERSION}
如果你使用的是 Debian Linux 或 Windows 10 上的 WSL,请运行以下命令:
$ curl -o /tmp/pachctl.deb -L https://github.com/pachyderm/pachyderm/releases/download/v${PACHYDERMVERSION}/pachctl_${PACHYDERMVERSION}_amd64.deb && sudo dpkg -i /tmp/pachctl.deb
-
执行以下命令来验证是否已安装
pachctl:$ pachctl version --client-only
以下是系统输出的示例:
COMPONENT VERSION
pachctl 2.0.1
至此,你已安装了运行 Pachyderm 所需的先决条件。现在,让我们准备集群并在本地 Kubernetes 集群上部署 Pachyderm。
启用 Pachyderm 的自动补全
自动补全是 Unix shell 提供的一项功能,通过命令行界面(CLI)自动填写参数。根据系统中使用的 shell 类型,自动补全功能会在你输入命令时,建议或自动补全部分输入的命令,有时按下Tab键即可。Pachyderm 支持 Bourne Again Shell(bash)和 Z shell(zsh,一种扩展的 Bourne shell)的自动补全功能。bash 和 zsh 是 macOS 和 Linux 上最常用的 Unix 命令行解释器。在本节中,你将学习如何启用 Pachyderm 的自动补全功能,以及 pachctl 命令支持的参数。
如果你不知道自己使用的是哪种 shell,请键入以下命令查看:
$ echo "$SHELL"
如果你使用的是 bash,则前面命令的输出应如下所示:
/bin/bash
如果你使用的是 zsh,则前面命令的输出应如下所示:
/bin/zsh
既然我们已经知道使用的是哪种 shell,接下来可以安装 Pachyderm 自动补全。
启用 bash 的 Pachyderm 自动补全
按照以下步骤在你的计算机上启用 Pachyderm 自动补全:
- 执行以下命令以启用
bash-completion。
如果你使用的是带有 Homebrew 的 macOS 或 Linux,请使用以下命令:
$ brew install bash-completion
如果你使用的是 Ubuntu Linux,请使用以下命令:
$ sudo apt install bash-completion
如果你使用的是 RHEL 或 CentOS Linux,请使用以下命令:
$ sudo yum install bash-completion bash-completion-extras
- 执行以下命令以验证
bash-completion是否已在你的计算机上启用。
如果你使用的是 macOS,请运行以下命令:
$ brew info bash-completion
如果你使用的是 Linux,请运行以下命令:
$ complete -p
- 确认
bash-completion的路径指向正确的目录。然后,执行以下任一命令以启用 Pachydermpachctl自动补全:
如果你使用的是 macOS,请运行以下命令:
$ pachctl completion bash --install --path /usr/local/etc/bash_completion.d/pachctl
如果你使用的是 Linux,请运行以下命令:
$ pachctl completion bash --install --path /usr/share/bash-completion/completions/pachctl
到此为止,Pachyderm 的命令行自动补全已经在你的 bash shell 中启用。
启用 zsh 的 Pachyderm 自动补全
zsh 和 macOS Catalina。按照以下步骤在你的计算机上启用 Pachyderm 自动补全:
重要提示
如果你不希望启用自动补全,你可以尝试使用 pachctl shell。要启用此功能,请键入 pachctl shell。
- 执行以下命令以启用
zsh自动补全。
如果你使用的是带有 Homebrew 的 macOS 或 Linux,请使用以下命令:
$ brew install zsh-completion
如果你在 Linux 上,访问 github.com/zsh-users/zsh-completions 页面,并根据你的 Linux 发行版按照说明启用 zsh 补全。例如,对于 Ubuntu 19.10,应该如下所示:
$ echo 'deb http://download.opensuse.org/repositories/shells:/zsh-users:/zsh-completions/xUbuntu_19.10/ /' | sudo tee /etc/apt/sources.list.d/shells:zsh-users:zsh-completions.list
$ curl -fsSL https://download.opensuse.org/repositories/shells:zsh-users:zsh-completions/xUbuntu_19.10/Release.key | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/shells_zsh-users_zsh-completions.gpg > /dev/null
$ sudo apt update && sudo apt install zsh-completions
- 执行以下命令以验证
zsh自动补全是否已在你的计算机上启用。
如果你使用的是 macOS,请运行以下命令:
$ brew info zsh-completions
如果你使用的是 Linux,请运行以下命令:
$ complete -p
- 确认
zsh自动补全的路径指向正确的目录。然后,执行以下任一命令以启用 Pachydermpachctl自动补全。
在 macOS 上,运行以下命令:
$ pachctl completion zsh --install --path /usr/local/share/zsh-completions/_pachctl
如果你使用的是 Linux,请运行以下命令:
$ pachctl completion zsh --install --path /home/linuxbrew/.linuxbrew/share/zsh-completions/_pachctl
到此为止,Pachyderm 命令行自动补全现在已在你的 zsh shell 中启用。接下来,我们来准备 Kubernetes 环境。
准备 Kubernetes 环境
在本节中,你将使用在 安装所需工具 部分中部署的首选工具来配置 Kubernetes 集群。
在 Docker Desktop 上启用 Kubernetes
如果你使用 Docker Desktop 作为容器平台来部署 Kubernetes 集群,可以按照以下步骤启用 Kubernetes:
-
打开 Docker 用户界面。
-
在 Docker UI 的右上角,点击 设置 图标。
-
切换到 Kubernetes 设置面板,并点击 启用 Kubernetes 按钮,以在 Docker Desktop 上启动单节点 Kubernetes 集群。通过点击 应用并重启 按钮来应用这些设置:

图 4.4 – 在 Docker Desktop 中启用 Kubernetes
-
打开终端窗口并通过执行以下命令确认 Kubernetes 是否正在运行:
$ kubectl get node
以下是系统响应的示例:
NAME STATUS ROLES AGE VERSION
docker-desktop Ready control-plane,master 7m9s v1.21.5
至此,你已经在 Docker Desktop 上配置了单节点 Kubernetes 集群。现在,我们准备在本地 Kubernetes 环境中部署 Pachyderm。
使用 minikube 启用 Kubernetes
按照以下步骤在使用 minikube 时本地运行 Kubernetes:
-
将 Docker 设置为
minikube的默认驱动程序:$ minikube config set driver docker -
启动 Kubernetes 集群:
$ minikube start -
执行以下命令以验证你的 Kubernetes 集群是否准备好:
$ kubectl get node NAME STATUS ROLES AGE VERSION minikube Ready control-plane,master 29m v1.20.2
至此,你的 Kubernetes 集群已经使用 minikube 配置完成。现在,我们准备在本地 Kubernetes 环境中部署 Pachyderm。
部署 Pachyderm
在生产环境中运行 Pachyderm 时,建议在可以扩展资源以满足较大流水线计算需求的环境中启动。Pachyderm 可以安装在任何 Kubernetes 集群上,包括 AWS、Google Cloud、Microsoft Azure、IBM Cloud 和 OpenShift 提供的托管 Kubernetes 服务,也可以在本地工作站上安装。在本节中,我们将重点介绍一个较小的测试部署,因此,本地集群足以开始。
Pachyderm 提供了示例 Helm 图表,帮助你将 Pachyderm 部署到所有主要云平台。你可以在 第二章 中了解更多关于 Helm 图表的信息,Pachyderm 基础。由于 Helm 图表是灵活的,你可以选择要安装的组件。例如,你可以安装名为控制台的 Pachyderm 浏览器界面。
Pachyderm 控制台是 Pachyderm 的用户界面,并通过 直接有向图(DAG)提供对你的流水线的鸟瞰图,以及其他有用的功能。
一些组件,如 Pachyderm 控制台,要求企业版许可证,但也可以通过免费试用许可证进行测试,试用期为 30 天。你可以在 www.pachyderm.com/trial/ 请求免费试用许可证。
按照以下步骤在本地 Kubernetes 集群中安装 Pachyderm:
-
部署 Pachyderm 包括多个资源。
helm命令帮助管理复杂 Kubernetes 应用的生命周期,并通过一个命令同时创建所有必要的组件。你可以在第五章中了解更多关于 Helm charts 的选项,在云平台上安装 Pachyderm。现在,让我们执行以下命令将 Pachyderm Helm Chart 仓库添加到本地仓库:$ helm repo add pach https://helm.pachyderm.com -
执行以下命令从 Chart 仓库获取最新的 Chart 信息:
$ helm repo update -
执行以下命令将最新版本的 Pachyderm 部署到你的集群中,无需控制台:
$ helm install pachd pach/pachyderm --set deployTarget=LOCAL
如果你有企业密钥并希望通过 Pachyderm 的控制台用户界面进行部署,请创建一个名为 license.txt 的文件,并将你的企业令牌粘贴到该文件中。然后,运行以下命令:
$ helm install pachd pach/pachyderm --set deployTarget=LOCAL --set pachd.enterpriseLicenseKey=$(cat license.txt) --set console.enabled=true
一旦控制台成功部署,请按照访问 Pachyderm 控制台章节中的说明访问控制台。
前面的命令返回以下输出:

图 4.5 – Pachyderm Helm Chart 在 Kubernetes 上部署
-
你可以检查 Helm Chart 仓库中的
values.yaml文件(github.com/pachyderm/pachyderm/tree/master/etc/helm/pachyderm),了解通过部署该 Chart 创建的 Kubernetes 对象。Pachyderm Helm Chart 创建了 Kubernetes 服务账户、服务、部署、PostgreSQL 和 etcd 实例,所有这些都是运行 Pachyderm 所必需的。 -
Kubernetes 部署是一个控制器,它根据你在清单文件中定义的要求推出一组 Pods 的副本集。副本集是一组相同的服务实例。执行以下命令验证在安装过程中创建的部署状态:
$ kubectl get deployments
前面的命令输出应如下所示:

图 4.6 – Pachyderm 部署对象列表
-
执行以下命令验证安装是否成功,并查看作为部署一部分创建的 Pods:
$ kubectl get pods
前面的命令输出应如下所示:

图 4.7 – Pachyderm Pods 列表
-
执行以下命令连接到你的新 Pachyderm 实例:
pachctl config import-kube local –overwrite pachctl config set active-context local pachctl port-forward -
打开浏览器并访问
http://localhost:4000。 -
使用名为
admin的模拟用户进行身份验证,并使用password作为密码。 -
返回终端并启用身份验证:
pachctl auth activate
系统会提示你再次登录 UI。使用名为 admin 的模拟用户登录,并将 password 作为密码。
-
执行以下命令验证 Pachyderm 是否成功安装:
pachctl version
上述命令的输出应如下所示:
COMPONENT VERSION
pachctl 2.0.1
pachd 2.0.1
现在我们已经在集群中安装了 Pachyderm,可以开始创建我们的第一个管道了。
访问 Pachyderm Console
如果你已与 Pachyderm 集群一起安装了 Console,你可以在 UI 中访问它,并查看你的管道、仓库和其他 Pachyderm 对象。Pachyderm Console 提供 30 天的免费试用期。按照以下步骤访问 Pachyderm Console:
-
执行以下命令以验证企业激活的状态:
pachctl enterprise get-state
上述命令的输出应如下所示:
Pachyderm Enterprise token state: ACTIVE
Expiration: 2022-02-02 22:35:21 +0000 UTC
-
如果端口转发未运行,请执行以下命令启动它。此步骤将把 Pachyderm Console 服务的端口
4000转发到本地工作站的端口4000:pachctl port-forward -
在网页浏览器中,打开
localhost:4000。 -
在登录屏幕上使用默认凭据
admin和password,如下所示:

图 4.8 – Pachyderm Console 登录屏幕
- 点击 登录 访问 Pachyderm Console 后,点击 查看项目 按钮以查看你的仓库和管道:

图 4.9 – Pachyderm 仪表板
因为我们尚未创建任何 Pachyderm 对象,所以此页面为空。
现在你已经学会了如何访问 Pachyderm Console,准备好在 Pachyderm 中创建第一个管道了。
删除现有的 Pachyderm 部署
仅当你想删除集群时才执行此部分的步骤。如果你想继续在其他章节中的示例上工作,请跳过此部分。
如果你需要删除部署并重新开始,你需要清除环境并从 准备 Kubernetes 环境 部分提供的步骤重新开始。当你删除现有的 Pachyderm 部署时,所有组件(除了 Helm 仓库和 pachctl)都会从你的机器中移除。
按照以下步骤删除现有的 Pachyderm 部署:
-
如果你为 Helm 实例使用了不同的名称,请执行以下命令查找你通过 Helm 图表部署的 Pachyderm 实例名称:
$ helm ls | grep pachyderm
上述命令的输出应如下所示:
pachd default 1 2021-11-08 21:33:44 deployed Pachyderm-2.0.1 2.0.1
-
使用你的 Pachyderm 实例名称执行以下命令,从集群中删除 Pachyderm 组件:
$ helm uninstall pachd -
如果你使用的是 minikube,请删除整个 Kubernetes 集群并重新部署,然后再重新部署 Pachyderm:
$ minikube stop $ minikube delete
至此,你已完全从计算机中移除了 Pachyderm 和本地 Kubernetes 集群。
总结
在本章中,我们了解了在本地计算机上为测试目的安装和运行 Pachyderm 所需的软件先决条件。
我们了解了 minikube 和 Docker Desktop 的基本知识,并学习了如何在本地机器上安装它们。我们还学习了如何安装 Pachyderm CLI 并在不同操作系统上启用自动补全功能。
然后,我们在系统上安装了 Helm 和 Pachyderm Helm 仓库。我们了解了 Helm Charts 以及如何获取免费的 Pachyderm 试用许可证。
我们使用基于桌面操作系统的最流行选项部署了一个单节点、本地 Kubernetes 集群。最后,我们部署了 Pachyderm,并学习了如何访问 Pachyderm 控制台。
我们还学习了如何在三大主要平台上进行操作——macOS、Linux 和 Windows。
在下一章节中,我们将学习如何通过云端安装 Pachyderm,并解释在生产环境中运行 Pachyderm 集群所需的软件要求。我们还将了解 Pachyderm Hub,即 软件即服务(SaaS)版本的 Pachyderm,适用于测试和生产环境。
进一步阅读
请参考以下链接,了解本章中涉及的主题:
-
官方 Homebrew 文档:
docs.brew.sh/ -
Kubectl 备忘单:
kubernetes.io/docs/reference/kubectl/cheatsheet/ -
Minikube 手册:
minikube.sigs.k8s.io/docs/handbook/ -
官方 Docker Desktop 文档:https://docs.docker.com/desktop/
-
生产环境中的 Kubernetes 最佳实践:
www.packtpub.com/product/kubernetes-in-production-best-practices/9781800202450 -
Kubernetes 和 Docker – 企业指南:
www.packtpub.com/product/kubernetes-and-docker-an-enterprise-guide/9781839213403 -
官方 Pachyderm pachctl 参考指南:
docs.pachyderm.com/latest/reference/pachctl/pachctl/
第五章:第五章:在云平台上安装 Pachyderm
在上一章中,你已经学习了在本地安装 Pachyderm 的过程,以便快速开始并在你的计算机上测试 Pachyderm。
生产环境用例需要额外的计算资源和可扩展性,可以通过云平台和流行云提供商提供的托管 Kubernetes 平台服务高效实现。Pachyderm 可以在 Kubernetes 集群上运行,无论是手动部署在云实例上,还是作为托管的 Kubernetes 服务部署。我们将讨论在云提供商上配置最流行和易于配置的方法。
本章将带你完成 Pachyderm 的云端安装,并解释运行 Pachyderm 集群所需的软件要求。本章将介绍在以下最流行的云平台上的安装:Amazon Elastic Kubernetes Service (EKS),Google Kubernetes Engine (GKE),以及 Microsoft Azure Kubernetes Service (AKS)。
在本章中,我们将涵盖以下主要主题:
-
安装所需工具
-
在 Amazon EKS 上部署 Pachyderm
-
在 GKE 上部署 Pachyderm
-
在 Microsoft AKS 上部署 Pachyderm
-
访问 Pachyderm 控制台
技术要求
如果你使用 macOS,请验证你使用的是最新版本的 macOS。如果你使用 Linux,必须是 CentOS、Fedora 或 Ubuntu 的 64 位版本。如果你使用 Windows,请从 Windows 子系统 Linux (WSL) 运行本节中描述的所有命令。你应该已经在前面的章节中安装了以下工具:
-
Homebrew(仅限 macOS)
-
Kubernetes
kubectl -
Helm
-
Pachyderm CLI –
pachctl -
WSL(仅限 Windows)
我们需要安装以下工具:
-
aws -
Amazon 身份和访问管理 (AWS IAM) Kubernetes 身份验证器
-
EKS 命令行工具 –
eksctl -
Google Cloud SDK –
gcloud -
Azure CLI –
az -
JSON 处理器 –
jq
我们将在本章中详细讨论这些工具的安装和配置。如果你已经知道如何操作,可以现在就开始设置它们。
安装所需工具
在本节中,我们将讨论安装我们在部署 Kubernetes 集群和在云平台上安装 Pachyderm 前需要的系统工具。
安装 AWS 命令行界面以管理 AWS
AWS 命令行界面 aws-cli 是执行 AWS 账户命令所必需的。有关更多信息,你可以参考 AWS 命令行界面的官方文档:docs.aws.amazon.com/cli/latest/userguide/。让我们在你的计算机上安装 aws-cli:
- 执行以下命令,在你的计算机上安装
aws-cli版本 2:
如果你正在使用 macOS:
$ curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg"
$ sudo installer -pkg AWSCLIV2.pkg -target
如果你使用的是 Linux(x86)或 Windows 上的 WSL:
$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
$ unzip awscliv2.zip
$ sudo ./aws/install
-
执行以下命令验证 AWS CLI 安装是否成功:
$ aws --version
上述命令的输出应如下所示:
aws-cli/2.4.7 Python/3.8.8 Linux/5.11.0-41-generic exe/x86_64.ubuntu.20 prompt/off
-
执行以下命令配置 AWS CLI,并输入您的
~/.aws/credentials,以便稍后运行命令时使用:$ aws configure
上述命令的输出应如下所示:
AWS Access Key ID [None]: YOURACCESSKEYHERE
AWS Secret Access Key [None]: YOURSECRETACCESSKEYHERE
Default region name [None]: us-east-1
Default output format [None]: json
-
如果要使用与凭证文件中配置的不同帐户,可以设置环境变量,直到当前 shell 会话结束时该变量将生效。根据需要,临时使用以下变量设置用户配置:
$ export AWS_ACCESS_KEY_ID=YOURACCESSKEY2HERE $ export AWS_SECRET_ACCESS_KEY=YOURSECRETACCESS2KEYHERE $ export AWS_DEFAULT_REGION=us-west-2
现在您已经在计算机上安装了 AWS 命令行接口,接下来让我们安装 Kubernetes 的 AWS IAM 认证器。
安装 Kubernetes 的 AWS IAM 认证器
Amazon EKS 利用 AWS IAM 为通过 EKS 创建的 Kubernetes 集群提供访问权限。为了让 kubectl 命令与 Amazon EKS IAM 角色一起工作,需要安装 Amazon IAM 认证器。让我们在您的计算机上安装 IAM 认证器:
- 执行以下命令安装
aws-iam-authenticator:
如果您使用的是 macOS:
$ brew install aws-iam-authenticator
如果您使用的是 Linux(x86)或 Windows 上的 WSL:
$ curl -o aws-iam-authenticator https://amazon-eks.s3.us-west-2.amazonaws.com/1.19.6/2021-01-05/bin/linux/amd64/aws-iam-authenticator
$ chmod +x ./aws-iam-authenticator
$ mkdir -p $HOME/bin && cp ./aws-iam-authenticator $HOME/bin/aws-iam-authenticator && export PATH=$PATH:$HOME/bin
$ echo 'export PATH=$PATH:$HOME/bin' >> ~/.bashrc
-
验证其版本并确保已安装
aws-iam-authenticator:$ aws-iam-authenticator version
上述命令的输出应如下所示。为了能够执行以下步骤,aws-iam-authenticator版本应为0.5.0或更高:
{"Version":"v0.5.0","Commit":"1cfe2a90f68381eacd7b6dcfa2 bf689e76eb8b4b"}
现在,您已经在计算机上安装了aws-iam-authenticator。
安装 eksctl 以管理 Amazon EKS
Amazon EKS 是 Amazon EC2 上的托管 Kubernetes 服务。要通过终端管理 Amazon EKS 并执行命令,需要使用 Amazon EKS 的官方 CLI——eksctl。有关更多信息,您可以参考 AWS eksctl 官方文档,网址为docs.aws.amazon.com/eks/latest/userguide/getting-started-eksctl.html。让我们在您的计算机上安装eksctl:
- 执行以下命令以在您的计算机上安装
eksctl:
如果您使用的是 macOS:
$ brew tap weaveworks/tap
$ brew install weaveworks/tap/eksctl
如果您使用的是 Linux(x86)或 Windows 上的 WSL:
$ curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
$ sudo mv /tmp/eksctl /usr/local/bin
-
验证其版本并确保已安装
eksctl:$ eksctl version
上述命令的输出应如下所示:
0.77.0
为了执行以下步骤,eksctl版本应为0.77.0或更高版本。现在您已经在计算机上安装了eksctl,以便管理 Amazon EKS。
安装 Google Cloud SDK 以管理 Google Cloud
Google Cloud SDK(gcloud)是执行 Google Cloud 帐户命令所需的工具。以下说明假设您已经拥有一个启用了计费的有效 GCP 帐户。如果您还没有帐户,请访问console.cloud.google.com并创建一个帐户。让我们在您的计算机上安装gcloud:
- 执行以下命令以在您的计算机上安装
gcloud:
如果您使用的是 macOS:
$ brew tap weaveworks/tap
$ brew install weaveworks/tap/eksctl
如果你正在使用 Linux(x86)或 Windows 上的 WSL:
$ curl https://sdk.cloud.google.com | bash
-
执行以下命令重新启动你的 shell:
$ exec -l $SHELL -
验证其版本并确保
gcloud已安装:$ gcloud version
前面的命令输出应如下所示。为了能够执行以下操作,Google Cloud SDK 版本应为 339.0.0 或更高版本:
Google Cloud SDK 367.0.0
bq 2.0.72
core 2021.12.10
gsutil 5.5
-
执行以下命令初始化 SDK,并按照指示操作:
$ gcloud init -
执行以下命令为未来的部署设置默认区域。在我们的示例中,计算区域设置为
us-central1-a:$ gcloud config set compute/zone us-central1-a
现在,你已经在计算机上安装了 gcloud 来管理 GKE。
安装 Azure CLI 以管理 Microsoft Azure
Azure CLI(az)是执行 Microsoft Azure 账户中命令所必需的。以下说明假设你已有一个启用计费的有效 Azure 账户。如果你还没有账户,请访问 portal.azure.com 创建一个账户。让我们在你的计算机上安装 Azure CLI:
- 执行以下命令在你的计算机上安装
gcloud:
如果你正在使用 macOS:
$ brew update && brew install azure-cli
$ brew install jq
如果你正在使用 Linux(x86)或 Windows 上的 WSL:
$ curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
$ sudo apt-get install jq
-
验证其版本并确保已安装 Azure CLI:
$ az version
前面的命令输出应如下所示。为了能够执行以下步骤,Azure CLI 版本应为2.0.1或更高版本:
{
"azure-cli": "2.31.0",
"azure-cli-core": "2.31.0",
"azure-cli-telemetry": "1.0.6",
"extensions": {}
}
-
执行以下命令初始化 Azure CLI,并按照指示操作:
$ az login -
执行以下命令创建一个具有唯一名称的资源组,并为未来的部署设置默认区域。在我们的示例中,计算区域设置为
centralus:$ az group create --name="pachyderm-group" --location=centralus
现在,你已经在计算机上安装了 Azure CLI 来管理 AKS。
在 Amazon EKS 上部署 Pachyderm
Kubernetes 是一个开源的容器编排平台,本身是一个庞大的主题。在本节中,我们从数据科学家的角度探讨容器化,仅专注于在市场上最常见的托管平台上运行我们的工作负载 Pachyderm。AWS 云平台上有多种方法和工具可以配置和管理生产级 Kubernetes 集群的生命周期,如 kOps、kubespray、k3s、Terraform 等。欲了解更多配置细节,请参考 Kubernetes 官方文档 kubernetes.io/docs/setup/production-environment/。让我们学习在 AWS 托管的 Kubernetes 服务 Amazon EKS 上启动和运行 Pachyderm 所需服务的最简单方法。
准备 Amazon EKS 集群以运行 Pachyderm
按照以下步骤使用eksctl来配置一个 Amazon EKS 集群。eksctl最初作为一个第三方开源工具开发,现在是通过 CLI 部署和管理 EKS 集群的官方工具。您需要安装 AWS CLI 和 AWS IAM Kubernetes 认证工具,并配置它们的凭证。如果您已经有一个集群,可以跳过这些步骤,直接跳到 在 Amazon EKS 上部署 Pachyderm 部分。此外,您可以参考 Amazon EKS 的官方文档:eksctl.io/introduction/:
-
执行以下命令,使用默认参数简单地部署 EKS 集群。此命令将生成一个包含两个
m5.large工作节点的集群,使用官方 AWS EKS 亚马逊机器镜像(AMI):$ eksctl create cluster
上述命令的输出应返回类似于以下内容的输出:
...
kubectl command should work with "/home/norton/.kube/config", try 'kubectl get nodes'
[✔] EKS cluster "exciting-badger-1620255089" in "us-east-1" region is ready
重要提示
要自定义 EKS 集群配置,可以将附加参数传递给eksctl,如下所示:
eksctl create cluster --name <name> --version <version> \
--nodegroup-name <name> --node-type <vm-flavor> \
--nodes <number-of-nodes> --nodes-min <min-number-nodes> \
--nodes-max <max-number-nodes> --node-ami auto
-
执行以下命令验证集群部署:
$ kubectl cluster-info && kubectl get nodes
上述命令的输出应如下所示:
Kubernetes control plane is running at https://ABCD.gr7.us-east-1.eks.amazonaws.com
CoreDNS is running at https://ABCD.gr7.us-east-1.eks.amazonaws.com/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
NAME STATUS ROLES AGE VERSION
ip-192-168-17-133.ec2.internal Ready <none> 21m v1.21.5-eks-bc4871b
ip-192-168-63-179.ec2.internal Ready <none> 21m v1.21.5-eks-bc4871b
现在,您的 Amazon EKS 集群已配置好,并准备好部署 Pachyderm。
创建 S3 对象存储桶
Pachyderm 使用符合 S3 标准的对象存储来存储数据。按照以下步骤创建一个 S3 对象存储桶:
-
生成将用于创建 S3 存储桶的变量,并将其传递给
pachctl,以便稍后存储 Pachyderm 数据。确保使用唯一的存储桶名称。在我们的示例中,我们将使用s3.pachyderm作为存储桶名称,容量为 200 GB,并位于与 EKS 集群相同的区域us-east-1:$ export S3_BUCKET_NAME=s3.pachyderm $ export EBS_STORAGE_SIZE=200 $ export AWS_REGION=us-east-1 -
为了让 Pachyderm 存储管道数据,需要一个专用的 S3 存储桶。执行以下命令,根据您的变量定义创建一个 S3 存储桶:
$ aws s3api create-bucket --bucket ${S3_BUCKET_NAME} \ --region ${AWS_REGION} -
执行以下命令确认存储桶已创建:
$ aws s3api list-buckets --query 'Buckets[].Name'
上述命令的输出应如下所示:
[
"s3.pachyderm",
]
现在我们已经创建了一个 S3 存储桶,可以准备在 Amazon EKS 上部署 Pachyderm。
部署集群
当你开始学习 Pachyderm 时,建议在一个小型本地集群中进行实验。我们在第四章中已介绍了 Pachyderm 的本地部署,本地安装 Pachyderm。在本章中,我们将重点介绍使用 IAM 角色在 Amazon EKS 集群上进行可扩展的生产级部署。
按照以下步骤在您的 Amazon EKS 集群上安装 Pachyderm:
- 分配给 EKS 集群的 AWS IAM 角色需要有权访问你在创建 S3 对象存储桶部分中创建的 S3 存储桶。如以下截图所示,登录到你的 AWS 管理控制台并进入 EKS 仪表板:

图 5.1 – 亚马逊 EKS 集群仪表板
- 点击集群。定位到集群中的 EC2 实例。找到 IAM 角色在实例描述页面。点击IAM 角色:

图 5.2 – 分配给 EC2 实例的 IAM 角色
-
用你的存储桶名称替换下面的
<s3-bucket>占位符。点击添加内联策略,创建一个类似如下代码的内联策略:{ "Statement": [ { "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:ListBucket", "s3:DeleteObject" ], "Resource": [ "arn:aws:s3:::<s3-bucket>", "arn:aws:s3:::*/*" ] } ] } -
切换到信任关系标签页,并点击编辑信任关系按钮。确认信任关系类似于下述内容,否则,进行更改并点击更新信任策略按钮来更新:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } -
现在,执行以下命令将 Pachyderm Helm Chart 仓库添加到你的本地仓库:
$ helm repo add pach https://helm.pachyderm.com -
执行以下命令从 Chart 仓库获取最新的 Chart 信息:
$ helm repo update -
为了快速部署,替换下方的 Amazon S3 存储桶名称、访问密钥 ID 和密钥,执行命令在没有控制台的情况下将 Pachyderm 的最新版本部署到你的集群:
$ helm install pachd pach/pachyderm \ --set deployTarget=AMAZON \ --set pachd.storage.amazon.bucket="AWS_S3_BUCKET" \ --set pachd.storage.amazon.id="AWS_ACCESS_KEY" \ --set pachd.storage.amazon.secret="AWS_SECRET" \ --set pachd.storage.amazon.region="us-east-1" --set pachd.externalService.enabled=true
如果你有企业密钥并希望通过 Pachyderm 控制台用户界面部署它,执行以下命令:
$ helm install pachd pach/pachyderm \
--set deployTarget=AMAZON \
--set pachd.storage.amazon.bucket="AWS_S3_BUCKET" \
--set pachd.storage.amazon.id="AWS_ACCESS_KEY" \
--set pachd.storage.amazon.secret="AWS_SECRET" \
--set pachd.storage.amazon.region="us-east-1" \
--set pachd.enterpriseLicenseKey=$(cat license.txt) \
--set console.enabled=true
一旦控制台成功部署,按照访问 Pachyderm 控制台部分的说明访问控制台。
命令返回以下输出:

图 5.3 – Pachyderm Helm Chart 在 Kubernetes 上部署
可选:自定义安装参数
你还可以下载并自定义 Helm Chart 仓库中的values.yaml文件,github.com/pachyderm/pachyderm/tree/master/etc/helm/pachyderm,进一步优化运行 Pachyderm 所需的组件。
执行以下命令创建values.yaml文件的本地副本:
$ wget https://raw.githubusercontent.com/pachyderm/pachyderm/master/etc/helm/pachyderm/values.yaml
一旦自定义完成,你可以使用相同的 YAML 文件,通过执行以下命令来安装你的 Helm Chart:
$ helm install pachyderm -f values.yaml pach/pachyderm
-
Kubernetes 部署是一个控制器,根据你在
manifest文件中定义的要求,推出一个 Pod 的副本集。副本集是一组相同服务的实例。执行以下命令验证在安装过程中创建的部署状态:$ kubectl get deployments
上述命令的输出应如下所示:

图 5.4 – Pachyderm 部署对象列表
-
执行以下命令以验证安装是否成功,并查看作为部署一部分创建的 Pods:
$ kubectl get pods
上述命令的输出应如下所示:

图 5.5 – Pachyderm Pods 列表
-
执行以下命令以验证作为部署一部分创建的持久卷:
$ kubectl get pv
上述命令的输出应如下所示:
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-cab1f435-02fb-42df-85d9-d49f6151b281 200Gi RWO Delete Bound default/etcd-storage-etcd-0 etcd-storage-class 81m
重要提示
当使用--dynamic-etcd-nodes标志部署 Pachyderm 时,它会创建一个etcd部署来管理管理元数据。etcd Pods 使用默认的 AWS StorageClass,gp2来配置块存储。如果在部署过程中需要使用不同的 StorageClass,则需要向集群部署 Amazon EBS CSI 驱动程序,并在 Helm Chart 部署过程中将etcd.storageclass参数更新为gp3。
-
执行以下命令以验证 Pachyderm 的成功安装:
$ pachctl version
上述命令的输出应如下所示:
COMPONENT VERSION
pachctl 2.0.0
pachd 2.0.0
现在我们已经在 AWS EKS 集群上安装了 Pachyderm,准备好创建我们的第一个管道了。
在 Amazon EKS 上删除 Pachyderm 部署
如果你需要删除 Pachyderm 部署或重新开始,可以清除你的环境并按照准备 EKS 集群以运行 Pachyderm的说明从头开始。让我们执行以下步骤来删除现有的 Pachyderm 部署:
-
如果你使用了不同的名称来命名你的 Helm 实例,请执行以下命令以查找通过 Helm Chart 部署的 Pachyderm 实例名称:
$ helm ls | grep pachyderm
上述命令的输出应如下所示:
pachd default 1 2021-12-27 20:20:33.168535538 -0800 PST deployed pachyderm-2.0.0 2.0.0
-
使用你的 Pachyderm 实例名称执行以下命令,以从集群中移除 Pachyderm 组件:
$ helm uninstall pachd -
执行以下命令以获取已部署的 EKS 集群列表,并识别你的集群名称:
$ eksctl get cluster
上述命令的输出应如下所示:
2021-05-05 21:53:56 [ℹ] eksctl version 0.47.0
2021-05-05 21:53:56 [ℹ] using region us-east-1
NAME REGION EKSCTL CREATED
exciting-badger-1620255089 us-east-1 True
-
如果你想完全移除集群,请从前面的输出中复制集群名称,并在替换名称后执行以下命令以删除 Amazon EKS 集群。请注意,集群上的所有其他工作负载也会被销毁:
$ eksctl delete cluster --name <name>
上述命令的输出应类似于以下内容:
...
2021-05-05 22:00:54 [ℹ] will delete stack "eksctl-exciting-badger-1620255089-cluster"
2021-05-05 22:00:54 [✔] all cluster resources were deleted
现在你已经完全从 AWS 账户中移除了 Pachyderm 和 EKS 集群。
在 GKE 上部署 Pachyderm
如果你使用 Google Cloud,可以通过kOps、kubespray、Terraform 等方式部署托管的 Kubernetes 服务。有关其他配置详情,你可以参考 Kubernetes 的官方文档:kubernetes.io/docs/setup/production-environment/。让我们学习如何在 Google Cloud 的托管 Kubernetes 服务 GKE 上以最简单的方式启动 Pachyderm 所需的服务。
准备 GKE 集群以运行 Pachyderm
按照以下步骤使用 Google Cloud SDK 配置 GKE 集群。你需要安装 Google Cloud SDK 并配置其凭据。如果你已经有了集群,可以跳过这些说明并跳到 部署集群部分。另外,你可以参考 Google Cloud SDK 官方文档 cloud.google.com/sdk/docs/install:
-
执行以下命令以使用默认参数部署 GKE 集群。此命令将在默认计算区域内使用容器优化操作系统(COS)和 Docker 生成一个包含三节点的集群,推荐使用
n2-standard-4实例类型:$ gcloud container clusters create pachyderm-cluster \ --scopes compute-rw,storage-rw,service-management,service-control,logging-write,monitoring \ --machine-type n2-standard-4
前面的命令输出应类似于以下内容:
...
kubeconfig entry generated for pachyderm-cluster.
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS
pachyderm-cluster us-central1-a 1.18.16-gke.2100 35.238.200.52 n2-standard-4 1.18.16-gke.2100 1 RUNNING
重要提示
若要简单地自定义 GKE 集群参数,可以使用 GCP 控制台和 Kubernetes Engine 创建向导。在向导中配置参数后,单击向导中的命令行按钮,将配置转换为 CLI 命令并使用 gcloud 命令。
-
执行以下命令以验证集群的部署:
$ kubectl cluster-info && kubectl get nodes
前面的命令输出应如下所示:
Kubernetes control plane is running at https://<IP_ADDRESS>
GLBCDefaultBackend is running at https://<IP_ADDRESS>/api/v1/namespaces/kube-system/services/default-http-backend:http/proxy
KubeDNS is running at https://<IP_ADDRESS>/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
Metrics-server is running at https://<IP_ADDRESS>/api/v1/namespaces/kube-system/services/https:metrics-server:/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
NAME STATUS ROLES AGE VERSION
gke-pachyderm-cluster-default-pool-26cf3a77-1vr1 Ready <none> 12 v1.18.16-gke.2100
gke-pachyderm-cluster-default-pool-26cf3a77-5sgs Ready <none> 12m v1.18.16-gke.2100
gke-pachyderm-cluster-default-pool-26cf3a77-lkr4 Ready <none> 12m v1.18.16-gke.2100
现在,你的 GKE 集群已配置完毕,准备部署 Pachyderm。
创建 Google Cloud 对象存储桶
Pachyderm 使用对象存储来存储数据。按照以下步骤创建 Google Cloud 对象存储桶:
-
生成用于创建
pachctl的变量,这些变量将在稍后存储你的 Pachyderm 数据。确保使用唯一的存储桶名称。在我们的示例中,我们将使用pachyderm-bucket作为存储桶名称,容量为 200 GB,并位于与 GKE 集群相同的区域us-central1:$ export GCS_BUCKET_NAME=pachyderm-bucket $ export GKE_STORAGE_SIZE=200 -
为了让 Pachyderm 存储管道数据,必须创建一个专用的 GCS 存储桶。执行以下命令以使用你的变量定义的参数创建一个 GCS 存储桶:
$ gsutil mb gs://${GCS_BUCKET_NAME} -
执行以下命令以确认存储桶已创建:
$ gsutil ls
前面的命令输出应如下所示:
gs://pachyderm-bucket/
现在,你已经创建了一个 GCS 存储桶来存储 Pachyderm 数据。我们已经准备好在 GKE 上部署 Pachyderm。
部署集群
当你开始学习 Pachyderm 时,建议在小型本地集群中运行实验。我们之前已经在 第四章中介绍了 Pachyderm 的本地部署,在本地安装 Pachyderm。在本章中,我们将重点介绍使用 GKE 集群上的 IAM 角色部署可扩展的生产级 Pachyderm。
按照以下步骤在 GKE 集群上安装 Pachyderm:
-
如果你尚未创建服务账户,执行以下命令来创建一个服务账户:
$ gcloud iam service-accounts create my-service-account --display-name=my-account -
将以下
pachyderm-book替换为你的项目名称,并为你的服务账户添加一个绑定的存储管理员角色:$ gcloud projects add-iam-policy-binding \ pachyderm-book –role roles/owner --member \ serviceAccount:my-service-account@pachyderm-book.iam.gserviceaccount.com -
现在,执行以下命令将 Pachyderm Helm Chart 仓库添加到本地仓库:
$ helm repo add pach https://helm.pachyderm.com -
执行以下命令从 Chart 仓库获取最新的 Chart 信息:
$ helm repo update -
对于快速部署,替换 Google Cloud 存储桶名称和 Google Cloud 凭据,并执行以下命令,在不使用控制台的情况下,将 Pachyderm 的最新版本部署到你的集群中:
$ helm install pachd pach/pachyderm \ --set deployTarget=GOOGLE \ --set pachd.storage.google.bucket="GOOGLE_BUCKET" \ --set pachd.storage.google.cred="GOOGLE_CRED" \ --set pachd.externalService.enabled=true
如果你有企业密钥并希望通过 Pachyderm 的控制台用户界面部署,请执行以下命令:
$ helm install pachd pach/pachyderm \
--set deployTarget=GOOGLE \
--set pachd.storage.google.bucket="GOOGLE_BUCKET" \
--set pachd.storage.google.cred="GOOGLE_CRED" \
--set pachd.enterpriseLicenseKey=$(cat license.txt) \
--set console.enabled=true
一旦控制台成功部署,按照访问 Pachyderm 控制台部分的说明访问控制台。
-
Kubernetes 部署是一个控制器,它根据清单文件中定义的要求推出 Pods 的副本集。执行以下命令验证安装过程中创建的部署状态:
$ kubectl get deployments
上述命令的输出应如下所示:
NAME READY UP-TO-DATE AVAILABLE AGE
dash 1/1 1 1 44s
pachd 1/1 1 1 45s
-
执行以下命令验证安装是否成功,并查看作为部署的一部分创建的 Pods:
$ kubectl get Pods
上述命令的输出应如下所示:
NAME READY STATUS RESTARTS AGE
dash-cf6f47d7d-xpvvp 2/2 Running 0 104s
etcd-0 1/1 Running 0 104s
pachd-6c99f6fb7-dnjhn 1/1 Running 0 104s
-
执行以下命令验证作为部署一部分创建的持久卷:
$ kubectl get pv
上述命令的输出应如下所示:
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-c4eac147-8571-4ccb-8cd0-7c1cb68a627d 200Gi RWO Delete Bound default/etcd-storage-etcd-0 etcd-storage-class 3m4s
-
执行以下命令验证 Pachyderm 是否成功安装:
$ pachctl version
上述命令的输出应如下所示:
COMPONENT VERSION
pachctl 2.0.0
pachd 2.0.0
现在我们已经在你的 GKE 集群上安装了 Pachyderm,你可以开始创建你的第一个流水线。
在 GKE 上删除 Pachyderm 部署
如果你需要删除现有的部署并重新开始,可以通过使用准备 GKE 集群运行 Pachyderm的说明清除你的环境并重新开始。接下来让我们执行以下步骤来删除现有的 Pachyderm 部署:
-
如果你使用了不同的 Helm 实例名称,执行以下命令查找通过 Helm Chart 部署的 Pachyderm 实例名称:
$ helm ls | grep pachyderm
上述命令的输出应如下所示:
pachd default 1 2021-12-27 20:20:33.168535538 -0800 PST deployed pachyderm-2.0.0 2.0.0
-
使用你的 Pachyderm 实例名称执行以下命令,从集群中删除 Pachyderm 组件:
$ helm uninstall pachd -
执行以下命令以检索已部署的 GKE 集群列表,并识别你的集群名称:
$ gcloud container clusters list
上述命令的输出应如下所示:
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS
pachyderm-cluster us-central1-a 1.18.16-gke.2100 35.238.200.52 n2-standard-2 1.18.16-gke.2100 3 RUNNING
-
如果你希望完全删除集群,请从之前的输出中复制集群名称,并在替换名称后执行以下命令来删除 GKE 集群。请注意,集群上的所有其他工作负载也会被销毁:
$ gcloud container clusters delete <name>
上述命令的输出应类似于以下内容:
...
Deleting cluster pachyderm-cluster...done.
Deleted [https://container.googleapis.com/v1/projects/pachydermbook/zones/us-central1-a/clusters/pachyderm-cluster].
现在你已经完全从 GCP 账户中移除了 Pachyderm 和你的 Kubernetes 集群。
在 Microsoft AKS 上部署 Pachyderm
如果你使用的是 Microsoft Azure,可以通过自动化和命令行工具在 Azure 平台上部署托管的 Kubernetes 服务,借助 kOps、kubespray、Terraform 等工具。有关更多配置细节,请参考 Kubernetes 的官方文档 kubernetes.io/docs/setup/production-environment/。让我们了解在 AKS 上启动 Pachyderm 所需服务的最简单方法。
准备一个 AKS 集群以运行 Pachyderm
按照以下步骤使用 Azure CLI 配置 AKS 集群。你需要安装 Azure CLI 并配置其凭据。如果你已有集群,可以跳过这些说明,直接跳到 在 Microsoft AKS 上部署 Pachyderm 部分。此外,你还可以参考 Azure CLI 的官方文档 docs.microsoft.com/en-us/cli/azure/:
-
在之前指定的
resource-group中执行以下命令,以使用默认参数部署 AKS 集群。此命令将在默认计算区中生成一个三节点集群,实例类型为推荐的Standard_DS4_v2:$ az aks create --resource-group pachyderm-group --name pachyderm-cluster --generate-ssh-keys --node-vm-size Standard_DS4_v2
前面的命令输出应与以下内容类似:
...
"privateFqdn": null,
"provisioningState": "Succeeded",
"resourceGroup": "pachyderm-group",
"servicePrincipalProfile": {
"clientId": "msi",
"secret": null
},...
重要提示
如果你不记得资源组名称,可以使用 az group list 命令列出之前创建的资源组。
-
执行以下命令以连接到你的集群:
$ az aks get-credentials --resource-group pachyderm-group --name pachyderm-cluster -
执行以下命令以验证集群部署:
$ kubectl get nodes
前面的命令输出应如下所示:
NAME STATUS ROLES AGE VERSION
aks-nodepool1-34139531-vmss000000 Ready agent 5m57s v1.19.9
aks-nodepool1-34139531-vmss000001 Ready agent 5m58s v1.19.9
aks-nodepool1-34139531-vmss000002 Ready agent 5m58s v1.19.9
现在你的 AKS 集群已配置完毕,可以部署 Pachyderm 了。
创建 Azure 存储容器
Pachyderm 使用 blob 存储来存储数据,使用块存储来存储元数据。建议使用 SSD 而非标准的基于 HDD 的较慢存储选项。
按照以下步骤创建一个 Premium LRS 块 blob 存储容器:
-
生成将用于创建 Azure 块 blob 存储的变量,并传递给
pachctl以便稍后存储 Pachyderm 数据。确保使用唯一的存储帐户和容器名称。在我们的示例中,我们将使用pachydermstorageaccount作为STORAGE_ACCOUNT,pachydermblobcontainer作为CONTAINER_NAME,并将其定位在centralus区域:$ export RESOURCE_GROUP=pachyderm-group $ export STORAGE_ACCOUNT=pachydermstorageaccount $ export CONTAINER_NAME=pachydermblobcontainer $ export AZURE_STORAGE_SIZE=200 -
执行以下命令,将存储帐户与由变量定义的参数传递给 Azure 存储:
$ az storage account create \ --resource-group="${RESOURCE_GROUP}" \ --location="centralus" \ --sku=Premium_LRS \ --name="${STORAGE_ACCOUNT}" \ --kind=BlockBlobStorage -
执行以下命令确认存储桶已创建:
$ az storage account list
前面的命令输出应如下所示:
...
"web": "https://pachydermstorageaccount.z19.web.core.windows.net/"
},
"primaryLocation": "centralus",
"privateEndpointConnections": [],
"provisioningState": "Succeeded",
"resourceGroup": "pachyderm-group",
...
-
部署 Pachyderm 时需要一个存储帐户密钥。执行以下命令以将存储密钥存储在变量中:
$ STORAGE_KEY="$(az storage account keys list \ --account-name="${STORAGE_ACCOUNT}" \ --resource-group="${RESOURCE_GROUP}" \ --output=json \ | jq '.[0].value' -r )" -
执行以下命令,在你的存储帐户中创建一个数据存储容器:
$ az storage container create --name ${CONTAINER_NAME} \ --account-name ${STORAGE_ACCOUNT} \ --account-key "${STORAGE_KEY}"
前面的命令输出应如下所示:
{
"created": true
}
现在,你在 Azure 存储帐户中已创建了一个 Azure 数据存储容器,用于存储 Pachyderm 数据。
部署集群
当您开始学习 Pachyderm 时,建议在一个小型本地集群中进行实验。我们之前在 第四章 中介绍了 Pachyderm 的本地部署,本地安装 Pachyderm。在本章中,我们将重点介绍在 AKS 集群上进行可扩展的生产级部署。
按照以下步骤在您的 AKS 集群上安装 Pachyderm:
-
如果尚未连接到 Kubernetes 集群,请执行以下命令连接到您的集群:
$ az aks get-credentials --resource-group pachyderm-group --name pachyderm-cluster -
若要快速部署,替换 Azure 存储容器名称、Azure 存储帐户名称和 AKS 帐户密钥,然后执行以下命令,在您的集群上部署最新版本的 Pachyderm,而不使用控制台:
$ helm install pachd pach/pachyderm \ --set deployTarget=MICROSOFT \ --set pachd.storage.microsoft.container="CONTAINER_NAME" \ --set pachd.storage.microsoft.id="AZURE_ID" \ --set pachd.storage.microsoft.secret="AZURE_SECRET" \ --set pachd.externalService.enabled=true
如果您有企业密钥,并且希望通过 Pachyderm 的控制台用户界面进行部署,请执行以下命令:
$ helm install pachd pach/pachyderm \
--set deployTarget=MICROSOFT \
--set pachd.storage.microsoft.container="CONTAINER_NAME" \
--set pachd.storage.microsoft.id="AZURE_ID" \
--set pachd.storage.microsoft.secret="AZURE_SECRET" \
--set pachd.enterpriseLicenseKey=$(cat license.txt) \
--set console.enabled=true
一旦控制台成功部署,按照 访问 Pachyderm 控制台 部分的指示访问控制台。
-
Kubernetes 部署是一个控制器,它基于清单文件中定义的要求,推出一个 Pod 的副本集。执行以下命令以验证安装过程中创建的部署状态:
$ kubectl get deployments
前面命令的输出应如下所示:
NAME READY UP-TO-DATE AVAILABLE AGE
dash 1/1 1 1 39s
pachd 1/1 1 1 39s
-
执行以下命令以验证成功安装并查看作为部署的一部分创建的 Pods:
$ kubectl get pods
前面命令的输出应如下所示:
NAME READY STATUS RESTARTS AGE
dash-866fd997-z79jj 2/2 Running 0 54s
etcd-0 1/1 Running 0 54s
pachd-8588c44f56-skmkl 1/1 Running 0 54 s
-
执行以下命令以验证作为部署的一部分创建的持久卷:
$ kubectl get pv
前面命令的输出应如下所示:
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-9985a602-789d-40f3-9249-7445a9c15bc3 200Gi RWO Delete Bound default/etcd-storage-etcd-0 default 89s
重要说明
当使用 --dynamic-etcd-nodes 标志部署 Pachyderm 时,它会创建一个 etcd 部署来管理管理元数据。在 Azure 中,etcd Pods 使用 default StorageClass 提供的块存储。这种存储类使用 azure-disk 提供程序和 StandardSSD_LRS 卷。如果在部署过程中想使用不同的 StorageClass,您可以自定义 values.yaml 文件,并在部署之前更新 etcd.storageClass 参数。
-
执行以下命令以验证 Pachyderm 是否已成功安装:
$ pachctl version
前面命令的输出应如下所示:
COMPONENT VERSION
pachctl 2.0.0
pachd 2.0.0
现在,您已在 AKS 集群上安装了 Pachyderm,准备创建您的第一个管道。
在 AKS 上删除 Pachyderm 部署
如果需要删除部署或重新开始,您可以使用 准备 AKS 集群以运行 Pachyderm 指令来清除环境并重新开始。
让我们执行以下步骤以删除现有的 Pachyderm 部署:
-
如果您为 Helm 实例使用了不同的名称,请执行以下命令查找使用 Helm Chart 部署的 Pachyderm 实例名称:
$ helm ls | grep pachyderm
前面命令的输出应如下所示:
pachd default 1 2021-12-27 20:20:33.168535538 -0800 PST deployed pachyderm-2.0.0 2.0.0
-
使用您的 Pachyderm 实例名称执行以下命令,以从集群中删除 Pachyderm 组件:
$ helm uninstall pachd -
执行以下命令以检索已部署的所有 AKS 集群列表,并识别您的集群名称:
$ az aks list
上述命令的输出应如下所示:
...
"location": "centralus",
"maxAgentPools": 100,
"name": "pachyderm-cluster",
"networkProfile": {
…
-
如果您想完全删除集群,请从上述输出中复制您的集群名称,并在替换名称后执行以下命令以删除 AKS 集群。请注意,此集群上的所有其他工作负载也将被销毁:
$ az aks delete --name <name> --resource-group pachyderm-group
上述命令的输出应与以下内容类似:
...
Deleting cluster pachyderm-cluster...done.
Deleted [https://container.googleapis.com/v1/projects/pachydermbook/zones/us-central1-a/clusters/pachyderm-cluster].
现在,您已从 AKS 帐户中完全删除了 Pachyderm 和您的 Kubernetes 集群。
访问 Pachyderm 控制台
Pachyderm 企业版提供了一个图形用户界面,您可以在其中查看管道和代码库。使用端口转发访问 Pachyderm 控制台已在第四章,在本地安装 Pachyderm中进行了介绍。
此外,对于云部署,您可以部署 Kubernetes Ingress 来安全访问 Pachyderm 控制台。有关更多信息,请参阅官方 Pachyderm 文档。
概述
在本章中,我们了解了在主要云提供商的托管 Kubernetes 服务上运行 Pachyderm 所需的软件先决条件,包括 AWS、Google Cloud 和 Microsoft Azure。
我们获取了有关云提供商命令行工具的基本知识,并学习了如何在本地机器上安装和操作这些工具,以提供生产级别的 Kubernetes 集群。
我们创建了一个对象存储桶,并使用最常见的配置选项部署了高可用性多节点托管 Kubernetes 集群。最后,我们部署了一个 Pachyderm 实例。
在下一章中,我们将详细了解如何创建您的第一个管道。您将学习一个简单的数据科学示例和管道创建工作流程。
进一步阅读
您可以参考本章涵盖的主题的以下链接获取更多信息:
-
使用 AWS CLI 官方文档:
docs.aws.amazon.com/cli/latest/userguide/cli-chap-using.html -
开始使用 Google Cloud SDK 官方文档:
cloud.google.com/sdk/docs/quickstart -
使用 Azure CLI 官方文档:
docs.microsoft.com/en-us/cli/azure/ -
eksctl 文档:
eksctl.io/introduction/ -
eksctl 高级集群部署示例:
github.com/weaveworks/eksctl/tree/main/examples -
kOps 文档:
kubernetes.io/docs/setup/production-environment/tools/kops/ -
Kubespray 文档:
kubernetes.io/docs/setup/production-environment/tools/kubespray/ -
Kubernetes 生产环境最佳实践:
www.packtpub.com/product/kubernetes-in-production-best-practices/9781800202450 -
掌握 Kubernetes – 第三版:
www.packtpub.com/product/mastering-kubernetes-third-edition/9781839211256
第六章:第六章:创建你的第一个管道
在第三章中,我们学习了 Pachyderm 管道规范以及你可以在其中配置的参数。管道规范是管道中最关键的配置部分,与代码一起使用。在本章中,我们将学习如何创建一个执行图像处理的 Pachyderm 管道。我们将详细介绍这一过程的所有步骤,包括创建 Pachyderm 仓库、创建管道、查看计算结果,并在原有管道中添加一个额外步骤。
本章将涵盖以下主题:
-
管道概述
-
创建仓库
-
创建管道规范
-
查看管道结果
-
添加另一个管道步骤
技术要求
本章要求你具备以下组件,并确保它们已安装和配置。
对于本地 macOS 安装,你需要以下内容:
-
macOS Mojave、Catalina、Big Sur 或更高版本
-
Docker Desktop for Mac 10.14
-
minikubev1.19.0 或更高版本 -
pachctl2.0.x 或更高版本 -
Pachyderm 2.0.x 或更高版本
对于本地 Windows 安装,你需要以下内容:
-
Windows Pro 64 位 v10 或更高版本
-
Windows Subsystem for Linux(WSL)2 或更高版本
-
Microsoft Powershell v6.2.1 或更高版本
-
Hyper-V
-
minikubev1.19.0 或更高版本 -
kubectlv1.18 或更高版本 -
pachctl2.0.x 或更高版本 -
Pachyderm 2.0.x 或更高版本
对于Amazon Elastic Kubernetes Service(Amazon EKS)安装,你需要以下内容:
-
kubectlv.18 或更高版本 -
eksctl -
aws-iam-authenticator -
pachctl2.0.x 或更高版本 -
Pachyderm 2.0.x 或更高版本
对于 Microsoft Azure 云安装,你需要以下内容:
-
kubectlv.18 或更高版本 -
Azure CLI
-
pachctl2.0.x 或更高版本 -
Pachyderm 2.0.x 或更高版本
-
jq1.5 或更高版本
对于Google Kubernetes Engine(GKE)云安装,你需要以下内容:
-
Google Cloud SDK v124.0.0 或更高版本
-
kubectlv.18 或更高版本 -
pachctl2.0.x 或更高版本 -
Pachyderm 2.0.x 或更高版本
你不需要任何特殊硬件来运行本章中的管道。如果你在本地运行 Pachyderm 集群,任何现代笔记本电脑都应支持本章中的所有操作。如果你在云平台上运行 Pachyderm,你需要一个持久卷(PV)。更多细节请参见第五章,在云平台上安装 Pachyderm。
本章中描述的所有脚本和数据可以在github.com/PacktPublishing/Reproducible-Data-Science-with-Pachyderm/tree/main/Chapter06-Creating-Your-First-Pipeline获取。
现在我们已经回顾了本章的技术要求,接下来让我们更深入地了解我们的管道。
管道概述
在第四章《本地安装 Pachyderm》和第五章《在云平台上安装 Pachyderm》中,我们学习了如何在本地或云平台上部署 Pachyderm。到现在为止,你应该已经在自己的电脑或云平台上运行了某个版本的 Pachyderm。现在,让我们创建我们的第一个管道。
Pachyderm 管道是一种技术,它处理来自 Pachyderm 输入仓库或多个输入仓库的数据,并将其上传到 Pachyderm 输出仓库。每次新的数据上传到输入仓库时,管道会自动处理这些数据。每次新的数据进入仓库时,它会被记录为一个提交哈希,可以稍后访问、重新运行或分析。因此,管道是 Pachyderm 生态系统中的一个重要组件,确保数据科学工作负载的可复现性。
为了帮助你快速入门,我们准备了一个简单的图像处理示例,它将在图像上绘制轮廓。轮廓是表示物体形状的外框。这是一项常用于图像处理管道的有用技术。
图像处理是一项广泛使用的技术,它可以增强图像质量、将图像转换为另一张图像、提取图像的各种信息等。通过机器学习,你可以建立管道来确定图像中的物体、生成图像的直方图等。
有许多开源库可用于高级图像处理,其中最著名的是OpenCV和scikit-image。这两个库广泛应用于机器学习专家的各种图像处理任务。
在这个示例中,我们将使用 scikit-image。scikit-image 或skimage是一个开源图像处理库,允许你运行各种图像处理算法来分析和转换图像。scikit-image 是专门为 Python 编程语言设计的。
在这个示例中,我们将使用 scikit-image 和其他几个开源组件,包括以下内容:
-
NumPy:一个开源的 Python 库,帮助你处理数组。当你需要分析或分割图像时,图像必须先转换为数组才能进行处理。
-
Matplotlib:一个扩展 NumPy 的库,帮助你绘制图像并创建数据可视化。
我们将创建一个管道,使用来自photos仓库的数据,运行一个contour.py脚本来处理photos仓库中的图像,并将结果上传到contour输出仓库。
以下图表解释了我们的管道:

图 6.1 – 轮廓管道
以下代码解释了contour.py脚本:
import numpy as np
import matplotlib.pyplot as plt
import os
from skimage.io import imread, imsave
from skimage import measure
import logging
logging.basicConfig(level=logging.INFO)
def create_contours(photo):
image = imread(photo, as_gray=True)
t = os.path.split(photo)[1]
c = measure.find_contours(image, 0.9)
fig, ax = plt.subplots()
ax.imshow(image, vmin=-1, vmax=1, cmap='gray')
for contour in c:
ax.plot(contour[:, 1], contour[:, 0], linewidth=2)
ax.axis('image')
ax.set_xticks([])
ax.set_yticks([])
plt.savefig(os.path.join("/pfs/out", os.path.splitext(t)[0]+'.png'))
for dirpath, dirnames, filenames in os.walk("/pfs/photos"):
for f in filenames:
create_contours(os.path.join(dirpath, f))
上面的脚本包含一个名为create_contours的函数。该函数执行以下操作:
-
首先,它从
pfs/photos仓库中读取图像文件,并将其转换为灰度图像。这是因为需要将彩色图像(RGB)转换为二维的 NumPy 数组。 -
然后,它使用
measure.find_contoursAPI 方法,这个方法来自skimage.measure.find_contours模块,用于在值为 0.9 的位置找到我们将图像转换成的二维数组的轮廓。这个值代表了明暗之间的位置。通常,最好使用一个中间值,但在这个例子中,0.9 得到了最佳结果。 -
然后,它定义了子图以可视化我们的图像,并将其保存在
pfs/out目录中,实际上,这将是pfs/out/contour输出仓库。 -
脚本的最后一部分告诉程序将
create_contours函数应用于pfs/photos仓库中的所有文件。
这个脚本内置在一个 Docker 镜像中,我们将使用它来运行我们的管道。这个 Docker 镜像托管在 Docker Hub 上。
我们将使用来自 freepik.com 的以下图像进行处理。第一张图像是棕色花瓶的图像:

图 6.2 – 棕色花瓶
第二张图像是手的图像:

图 6.3 – 手
最后,第三张图像是风景的图像:

图 6.4 – 风景
如你所见,这些是一些简单的图像,找出轮廓应该很容易。你可以尝试将这个管道应用于更复杂的图像,看看你能得到什么结果。一般来说,图像中元素之间的对比度越大,算法能找到的轮廓就越精确。
现在我们已经理解了正在处理的示例,让我们继续创建一个仓库吧。
创建一个仓库
创建管道的第一步是创建一个 Pachyderm 仓库并将一些数据放入其中。正如你可能还记得的,第二章《Pachyderm 基础》,Pachyderm 仓库是 Pachyderm 集群中的一个位置,用于存储数据。我们将创建一个输入仓库,管道将在第一次运行时自动创建一个输出仓库。
要创建一个输入仓库,请执行以下步骤:
-
登录到你的终端。
-
验证 Pachyderm 是否已启动并运行:
% pachctl version
你应该看到类似以下的输出:
COMPONENT VERSION
pachctl 2.0.0
pachd 2.0.0
pachd组件必须列出一个版本。
-
创建一个名为
photos的 Pachyderm 输入仓库:% pachctl create repo photos
不会返回任何输出。
-
验证
photos仓库是否已经创建:% pachctl list repo
你应该看到以下输出:
NAME CREATED SIZE (MASTER) ACCESS LEVEL
photos 11 seconds ago ≤ 0B [repoOwner]
在这里,你可以看到photos仓库已经创建,并且是空的。尽管主分支的大小被计算在内,但此时该仓库中没有分支。Pachyderm 会在你放入文件时自动创建指定的分支。
-
将一些图片放入
photos仓库中。我们需要将文件放入photos仓库的根目录中。为此,您需要使用-r(递归)标志,并指定包含文件的计算机目录路径。例如,如果您将文件下载到计算机上的数据文件夹中,则需要运行以下命令:% pachctl put file -r photos@master:/ -f data
以下是一些示例输出:
data/brown_vase.png 25.82 KB / 25.82 KB [=====] 0s 0.00 b/s
data/hand.png 33.21 KB / 33.21 KB [======] 0s 0.00 b/s
data/landscape.png 54.01 KB / 54.01 KB [=========] 0s
Pachyderm 会自动创建指定的分支。在此示例中,Pachyderm 会创建master分支。您可以随意命名分支,但为了简便起见,我们称之为master。本节中的所有命令都假设使用master分支。
-
验证文件是否已添加到仓库:
% pachctl list file photos@master
以下是一些示例输出:
NAME TYPE SIZE
/brown_vase.png file 25.21KiB
/hand.png file 32.43KiB
/landscape.png file 52.74KiB
-
另外,您可以通过对每个图像运行
pachctl put file命令,将每个文件逐一放入。例如,要放置landscape.jpg文件,请将计算机上的目录更改为data并使用以下命令:% pachctl put file photos@master -f landscape.jpg
以下是一些示例输出:
data/landscape.jpg 54.01KB / 54.01 KB [=] 0s 0.00 b/s/
对所有图像文件重复此命令。
重要提示
确保输出中的TYPE参数显示为file而不是dir。Pachyderm 不区分目录和文件,您需要使用-f将文件放入目录或仓库根目录。如果您的任何文件列出为dir,则需要通过运行pachctl delete file photos@master:<path>删除它们并重新开始。如果您将文件放在目录中,管道将无法按预期工作。
现在我们已经创建了一个仓库,让我们创建我们的管道规范。
创建管道规范
在创建仓库部分中,我们创建了一个名为photos的仓库并放入了一些测试文件。此示例的管道规范必须引用以下元素:
-
一个包含待处理数据的输入仓库
-
需要在您的数据上运行的计算机程序或脚本
-
指定数据粒度的通配符模式
-
包含您的代码的具有内建依赖项的 Docker 镜像
我们已经为您创建了一个管道规范,您可以用它来创建管道。以下是管道规范文件中的内容,格式为YAML Ain't Markup Language(YAML):
---
pipeline:
name: contour
description: A pipeline that identifies contours on an image.
transform:
cmd:
- python3
- "/contour.py"
image: svekars/contour-histogram:1.0
input:
pfs:
repo: photos
glob: "/"
让我们更详细地查看管道规范。以下是管道中的参数:

图 6.5 – Contour 管道参数
此管道规范不包括任何优化或额外参数。它是一个最小管道,将执行我们示例所需的计算。
要创建管道,请执行以下步骤:
-
登录到您的终端。
-
通过运行以下命令创建
contour管道:% pachctl create pipeline -f contour.yaml
不会返回任何输出。
-
验证管道是否已创建:
% pachctl list pipeline
以下是系统输出:
NAME VERSION INPUT CREATED STATE / LAST JOB DESC
contour 1 photos:/* 5 seconds ago running / - A pipeline that identifies contours on an image.
一旦你创建管道,它将把状态设置为 running 并尝试处理输入仓库中的数据。你可能还会看到 LAST JOB 的状态为 starting 或 running。
重要提示
在前述输出中的另一个重要内容是管道版本。我们的管道版本是 1。如果你更改了管道 YAML 文件中的内容并进行了更新,版本号会更新为下一个数字。
-
查看已经为你的管道启动的作业:
pachctl list job
以下是系统输出:
ID SUBJOBS PROGRESS CREATED MODIFIED
71169d… 1 2 minutes ago 2 minutes ago
pachctl list job 命令的输出给出了以下信息:

图 6.6 – 管道输出解释
现在我们的管道已成功运行,让我们在输出仓库中查看结果。
查看管道结果
一旦你的管道运行完毕,你可以在输出仓库中查看结果。我们将同时查看命令行和 Pachyderm 仪表板中的输出结果,以便进行查看。
如果你使用的是本地的 Pachyderm 部署并且使用了 minikube,你需要启用端口转发才能访问 Pachyderm 用户界面。
要在终端中查看管道结果,请执行以下步骤:
-
登录到你的终端。
-
验证名为
contour的输出仓库是否已创建:% pachctl list repo
以下是系统输出:
% pachctl list repo
NAME CREATED SIZE (MASTER) ACCESS LEVEL
contour About a minute ago ≤ 117.6KiB [repoOwner] Output repo for pipeline contour.
photos 5 minutes ago ≤ 110.4KiB [repoOwner] B
如你所见,contour 仓库已经创建,并且其中包含 117.6 KiB 的数据。如果你是在本地运行 Pachyderm,你还可以通过运行以下命令来预览这些文件的内容。
-
如果你使用的是 macOS,请运行以下命令列出输出仓库中的文件:
% pachctl list file contour@master
以下是系统输出:
NAME TYPE SIZE
/brown_vase.png file 23.78KiB
/hand.png file 29.79KiB
/landscape.png file 64.08Kib
-
现在,将
open命令与pachctl get file命令连接,打开 Mac 上默认的预览应用程序中显示的一张图片。例如,要预览hand.png,请运行以下命令:% pachctl get file contour@master:hand.png | open -f -a Preview.app
你应该会看到以下输出:

图 6.7 – 手动处理
现在,让我们在用户界面中查看处理后的结果。如果你是在云服务提供商上运行 Pachyderm,只需在浏览器中输入 Pachyderm 仪表板运行的 IP 地址。如果你是在 Pachyderm Hub 上运行 Pachyderm,请按照 Pachyderm Hub 中的指示访问控制台。如果你是在本地的 minikube 中运行 Pachyderm,请继续执行剩下的步骤以启用端口转发。
重要提示
除非你在 Pachyderm Hub 中运行实验,否则 Pachyderm 控制台仅在你已部署的情况下可用。你需要拥有试用版或企业版许可证,才能在本地或云中部署 Pachyderm 控制台。
-
打开一个独立的终端窗口。
-
通过运行以下命令为本地 Pachyderm 部署启用端口转发:
% pachctl port-forward
你应该会看到以下输出:
Forwarding the pachd (Pachyderm daemon) port...
listening on port 30650
Forwarding the pachd (Pachyderm daemon) port...
listening on port 30650
Forwarding the OIDC callback port...
listening on port 30657
Forwarding the s3gateway port...
listening on port 30600
Forwarding the identity service port...
listening on port 30658
Forwarding the dash service port...
...
如果你使用的是默认设置,Pachyderm 仪表板应在 http://localhost:30080 加载。
-
将仪表板的 IP 地址粘贴到网页浏览器中。
-
如果系统提示您登录,请按照屏幕上的指示进行操作。登录后,您应该会看到以下界面:

图 6.8 – Pachyderm 直接无环图(DAG)
这是一个为输入和输出仓库以及管道创建的直接无环图(DAG)。
- 点击轮廓输出仓库(屏幕上的最后一个),然后点击查看文件:

图 6.9 – 输出仓库信息
文件列表将会显示出来。
- 点击
hand.png:

图 6.10 – 输出文件
您可以通过 UI 预览所有结果文件。同样,这些文件可以由另一个管道消费,或者通过 S3 网关提供给 Pachyderm 之外的服务,或者输出仓库可以被挂载并在本地磁盘上访问。接下来,我们来看看其他图像应该是什么样子。
您应该看到景观图像已发生变化,如下所示:

图 6.11 – 处理后的景观图像
brown_vase.png图像应该如下所示:

图 6.12 – 处理后的花瓶图像
在本节中,我们学习了如何查看管道的结果。现在,让我们添加另一个管道步骤。
添加另一个管道步骤
Pachyderm 管道可以连接成多步骤工作流。对于每个步骤,您需要有单独的管道规范和一个 Docker 镜像(如果使用了的话)。在本节中,我们将为我们的图像处理工作流添加另一个步骤。我们将使用skimage.exposure.histogram模块为我们在contour输出仓库中的所有图像创建直方图。
示例概述
直方图是数据的可视化表示,提供了有关图像的信息,如像素的数量、强度以及其他信息。由于我们将图像表示为数值数据,因此可以为我们在工作流第一步——轮廓管道中处理的每个图像创建一个直方图。在工作流的这一步中,我们将为每个已存入contour输出仓库的图像创建直方图,并将它们以 PNG 格式保存到histogram输出仓库中。
这是为hand.png图像生成的直方图示例:

图 6.13 – 灰度图像直方图
y 轴表示像素的数量,而x 轴表示像素的强度。
这是包含轮廓和直方图管道的新两步工作流图:

图 6.14 – 轮廓和直方图工作流
histogram管道将从contour仓库中获取文件,为它们创建直方图,并将它们输出到histogram仓库。
直方图创建脚本概述
在此管道步骤中,我们将使用histogram.yaml,它将为我们创建一个管道。该管道将运行histogram.py脚本。
让我们回顾一下 histogram.py 脚本,它从 contour 仓库中的文件创建直方图:
from skimage import io
import matplotlib.pyplot as plt
import numpy as np
import os
def create_histogram(photo):
image = io.imread(photo)
t = os.path.split(photo)[1]
plt.hist(image.ravel(), bins=np.arange(10, 70), color='blue', alpha=0.5, rwidth=0.7)
plt.yscale('log')
plt.margins(x=0.03, y=-0.05)
plt.xlabel('Intensity')
plt.ylabel('Count')
plt.savefig(os.path.join("/pfs/out", os.path.splitext(t)[0]+'.png'))
for dirpath, dirnames, filenames in os.walk("/pfs/contour"):
for f in filenames:
create_histogram(os.path.join(dirpath, f))
该脚本导入了以下库:
-
skimage.io:io模块来自 scikit-image 库,它使我们能够在 Python 文件中进行读写操作。我们需要这个模块从contour仓库中读取文件。 -
matploit.pyplot:这个 Matplotlib 接口使我们能够绘制图像。我们使用它来创建直方图,为图表的 x 轴和 y 轴添加标签等等。 -
numpy:我们需要 NumPy 将图像表示为数组,并保持所需范围内的柱状图数量。 -
os:Python 标准库中的os模块使我们能够进行文件的读写操作。我们需要这个模块从 Pachyderm 的contour仓库中读取图像,并将图像保存到正确的输出仓库中。
让我们更仔细地看一下脚本的功能。create_histogram 函数从 contour 仓库中读取图像文件。然后,使用 matploit.pyplot.hist (plt.hist) 函数,脚本使用以下参数创建一个直方图:
-
numpy.ravel函数将图像从二维数组转换为一维数组,这对于绘制直方图是必要的。 -
bins参数定义了直方图中垂直条形的形状和分布。为了在图表中均匀分布它们,我们使用np.arange函数定义了一个范围。 -
color='blue'参数定义了直方图柱状图的颜色。 -
alpha=0.5参数定义了透明度的级别。 -
rwidth=0.7参数定义了每个柱状图的宽度。 -
plt.yscale('log')参数定义了 y 轴的对数尺度。我们需要这个参数来缩小 y 轴的尺度,以便更好地进行数据可视化。 -
plt.margins(x=0.03, y=-0.05)参数定义了直方图与图表起始位置之间的空白区域。 -
plt.xlabel('Intensity')和plt.ylabel('Count')参数定义了 x 轴和 y 轴的标签。 -
plt.savefig函数定义了直方图的保存位置。在我们的例子中,我们将把它保存在pfs/out目录下,Pachyderm 会自动在pfs/out/histogram路径下创建一个直方图仓库。重要说明
在你的脚本中,你不需要添加仓库的路径,只需添加
pfs/out目录的路径。
流水线规范概述。
histogram.yaml 流水线规范创建了直方图流水线。
下面是我们的流水线规范的样子:
---
pipeline:
name: histogram
description: A pipeline that creates histograms for images stored in the contour repository.
transform:
cmd:
- python3
- "/histogram.py"
image: svekars/contour-histogram:1.0
input:
pfs:
repo: contour
glob: "/"
这个流水线的功能如下:
-
将存储在
contour仓库中的文件上传为一个单独的数据项。 -
从 Docker Hub 拉取存储的 Docker 镜像
svekars/histogram:1.0。 -
对从
contour仓库下载的所有文件运行histogram.py脚本。 -
将转换结果上传到
histogram输出仓库。
现在我们已经审查了流水线的内容,让我们继续创建它。
创建流水线。
下一步是创建直方图流水线,该流水线将为photos仓库中的每个图像创建一个直方图。
让我们通过使用histogram.yaml文件创建工作流的第二个步骤:
-
登录到终端。
-
验证 Pachyderm 是否已启动并运行:
% pachctl version
以下是系统输出:
COMPONENT VERSION
pachctl 2.0.0
pachd 2.0.0
如果pachd没有响应,您可能需要在本地安装中运行minikube stop和minikube start,以便能够继续使用它。如果您在云环境中,您需要检查您的连接。如果您在 Pachyderm Hub 中运行 Pachyderm,请检查您是否已经从控制台进行身份验证,并按照屏幕上的说明操作。
-
创建
histogram流水线:% pachctl create pipeline -f histogram.yaml
不会返回系统输出。
-
验证流水线是否已创建:
% pachctl list pipeline
以下是系统输出:
NAME VERSION INPUT CREATED STATE / LAST JOB DESCRIPTION
contour 1 photos:/* 12 minutes ago running / success A pipeline that identifies contours on an image.
histogram 1 contour:/ 12 seconds ago running / success A pipeline that creates histograms for images stored in the contour repository.
根据前面的输出,直方图流水线已创建,并且当前正在运行代码。
-
获取仓库列表:
% pachctl list repo
以下是系统输出:
NAME CREATED SIZE (MASTER) DESCRIPTION
histogram 23 seconds ago ≤ 27.48KiB [repoOwner] Output repo for pipeline histogram.
contour 24 minutes ago ≤ 117.6KiB [repoOwner] Output repo for pipeline contour.
photos 29 minutes ago ≤ 110.4KiB [repoOwner]
histogram输出仓库已创建,并包含 27.48 KiB 的数据。这些是我们的直方图文件。
-
列出
histogram仓库中的文件:% pachctl list file histogram@master
以下是系统输出:
NAME TYPE SIZE
/hand.png file 9.361KiB
/landscape.png file 9.588KiB
/brown_vase.png file 8.526KiB
到此,我们的直方图可视化已经被添加到仓库中。
-
查看直方图文件。例如,如果您在 Mac 上查看
landscape.png直方图文件,请运行以下命令:pachctl get file histogram@master:landscape.png | open -f -a Preview.app
这是结果直方图:

图 6.15 – 风景图像的直方图
您可以通过类似的方式或通过前面提到的 Pachyderm 控制面板预览其他文件。
- 进入控制台,查看新添加的流水线的 DAG:

图 6.16 – 更新后的 DAG
如您所见,您现在有一个名为histogram的新流水线,并且在 DAG 中新增了一个同名的输出仓库。
现在我们已经创建了第一个流水线,让我们清理环境,以便有一个干净的集群来处理下章中的任务。
清理
一旦实验完成,您可能想清理集群,以便开始下一个实验时有一个全新的安装。要清理环境,请执行以下步骤:
-
删除所有流水线和仓库:
pachctl delete pipeline –all && pachctl delete repo --all -
验证集群中是否存在仓库和流水线:
pachctl list repo && pachctl list pipeline
您应该看到以下输出:
NAME CREATED SIZE (MASTER) DESCRIPTION
NAME VERSION INPUT CREATED STATE / LAST JOB DESCRIPTION
至此,您已成功清理了集群。
总结
在本章中,您成功创建了第一个 Pachyderm 仓库、流水线,甚至通过添加另一个流水线步骤进行了扩展。我们使用了 scikit-image、Matplotlib 和 NumPy 来创建存储在 Pachyderm 仓库中的图像的轮廓,并为这些图像创建了直方图。这是理解 Pachyderm 如何工作的第一步。在 Pachyderm 中,您将经常使用流水线。正如您已经注意到的,您可以在流水线中放入任何代码。尽管本书中的大多数示例将使用 Python,您可以使用任何您选择的编程语言。
在下一章中,我们将深入学习 Pachyderm 的功能,如何将数据导入 Pachyderm 并将其导出到外部系统,如何修改管道代码,如何调整各种参数以及其他重要的 Pachyderm 操作。
进一步阅读
有关本章涵盖的主题的更多信息,请查看以下资源:
-
Docker Hub 文档:
docs.docker.com/docker-hub/ -
Matplotlib 文档:
matplotlib.org/ -
NumPy 文档:
numpy.org/doc/stable/ -
Scikit-image 文档:
scikit-image.org -
风景图片:
www.freepik.com/free-vector/beautiful-gradient-spring-landscape_6969720.htm -
棕色花瓶图片:
www.freepik.com/free-photo/narrow-neck-vase_921733.htm -
手部图片:
www.freepik.com/free-photo/hand-holding-something-with-white-background_978615.htm
第七章:第七章:Pachyderm 操作
在 第六章,创建第一个管道 中,我们创建了第一个管道,并学习了如何创建 Pachyderm 仓库、将数据放入仓库、创建并运行管道,以及查看管道的结果。我们现在知道如何创建标准的 Pachyderm 管道规范,并将脚本包含在其中,以便它们可以在输入仓库中的数据上运行。
在本章中,我们将回顾所有不同的将数据放入 Pachyderm 内部并导出到外部系统的方法。我们将学习如何更新在管道内部运行的代码,以及更新管道规范的过程。我们将学习如何构建一个 Docker 容器并在上传到注册表之前进行本地测试。
我们还将探讨一些最常见的故障排除步骤,这些步骤是在管道失败时应执行的。
本章将涵盖以下主题:
-
回顾标准的 Pachyderm 工作流程
-
执行数据操作
-
执行管道操作
-
执行维护操作
技术要求
您应该已经安装了以下组件。
对于本地 macOS 安装,您需要以下组件:
-
macOS Mojave、Catalina、Big Sur 或更高版本
-
Docker Desktop for Mac 10.14
-
minikubev1.9.0 或更高版本 -
pachctl2.0.x 或更高版本 -
Pachyderm 2.0.x 或更高版本
对于本地 Windows 安装,您需要以下组件:
-
Windows Pro 64 位 v10 或更高版本
-
Windows Subsystem for Linux (WSL) 2 或更高版本
-
Microsoft PowerShell v6.2.1 或更高版本
-
Hyper-V
-
minikubev1.9.0 或更高版本 -
kubectlv1.18 或更高版本 -
pachctl2.0.x 或更高版本 -
Pachyderm 2.0.x 或更高版本
对于 Amazon Elastic Kubernetes Service (Amazon EKS) 安装,您需要以下组件:
-
kubectlv.18 或更高版本 -
eksctl -
aws-iam-authenticator -
pachctl2.0.x 或更高版本 -
Pachyderm 2.0.x 或更高版本
对于 Microsoft Azure Kubernetes Service (AKS) 云安装,您需要以下组件:
-
kubectlv.18 或更高版本 -
Azure CLI
-
pachctl2.0.x 或更高版本 -
Pachyderm 2.0.x 或更高版本
-
jq1.5 或更高版本
对于 Google Kubernetes Engine (GKE) 云安装,您需要以下组件:
-
Google Cloud SDK v124.0.0 或更高版本
-
kubectlv.18 或更高版本 -
pachctl2.0.x 或更高版本 -
Pachyderm 2.0.x 或更高版本
除此之外,您还需要以下组件:
- Docker Hub 账户,用于上传镜像
下载源文件
本章的所有源文件都位于此仓库:github.com/PacktPublishing/Reproducible-Data-Science-with-Pachyderm/tree/main/Chapter07-Pachyderm-Operations。
回顾标准的 Pachyderm 工作流程
正如您在创建管道时可能已经注意到的那样,在使用 Pachyderm 时,您需要遵循特定的工作流。根据您的自动化工具、团队流程和所使用的软件,它可能会有所不同,但通常可以总结为以下常见步骤:
-
将您的数据添加到 Pachyderm。
-
创建管道或管道集。
-
添加更多数据。
-
修改参数。
-
修改您的管道或管道集。
-
将结果输出到输出仓库。
-
根据需要或持续地重复步骤 3-6。
-
提供您的模型或打包您的库并使其可用。
以下图示演示了这一过程:

图 7.1 – Pachyderm 工作流
根据您将代码存储在 Docker 镜像中、管道本身中,还是使用包含 Python 代码的构建管道,您每次更改代码时都需要重新构建 Docker 镜像。对于仅使用 Python 管道的轻量级工作流,它使用基础 Docker 镜像和一个特殊的构建管道。您可以在 Pachyderm 官方文档中阅读有关此方法的信息:docs.pachyderm.com。对于其他语言,您可能需要定期构建 Docker 镜像。
现在我们知道了典型的工作流,让我们深入了解数据操作,学习所有将数据上传到 Pachyderm 的方法。
执行数据操作。
正如您可能已经注意到的,要开始使用 Pachyderm,您需要将数据放入其中。然后,数据会通过多个转换步骤进行处理。之后,您可以将数据和模型导出到外部源,以库、二进制文件、包、表格、仪表盘或任何其他格式进行进一步使用。在本节中,我们将回顾将数据上传和下载到 Pachyderm 以及从 Pachyderm 下载数据的方式,并介绍在此过程中可以应用的所有原生 Pachyderm 修改。
让我们从将数据上传到 Pachyderm 开始。
将数据上传到 Pachyderm。
您可以将将数据导入到 Pachyderm 的数据源分为以下几类:
-
从本地文件系统上传
-
从 URL 上传。
-
远程对象或块存储
-
一个流媒体或消息平台。
在本节中,您很可能主要使用本地文件系统将数据上传到 Pachyderm 仓库。这可以通过一个简单的 Pachyderm 命令完成:
-
要从本地文件系统上传数据,您可以使用以下命令:
pachctl put file -f <filename> repo@branch
仓库必须存在。
-
同样,要上传存储在远程位置的数据,您可以使用相同的命令,并指定正确的 URL:
pachctl put file -f https://mylink repo@branch -
对存储在对象存储中的文件同样适用。例如,如果您使用 Google Cloud Platform 上的对象存储,您可以使用以下命令:
pachctl put file -f gs://my-bucket repo@branch
之前的命令将文件放置在仓库的根目录中,但您也可以通过指定路径,将它们放入任何子目录中,如下所示:
pachctl put file -f gs://my-bucket repo@branch:/path
-
要上传整个目录,请使用
-r标志:pachctl put file -f directory -r repo@branch:/
运行pachctl put file --help查看更多示例。
-
如果您希望从消息队列自动上传数据到 Pachyderm,您需要创建一种特殊类型的管道,称为吐水口(spout)。吐水口的主要功能是将来自消息平台的数据流连接到 Pachyderm,并将其放入指定的 Pachyderm 仓库。您还可以指定一些代码,根据首选模式将数据分类到不同的文件夹中。以下是一个吐水口管道的示例:
--- pipeline: name: my-spout spout: {} transform: cmd: - python - myspout.py image: registry/image:1.0 env: HOST: my-messaging-queue TOPIC: mytopic PORT: '5672'
现在我们知道如何将数据放入 Pachyderm,让我们来看看 Pachyderm 中的数据来源和数据血统。
关于数据血统
如果您的系统依赖于数据,您需要确保用于决策过程的数据是准确且可信的。未能提供可追溯的数据足迹,可能会导致对组织的不利后果。随着越来越多基于数据的系统应用于我们生活的各个方面,基于错误数据做出的错误决策可能会对人们的生活造成毁灭性影响。
这就是为什么能够回溯到数据的源头并追踪数据的来源,是任何数据管理系统中的一个关键部分。能够追踪数据在多个转化步骤中发生的变化,直到其源头,这就是数据血统或数据来源。
通常,数据血统以有向无环图(DAG)的形式进行可视化。以下是 Pachyderm UI 中 DAG 表示的示例:

图 7.2 – Pachyderm DAG
每个容器代表一个输入或输出的仓库,或者一个管道。前面的示例非常简单。在有更多步骤的工作流中,DAG 可能看起来更为复杂。
为什么数据血统如此重要?以下是几个需要考虑的重要点:
-
随着隐私和公平等话题在各个层面被广泛讨论,为治理提供审计追踪正变得越来越必要。
-
随着数据科学的广泛产品化,实现一个能够回滚并修正数据和算法错误的系统变得至关重要。
-
数据的可信度是可以通过数据血统验证的另一个方面。
在第一章《可重复性问题》中,我们讨论了许多缺乏合适数据管理系统可能对人们生活产生毁灭性影响的例子,并且对企业造成损害。
现在我们已经讨论了数据血统的重要性,让我们来看一下如何在 Pachyderm 中探索数据血统。
探索数据血统
数据来源或数据血统是 Pachyderm 最重要的特性之一,它确保您的更改被保存并且可以追溯到管道的起点。
为了演示这个功能,我们将使用在第六章中使用的相同管道,创建你的第一个管道。如果你还没有下载这些文件,可以访问github.com/PacktPublishing/Reproducible-Data-Science-with-Pachyderm/tree/main/Chapter06-Creating-Your-First-Pipeline并从那里下载:
-
创建 Pachyderm 的
photos仓库,将brown_vase.png文件放入其中,并通过运行以下命令创建轮廓和直方图管道:pachctl create repo photos pachctl put file -f brown_vase.png photos@master pachctl create pipeline -f contour.yaml pachctl create pipeline -f histogram.yaml
你应该看到以下输出:
brown_vase.png 25.82KB / 25.82 KB [================] 0s 0.00 b/s
-
以下命令展示了如何查看你的数据和管道的谱系。首先,我们需要获取一个提交号,以便查看所需的数据变化:
pachctl list commit contour@master
输出应该类似于以下内容:
REPO BRANCH COMMIT FINISHED SIZE ORIGIN DESCRIPTION
contour master 3d42... 22 seconds ago 23.78KiB AUTO
在这个示例中,我们只有一个输出提交,哈希值为3d42e6385854478fbd2c9212c3afdab2。
-
然后,我们可以运行
inspect commit命令来获取溯源信息:pachctl inspect commit contour@3d42e6385854478fbd2c9212c3afdab2
前面的命令返回以下输出:
{
"commit": {
"branch": {
"repo": {
"name": "contour",
"type": "user"
},
"name": "master"
},
"id": "3d42e6385854478fbd2c9212c3afdab2"
},
"origin": {
"kind": "AUTO"
},
"child_commits": [
{
"branch": {
"repo": {
"name": "contour",
"type": "user"
},
"name": "master"
},
"id": "dfff764bd1dd41b9bf3613af86d6e45c"
}
],
"started": "2021-08-18T17:03:32.180913500Z",
"finishing": "2021-08-18T17:03:39.172264700Z",
"finished": "2021-08-18T17:03:39.225964100Z",
"direct_provenance": [
{
"repo": {
"name": "contour",
"type": "spec"
},
"name": "master"
},
{
"repo": {
"name": "photos",
"type": "user"
},
"name": "master"
}
],
"size_bytes_upper_bound": "24353",
"details": {
"size_bytes": "24353"
}
}
该输出显示了提交是在photos仓库中创建的。它的类型为AUTO,因为它是在数据上传到photos仓库时自动生成的。你还可以看到它创建了一个子提交,哈希值为dfff764bd1dd41b9bf3613af86d6e45c,你可以对其运行相同的命令。该子提交将具有ALIAS类型,因为它与photos仓库中的原始提交相关联。随着新数据的到来,这个列表会逐渐增加。
-
前面的命令告诉我们
contour仓库中提交的前驱是什么。我们还可以使用wait commit命令结合提交 ID 来跟踪提交何时进入输出仓库。例如,如果我们想查看3e16201310374944b48ed73f83be2be7提交在下游管道中带来的变化,可以运行以下命令:pachctl wait commitset photos@438428d0c3a145aa905c86c9fb1789ea
溯源是 Pachyderm 的一个强大功能。当你需要寻找审计轨迹以查明是什么导致管道产生偏差时,它特别有用。
现在我们已经学习了如何在 Pachyderm 中探索数据溯源,接下来我们来看看如何将 Pachyderm 仓库挂载到本地文件系统。
将 Pachyderm 仓库挂载到本地文件系统
你可以通过使用用户空间文件系统(FUSE)接口将 Pachyderm 系统挂载到本地计算机,从而像访问本地文件一样访问你的 Pachyderm 仓库。FUSE 支持所有主流平台,如 Microsoft Windows、Linux 和 macOS。默认情况下,你可以以只读方式挂载 Pachyderm 仓库,但也可以启用写入权限。你需要明白,修改这些挂载中的文件会导致溯源信息破坏,因此通常不应使用这种方式。可以使用这个功能来执行以下操作:
-
查看管道运行的结果。
-
允许第三方应用程序访问 Pachyderm 输出仓库,以便进行进一步处理。
要将 Pachyderm 仓库挂载到本地计算机文件系统,请完成以下步骤:
-
在你的机器上安装 FUSE。如果你使用的是 macOS,请运行以下命令:
brew install osxfuse
如果你使用的是 Linux,请运行以下命令:
sudo apt-get install -y fuse
在 Windows 上,运行以下命令:
choco install winfsp
-
使用
pachctl mount命令挂载 Pachyderm 仓库。例如,要挂载contour仓库,请运行以下命令:pachctl mount ~/Documents/contour --repos contour@master
此命令将在你的终端中持续运行,直到你用Ctrl + C中断它。
- 要访问你的文件,打开文件浏览器。例如,如果你使用的是 macOS,请使用 Finder。你应该能看到像下面这样的
~/Documents/contour文件夹已挂载:

图 7.3 – 挂载的 Pachyderm 仓库
在这里,你可以根据需要查看文件。
-
要挂载具有写权限的仓库,请使用相同的命令并加上
--write标志:pachctl mount ~/Documents/contour --repos contour@master --write
请谨慎使用此功能,因为修改输出仓库中的文件会破坏来源信息。
-
要挂载多个仓库,请使用
--repos标志指定每个仓库的列表:pachctl mount ~/Documents/pachyderm-repos --repos contour@master --repos data@master --repos histogram@master --repos photos@master
以下截图显示了data、contour、histogram和photos仓库在你的机器上是如何挂载的:

图 7.4 – 挂载的 Pachyderm 仓库
在本节中,我们学习了如何执行最常见的 Pachyderm 数据操作,包括将数据上传到 Pachyderm、探索来源信息、将 Pachyderm 仓库挂载到本地计算机,以及在将数据上传到 Pachyderm 时进行数据拆分。接下来,我们将探讨在使用 Pachyderm 时需要执行的最常见管道操作。
执行管道操作
除了创建和删除管道外,你还可能需要使用新的代码更改更新管道。如果对管道规范本身进行了更改,例如增加 Pachyderm 工作节点的数量、输入仓库、通配符模式或类似的更改,你只需要在 YAML 或 JSON 文件中进行更改,并更新管道规范的版本。但是,如果更改发生在你的代码中,并且代码在 Docker 镜像中,你需要重建 Docker 镜像。让我们逐一讨论这些使用场景。
更新你的管道规范
管道规范使你能够控制各种 Pachyderm 参数,例如控制管道从哪个仓库获取数据、启动多少个工作节点以及为管道分配多少资源。你还可以通过stdin字段在管道中指定你的代码。这样的管道可以使用一个基本的 Docker 镜像,你不需要更新它。如果是这种情况,并且你需要在管道规范或stdin字段中的代码中进行更改,以下是你需要做的步骤:
-
在包含管道规范的 YAML 或 JSON 文件中进行必要的更改。例如,如果你想将
contour.yaml管道中的 glob 模式从glob: "/"更改为glob: "/*",只需直接在 YAML 文件中进行这些更改并保存。 -
然后,你需要通过指定这个 YAML 文件来更新已运行管道的版本:
pachctl update pipeline -f contour.yaml -
验证管道版本是否已更新:
pachctl list pipeline
如果之前的管道版本是1,它应该变成2:
NAME VERSION INPUT CREATED STATE / LAST JOB DESCRIPTION
contour 2 photos:/* 6 seconds ago running / success A pipeline that identifies contours on an image.
新的管道不会处理已经处理过的数据,除非你通过使用--reprocess标志明确指定。
-
要在已处理的数据上运行更新后的管道,请使用以下命令:
pachctl update pipeline -f contour.yaml --reprocess -
在输出中,你应该看到版本已再次更新:
NAME VERSION INPUT CREATED STATE / LAST JOB DESCRIPTION contour 3 photos:/* 15 seconds ago running / success A pipeline that identifies contours on an image. -
默认情况下,如果你运行
pachctl list pipeline,Pachyderm 只会显示最新管道的信息。如果你使用--history标志运行此命令,你可以看到所有的历史版本:pachctl list pipeline contour --history 3
输出应该如下所示:
NAME VERSION INPUT CREATED STATE / LAST JOB DESCRIPTION
contour 3 photos:/ 25 seconds ago running / success A pipeline that identifies contours on an image.
contour 3 photos:/ 25 seconds ago running / success A pipeline that identifies contours on an image.
contour 3 photos:/ 25 seconds ago running / success A pipeline that identifies contours on an image.
你可以看到,版本 3 的管道已经运行了三次。
-
现在,让我们检查第三个版本的管道是否在
contour仓库中输出了提交:pachctl list commit contour@master
这个命令应该返回类似的输出:
REPO BRANCH COMMIT FINISHED SIZE ORIGIN PROGRESS DESCRIPTION
contour master 38eb403e62844f45939c6307bb0177c7 46 seconds ago 23.78KiB AUTO
现在我们知道了如何在没有代码更改的情况下更新管道,让我们看看当你的代码在 Docker 镜像中时,需要更新代码的工作流。
更新你的代码
如果你的代码被指定在一个嵌入到 Docker 镜像中的文件中,每次修改代码时,你需要重新构建这个 Docker 镜像,上传到 Docker 注册表,并给镜像指定一个新的版本,然后在你的管道规范中更新镜像版本,最后运行pachctl update pipeline命令。
让我们修改在第六章中创建的轮廓管道中的contour.py文件,创建你的第一个管道。你需要在 Docker 注册表中有一个账户来完成此部分。如果你没有账户,可以在 Docker Hub 上创建一个免费账户。本书中提到的所有镜像都存储在 Docker Hub 中,我们将以 Docker Hub 为例。如果你使用其他 Docker 镜像注册表,请按照该注册表的文档进行登录并上传镜像。
我们还需要这个管道的 Dockerfile 来构建新的镜像:
-
如果你还没有这样做,请从
github.com/PacktPublishing/Reproducible-Data-Science-with-Pachyderm/tree/main/Chapter06-Creating-Your-First-Pipeline下载 Dockerfile。 -
通过在
hub.docker.com/注册来配置你的 Docker Hub 账户。 -
登录到 Docker Hub 后,点击创建仓库。
-
为你的仓库命名并写一个简短的描述。在本示例中,我们将使用公共注册表,但 Pachyderm 也支持私有注册表:

图 7.5 – 创建 Docker Hub 注册表
-
点击创建。
-
打开您机器上的终端并运行以下命令:
docker login -
提供您的 Docker Hub 凭据以登录到 Docker Hub。您应该会看到如下输出:
Login Succeeded -
打开
contour.py文件进行编辑。 -
让我们在代码中做一个非常小的改动——在第 18 行,将
linewidth改为1。修改后应该是这样:ax.plot(contour[:, 1], contour[:, 0], linewidth=1) -
保存您的更改并退出。
-
为了使这些更改在我们的 Pachyderm 管道中生效,我们需要构建一个新的 Docker 镜像。为了使下一个命令生效,您需要确保当前目录中有 Dockerfile。运行以下命令:
docker build . -t <your-registry>/contour-histogram:1.1
将<your-registry>替换为您通过前面的步骤创建的 Docker Hub 仓库名称。您应该会看到类似以下的输出:
Sending build context to Docker daemon 2.325GB
Step 1/10 : FROM ubuntu:18.04
---> 3339fde08fc3
…
Step 9/10 : ADD contour.py /contour.py
---> 4fb17a5f1f0b
Step 10/10 : ADD histogram.py /histogram.py
---> e64f4cb9ecb1
Successfully built e64f4cb9ecb1
第一次构建 Docker 镜像时可能会需要一些时间。请注意,在前面输出的第 9 步中,Docker 会添加您更新后的contour.py脚本。
-
下一步是将您的镜像上传到 Docker 注册表。您也可以先将 Docker 镜像本地挂载并测试,然后再上传。要将 Docker 镜像本地挂载,运行以下命令:
docker save <your-registry>/contour-history:1.1 | (\ eval $(minikube docker-env) docker load )
这个命令需要一些时间才能运行,但当您需要测试某些内容而不需要不断将新镜像推送到 Docker Hub 时,它非常方便。我们建议您将镜像本地挂载,运行管道,准备好后再上传到 Docker Hub。
或者,如果是直接上传到 Docker Hub,请运行以下命令:
docker push <your-registry>/contour-history:1.1
-
在加载完您的镜像后,您需要使用管道的新版本更新管道规范。每次构建新镜像时,给镜像分配一个新版本号,以便跟踪您的更改。要更新管道规范中的镜像版本,打开
contour.yaml文件,并更改以下第9行:9 image: <your-registry>/contour-histogram:1.1 -
现在,您可以使用新的代码运行更新后的管道。让我们运行
update命令并带上--reprocess标志,以查看我们的更改如何影响结果:pachctl update pipeline -f contour.yaml --reprocess
在下图中,您可以看到两个版本之间的比较。左边是第一版,轮廓明显比右边的新版本要粗:

图 7.6 – 比较管道版本的结果
我们已经学习了如何更新 Pachyderm 管道。这种方法适用于任何语言或框架。Pachyderm 也提供了内建的Docker build和Docker push命令可以使用。不过,我们建议您遵循前面描述的过程,因为它似乎更为大多数工程师熟悉,也更为透明。
运行维护操作
像所有系统或工具一样,Pachyderm 可能需要定期维护、升级和故障排除。在接下来的部分中,我们将讨论管道维护的最重要方面。
故障排除您的管道
在本节中,您将学习如何排查管道错误。
您的管道可能因以下原因失败:
-
代码错误:这种类型的错误发生在代码中出现问题时,比如某个资源不可用或指定了错误的值。修复这种错误涉及到排查代码。您可以尝试在本地修复后再在 Pachyderm 中进行测试。
-
管道规范错误:这种类型的错误发生在管道规范中出现问题时;例如,管道无法拉取 Docker 镜像。这通常发生在指定了错误的镜像版本或存在网络问题时。
-
资源相关错误:这种类型的错误发生在您的集群内存耗尽或存在类似资源限制的问题时。
Pachyderm 提供了通过 pachctl logs 命令进行管道故障排查的内置功能,您也可以使用 Kubernetes 原生工具来排查管道问题。由于每个 Pachyderm 管道都是一个 Kubernetes Pod,您可以使用 Kubernetes 的日志记录和调试工具来进行故障排查。
若要检测和排查 Pachyderm 管道错误,请完成以下步骤:
-
当管道失败时,您应该在管道状态中看到它:
pachctl list pipeline
这是一个失败管道的示例输出:
NAME VERSION INPUT CREATED STATE / LAST JOB DESCRIPTION
contour 1 photos:/ 28 seconds ago crashing / starting A pipeline that identifies contours on an image.
-
要排查此管道问题,我们需要查看管道或作业的日志。要查看管道的日志,请运行以下命令:
pachctl logs --pipeline=contour
以下是一个示例响应:
container "user" in pod "pipeline-contour-v1-fmkxj" is waiting to start: image can't be pulled
在前面的示例中,失败的原因很明显——管道未能拉取 Docker 镜像。这可能是由于管道规范中指定的镜像版本错误或网络问题导致的。验证管道规范是否正确通常能够解决问题。
-
以下文本是管道中另一个常见代码错误的示例:
Traceback (most recent call last): File "/pos-tag.py", line 13, in <module> with open('/pfs/out/pos-tag/pos-table.txt', 'w') as f: FileNotFoundError: [Errno 2] No such file or directory: '/pfs/out/contour/pos-table.txt'
在前面的示例中,管道未能找到指定的文件。这很可能是因为在 pos-tag.py 文件中指定的文件路径不正确。
-
在某些情况下,由于管道在启动作业之前崩溃,您可能无法查看作业日志。然而,在大多数情况下,您应该能够查看作业的日志。要查看作业日志,首先获取作业的哈希值:
pachctl list job
这是一个示例输出:
ID SUBJOBS PROGRESS CREATED MODIFIED
5865a26e1795481d96ecf867075c4f35 1 2 minutes ago 2 minutes ago
当您遇到管道错误时,如前述输出所示,进度条为黄色而不是绿色。这个指示符告诉您代码中可能存在问题。
-
使用作业哈希值查看作业日志中关于失败的更多信息:
pachctl logs --job=contour@5865a26e1795481d96ecf867075c4f35
输出应提供更多关于失败的信息。
-
最后,您可以使用
kubectl分析管道中的可能错误。通过运行以下命令获取您的管道 Pod 名称:kubectl get pod
您应该看到类似于以下的响应:
NAME READY STATUS RESTARTS AGE
etcd-0 1/1 Running 0 6h10m
pachd-85d69d846-drgrk 1/1 Running 0 6h10m
pg-bouncer-84df8bdc58-7kzzg 1/1 Running 0 6h10m
pipeline-contour-v1-7dgwl 1/2 ImagePullBackOff 0 6m54s
postgres-0 1/1 Running 0 6h10m
您需要获取管道 Pod 的日志。
-
通过运行以下命令获取 Pod 日志:
kubectl describe pod pipeline-contour-v1-7dgw重要说明
Pod 日志中的事件部分通常会提供关于任何问题的信息。有关 Kubernetes 调试和故障排除的更多信息,请参见 Kubernetes 文档:
kubernetes.io/docs/tasks/debug-application-cluster/。
这是你将看到的示例输出:
...
Events:
...
Normal BackOff 3m7s (x20 over 8m6s) kubelet, minikube Back-off pulling image "svekars/contour-histogram:1.2"
在这一部分,我们讨论了基本的故障排除操作。最佳策略是尽可能收集更多日志,分类问题,然后有针对性地进行排查。如果问题出在用户代码中,你可能想先在本地测试代码,再在 Pachyderm 中运行。最近 Pachyderm 引入的一个限制是免费套餐下,你能运行的管道数量有限。除非升级到付费版本,否则你将无法运行超过 16 个管道和 8 个工作者。
接下来,我们将讨论如何将集群从一个版本升级到另一个版本。
升级你的 Pachyderm 集群
Pachyderm 定期发布次要版本升级。升级不同次要版本和补丁版本(例如从 1.13.0 到 1.13.1,或从 1.12.4 到 1.13.0)相对直接,但在主要版本之间升级(例如从 1.13.0 到 2.0)可能会更具破坏性。让我们来回顾一下每种使用场景的过程。主要版本的升级不常发生。通常,Pachyderm 每隔几年发布一次主要版本。这类升级通常涉及破坏性更改,可能会有特定的说明。请参考 Pachyderm 文档,了解执行主要版本升级的步骤。
升级补丁和次要版本
在升级 Pachyderm 集群时,你需要确保备份你的数据和管道,升级pachctl的版本,然后重新部署你的集群。如果你在minikube环境中进行本地升级,可能不需要使用备份,但为了安全起见,还是建议创建一个备份。如果你在同一个命名空间中重新部署,所有数据应该仍然可用。如果你使用的是云环境,那么你需要在一个新的命名空间中重新部署。
要从一个补丁版本或次要版本升级到另一个版本,请完成以下步骤:
-
停止集群中当前正在运行的所有管道:
pachctl stop pipeline <pipeline> -
停止
contour管道:pachctl stop pipeline contour -
验证管道是否已挂起:
pachctl list pipeline
你应该看到以下输出:
NAME VERSION INPUT CREATED STATE / LAST JOB DESCRIPTION
contour 1 photos:/* 3 hours ago paused / success A pipeline that identifies contours on an image.
如果你有其他管道在运行,也请将它们停止。
-
如果你有任何自动化服务将数据上传到 Pachyderm,也需要确保所有外部数据加载操作已暂停。
-
为以防万一,将你的
pachd、etcd和console服务清单保存到单独的 YAML 文件中:kubectl get svc/pachd -o yaml > pachd_backup.yaml kubectl get svc/etcd -o yaml > etcd_backup.yaml kubectl get svc/dash -o yaml > dash_backup.yaml
如果你的升级失败,你应该能够通过这些清单手动恢复。
-
备份你的集群:
pachctl extract --no-auth --no-enterprise > my-pachyderm-backup
在上述示例中,我们指定了 --no-auth 和 --no-enterprise 标志。如果你使用的是 Pachyderm 企业版或已启用身份验证,请不要使用这些标志运行此命令。
-
验证
values.yaml文件是否已更新值。特别是,验证以下自动生成的值是否正确:global: postgresql.postgresqlPassword pachd: clusterDeploymentID rootToken enterpriseSecret oauthClientSecret -
升级你的
pachctl版本,如以下示例所示:brew upgrade pachyderm/tap/pachctl@2.0
使用系统中的包管理器进行升级。
-
验证 Pachyderm 版本是否已升级:
pachctl version --client-only
你应该在输出中看到升级后的版本。在这种情况下,版本为 2.0.0:
pachctl 2.0.0
-
使用
helm upgrade命令重新部署你的集群:helm upgrade pachd -f <pachyderm_deployment>_my_values.yaml pachyderm/pachyderm -
运行
kubectl get pod,直到你看到类似下面的 Pachyderm Pod 正在运行:NAME READY STATUS RESTARTS AGE console-5db94c4565-pzjft 1/1 Running 0 1m etcd-0 1/1 Running 0 1m pachd-84984bf656-g4w8s 1/1 Running 0 1m pg-bouncer-7f47f5c567-zwg8d 1/1 Running 0 1m postgres-0 1/1 Running 0 1m -
检查
pachd是否在运行:pachctl version
此命令应该返回类似如下的输出:
COMPONENT VERSION
pachctl 2.0.0
pachd 2.0.0
-
如果你在云环境中,使用以下命令从你创建的备份中恢复配置:
pachctl restore < my-pachyderm-backup -
检查你的管道和仓库是否已就绪:
pachctl list pipeline && pachctl list repo
系统响应应该类似于此:
NAME CREATED SIZE (MASTER) DESCRIPTION
contour 49 seconds ago 23.78KiB Output repo for ...
photos 49 seconds ago 25.21KiB
NAME VERSION INPUT CREATED STATE / LAST JOB DESCRIPTION
contour 1 photos:/* 6 minutes ago paused / success A pipeline that identifies contours on an image.
我们已经成功恢复了我们在新部署的集群中的仓库和管道。
清理
在你完成实验后,你可能想要清理你的集群,以便在下一个实验中重新开始。要清理环境,请运行以下命令:
-
删除所有管道和仓库:
pachctl delete pipeline –all && pachctl delete repo --all -
验证集群中是否没有仓库和管道:
pachctl list repo && pachctl list pipeline
你应该看到以下输出:
NAME CREATED SIZE (MASTER) DESCRIPTION
NAME VERSION INPUT CREATED STATE / LAST JOB DESCRIPTION
你已经成功清理了你的集群。
总结
在这一章中,我们学习了一些在 Pachyderm 集群生命周期中需要执行的最重要的操作。我们学习了多种将数据加载到 Pachyderm 的方式,包括如何使用消息系统进行数据加载。我们还学习了如何更新管道、构建 Docker 镜像,并将它们本地挂载或上传到 Docker 镜像仓库。最后,我们了解了一些基本的故障排除技巧以及如何在补丁和小版本之间进行升级。
在下一章中,我们将实现一个端到端的机器学习工作流,并深入了解如何部署更复杂的多步骤 Pachyderm 管道。
进一步阅读
-
Docker Hub 快速入门:
docs.docker.com/docker-hub/ -
Kubernetes 监控、日志记录和调试:
kubernetes.io/docs/tasks/debug-application-cluster/ -
Pachyderm 构建管道:
docs.pachyderm.com/latest/how-tos/developer-workflow/build-pipelines/ -
Dua, D. 和 Graff, C.(2019)。 UCI 机器学习库(
archive.ics.uci.edu/ml)。加利福尼亚州尔湾:加利福尼亚大学信息与计算机科学学院。
第八章:第八章:创建一个端到端的机器学习工作流
在之前的章节中,我们学习了 Pachyderm 基础知识,以及如何在本地和云平台上安装 Pachyderm。我们已经部署了第一个管道,学习了如何更新管道,并执行了一些基本的 Pachyderm 操作,如拆分。我希望到现在为止,你已经相信 Pachyderm 是一个功能极其强大的工具,能够提供很多灵活性和处理机器学习管道的能力。为了让这一点更加明显,我们将部署一个比之前更复杂的示例,远超之前的任何部署。希望这一章能特别有趣,能让你更加深入理解数据基础设施的特性。
本章将部署一个多步骤的 自然语言处理 (NLP) 工作流,演示如何大规模使用 Pachyderm。
本章包括以下主题:
-
NLP 示例概述
-
创建仓库和管道
-
创建一个命名实体识别 (NER) 管道
-
重新训练一个命名实体识别 (NER) 模型
技术要求
本章要求您安装并配置以下组件。
对于本地 macOS 安装,您需要以下组件:
-
macOS Mojave, Catalina, Big Sur 或更高版本
-
Docker Desktop for Mac 10.14
-
minikubev1.9.0 或更高版本 -
pachctl2.0.0 或更高版本 -
Pachyderm 2.0.0 或更高版本
对于本地 Windows 安装,您需要以下组件:
-
Windows Pro 64 位 v10 或更高版本
-
Windows Subsystem for Linux (WSL) 2 或更高版本
-
Microsoft PowerShell v6.2.1 或更高版本
-
Hyper-V
-
minikubev1.9.0 或更高版本 -
pachctl2.0.0 或更高版本 -
Pachyderm 2.0.0 或更高版本
对于 Amazon 弹性 Kubernetes 服务 (Amazon EKS) 安装,您需要以下组件:
-
kubectlv.18 或更高版本 -
eksctl -
aws-iam-authenticator -
pachctl2.0.0 或更高版本 -
Pachyderm 2.0.0 或更高版本
对于 Microsoft Azure 云安装,您需要以下组件:
-
kubectlv.18 或更高版本 -
Azure CLI
-
pachctl2.0.0 或更高版本 -
Pachyderm 2.0.0 或更高版本
-
jq1.5 或更高版本
对于 Google Kubernetes Engine (GKE) 云安装,您需要以下组件:
-
Google Cloud SDK v124.0.0 或更高版本
-
kubectlv.18 或更高版本 -
pachctl2.0.0 或更高版本 -
Pachyderm 2.0.0 或更高版本
云端或本地虚拟机的最低硬件要求如下:
-
CPU 数量:4
-
内存:8,192 MB
-
磁盘:20 GB
现在我们已经了解了完成本章任务所需的技术要求,我们可以部署一个具有足够资源的 Pachyderm 实例来运行本章描述的示例。
调整虚拟机参数
要运行本节描述的示例,您必须确保运行 Pachyderm 的虚拟机有足够的内存和 CPU,以满足管道的需求。无论是云环境还是本地环境,均适用此要求。
如果您在云平台上运行 Pachyderm,请确保已在符合本章技术要求部分中列出的最低硬件要求的虚拟机规格上部署了 Kubernetes。然后,按照第五章《在云平台上安装 Pachyderm》的描述重新部署您的 Pachyderm 集群。
如果您在本地计算机上通过minikube运行 Pachyderm,请确保minikube虚拟机足够大。如果您按照第四章《本地安装 Pachyderm》的描述部署了minikube虚拟机,您需要删除它,并部署一个具有更大 CPU 和内存的新minikube虚拟机。
为此,请完成以下步骤:
-
卸载旧的 Pachyderm 集群:
helm uninstall pachd
系统响应如下:
release "pachd" uninstalled
-
删除现有的
minikube虚拟机:minikube delete
您应该看到以下系统响应:
Deleting "minikube" in docker ...
Deleting container "minikube" ...
…
-
删除旧机器后,启动一个新的虚拟机,并使用以下参数:
minikube start --cpus 4 --memory 8192
此命令返回以下响应:
…
Starting control plane node minikube in cluster minikube
Creating docker container (CPUs=4, Memory=8192MB) ...
…
Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default
-
现在,按照第四章《本地安装 Pachyderm》的描述,重新部署您的 Pachyderm 集群。为了简单起见,以下是您需要运行的命令:
helm install --set deployTarget=LOCAL pachd ./pachyderm
您应该看到以下系统响应:
NAME: pachd
LAST DEPLOYED: Thu Aug 19 13:03:36 2021
NAMESPACE: default
STATUS: deployed
REVISION: 1
...
-
运行以下命令连接到
pachd:pachctl config import-kube local --overwrite pachctl config set active-context local
现在我们已经部署了足够资源的 Pachyderm 来运行本章中的示例,让我们回顾一下我们将要创建的 NLP 管道。
NLP 示例概述
在本节中,我们将回顾端到端的机器学习工作流,帮助我们理解如何在 Pachyderm 中调度它。
为了演示此功能,我们将创建一个 NLP 管道,对《沉睡谷的传说》这本由华盛顿·欧文所写的短篇小说书进行各种文本优化。
但首先,让我们回顾一下什么是 NLP 以及 NLP 涉及的典型阶段。
自然语言处理简介
NLP 是一种机器学习技术,使您能够分析自然文本,即语音或书面文本。这一人工智能分支已经存在多年,但随着计算机和互联网技术的进步,它找到了新的应用方式。
那么,如何在您的商业或学术研究中使用自然语言处理(NLP)呢?有很多方法,但最常见的包括以下几种:
-
语音识别:使计算机能够理解人类语音的技术。
-
聊天机器人:能够回答问题并从提供的答案中学习的软件。旧版聊天机器人基于标准软件工程技术定义的规则,因此它们无法进化,只能产生平庸的回答。新型聊天机器人则更加先进。
-
机器翻译:自动化将文本和语音从一种语言翻译成另一种语言的技术。最常见的例子当然是谷歌翻译。
-
文本提取、总结和分类:在信息过载的世界中,这是一项非常需要的技术。NLP 使你能够创建提供文本洞察的管道,比如研究论文的摘要或页面上使用的关键词信息。
-
情感分析:一种帮助根据信息的正面或负面情感来分类的著名技术。这项技术最著名的应用是 Gmail 邮箱分类器,它将你的电子邮件分为三类:主邮件、促销邮件和社交邮件。
这些是 NLP 的主要示例。然而,这个列表并不完整。NLP 还被应用于生物信息学中分析基因数据,在金融领域用于理解市场事件和趋势,在医疗保健中用于理解患者信息,以及在许多其他领域。
现在我们知道了 NLP 适用的领域,让我们回顾一下构建 NLP 管道所涉及的主要阶段。
学习 NLP 阶段
正如我们在上一节讨论的那样,NLP 用于解决各种与文本和语音相关的任务。像机器学习的其他领域一样,当你需要解决一个 NLP 问题时,你需要构建一个管道。NLP 管道有几种定义,但通常情况下,NLP 管道的阶段包括以下内容:
-
文本预处理或 清理:这一阶段包括诸如单词和句子分割、标记化、去除停用词和标点符号、将单词转换为小写字母、词形还原或词干提取等操作。
-
结构分析:这一阶段深入分析文本的主题。它包括如词性(POS)标注、依赖解析和词块切分等操作。
-
特征提取:这一阶段主要是回答关于数据的特定问题,并找出文本实体之间的关系。它可能包括如命名实体识别(NER)和命名实体消歧(NED)或链接和情感分析等任务。
-
建模:这一阶段是你在训练数据上训练模型并进行测试,以便将其进一步投入生产环境。
根据你的使用案例,管道可能包含所有或部分这些阶段,而且这些阶段的顺序也可能不同。
以下图示展示了一个示例的自然语言处理管道:

图 8.1 – 自然语言处理管道
现在我们知道了 NLP 管道的阶段,让我们更仔细地看看我们将要实现的示例。
回顾 NLP 示例
在我们的示例中,我们将使用华盛顿·欧文的《睡谷传奇》文本,最终我们将创建并训练一个 NER 管道,帮助我们回答书中主要人物是谁的问题。为了创建这个多步骤的工作流,我们需要创建以下管道:
-
数据清洗管道:该管道将从提供的 URL 下载文本,并清除所有 HTML 标签、标题及其他无关内容。然后,它将对文本进行分词、去除停用词和标点符号,接着进行词干提取和词形还原。
-
POS 标注管道:该管道将基于单词在句子中的位置和上下文,为从前一个管道清洗过的文本添加词性标注。
-
NER 管道:该管道将使用一个预训练模型处理我们的文本,并尝试为结果标注正确的实体。
-
NER 训练管道:该管道将基于提供的训练数据训练一个新的 NER 模型,以纠正第一个 NER 管道的结果。
-
改进版 NER 管道:该管道将使用新的 NER 模型处理我们的文本,并将故事中的人物列表输出到一个文本文件。
这是我们完整 NLP 管道工作流的示意图:

图 8.2 – Pachyderm NLP 管道
现在我们已经回顾了管道步骤,让我们一步步创建所有需要的仓库和管道。
创建仓库和管道
在本节中,我们将创建在前一节中回顾过的所有管道。六步工作流程将清理数据,应用词性标注(POS),执行命名实体识别(NER),根据提供的数据训练一个新的自定义模型,运行改进的管道,并将结果输出到最终的代码库。
第一步是创建数据清洗管道,它将从文本中剥离我们在进一步处理时不需要的元素。
重要提示
你需要从github.com/PacktPublishing/Reproducible-Data-Science-with-Pachyderm/tree/main/Chapter08-End-to-End-Machine-Learning-Workflow下载所有示例文件。Docker 镜像存储在hub.docker.com/repository/docker/svekars/nlp-example。
创建数据清洗管道
数据清洗通常是在执行其他任务之前进行的。对于这个管道,我们创建了一个 Python 脚本,使用自然语言工具包(NLTK)平台来执行数据清洗任务。NLTK 是一个开源的库集合,能够完成各种 NLP 相关任务,包括分词、词干提取、去除停用词和词形还原。
这是我们将用于该管道的管道规范:
---
pipeline:
name: data-clean
description: A pipeline that tokenizes the text.
input:
pfs:
glob: "/data.txt"
repo: data
transform:
cmd:
- python3
- "/data-clean.py"
image: svekars/nlp-example:1.0
这个管道执行以下操作:
-
从
data仓库中的data.txt文件获取提供的 URL -
使用
svekars/nlp-example:1.0镜像 -
运行
data-clean.py脚本,该脚本已添加到svekars/nlp-example:1.0镜像中
你可能注意到,在管道规格中使用的 glob 模式只处理一个文件——data.txt。这个文件包含了指向位于Project Gutenberg: Free eBooks网站的《睡谷传奇》文本的 URL。要访问该网站,请前往gutenberg.org。
现在我们已经回顾了管道,让我们更仔细地看看我们的脚本做了什么。以下是我们将在data-clean.py脚本中导入的组件列表:
from bs4 import BeautifulSoup
from urllib.request import urlopen
import nltk
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize
from nltk.stem.porter import PorterStemmer
nltk.download('wordnet')
from nltk.stem import WordNetLemmatizer
我们需要BeautifulSoup来解析包含我们文本的 HTML 文件。我们使用urlopen来打开data.txt文件中的 URL。我们需要 NLTK 以及stopwords、word_tokenize、PorterStemmer、WordNet和WordNetLemmatizer来执行各种 NLP 操作。
代码的第一部分打开我们已放置在数据仓库中的data.txt文件,读取文件并使用BeautifulSoup HTML 解析器解析文本。在paragraphs行中,我们去除除了<p> HTML 标签以外的所有 HTML 元素:
with open('/pfs/data/data.txt', "r", encoding='utf-8') as f:
data=f.read().replace('\n', '')
url = urlopen(data).read()
soup = BeautifulSoup(url, 'html.parser')
content = soup.get_text(strip=True)
paragraphs = soup.find_all('p')
脚本的第二部分将下载的文本保存到输出仓库中的文本文件。我们将需要下游管道:
f = open('pfs/out/text.txt', 'w', encoding='utf-8')
for i in paragraphs:
all_text = i.get_text()
f.writelines(all_text)
f.close()
在代码的下一部分中,我们使用word_tokenize NLTK 方法将文本拆分为单独的标记,并将其保存到输出仓库中的tokens.txt文件中:
tokens = []
for i in paragraphs:
tokens += word_tokenize(i.text)
with open('/pfs/out/tokens.txt', 'w', encoding='utf-8') as filehandle:
for item in tokens:
filehandle.write('%s\n' % item)
代码的下一部分将之前标记化的文本去除停用词,并将结果保存到输出仓库中的no_stopwords.txt文件中。停用词是指包括冠词、代词等常用词,这些词对文本的价值较小,可以忽略,以节省处理时间:
stopwords = stopwords.words("english")
no_stopwords = []
for word in tokens:
if not word in stopwords:
no_stopwords.append(word)
appendFile = open('/pfs/out/no_stopwords.txt', 'a', encoding='utf-8')
appendFile.write(word)
appendFile.write("\n")
appendFile.close()
代码的下一部分移除已经进行过分词并去除停用词的文本中的标点符号。代码将结果保存到一个名为no_punctuation.txt的单独文件中:
no_punctuation = []
for word in no_stopwords:
if word.isalpha():
no_punctuation.append(word)
appendFile = open('/pfs/out/no_punctuation.txt', 'a', encoding='utf-8')
appendFile.write(word)
appendFile.write("\n")
appendFile.close()
接下来是词干提取。grouping和grouped会被简化为group。有时,这种技术可能被认为过于激进,可以使用词形还原来代替。词干化后的输出会保存到stemmed.txt:
port_stem = PorterStemmer()
stemmed = []
for word in no_punctuation:
stemmed_word = port_stem.stem(word)
stemmed.append(stemmed_word)
appendFile = open('/pfs/out/stemmed.txt', 'a', encoding='utf-8')
appendFile.write(stemmed_word)
appendFile.write("\n")
appendFile.close()
脚本的最后一部分是词形还原,它使用 NLTK 的 WordNet Lemmatizer 数据库对已经标记化且去除了停用词和标点符号的文本进行词形还原。最后一段代码将结果保存到lematized.txt文件中。我们将在下一个管道中使用该文件:
lemmatizer = WordNetLemmatizer()
lemmatized = []
for word in no_punctuation:
l_text = lemmatizer.lemmatize(word)
lemmatized.append(l_text)
appendFile = open('/pfs/out/lematized.txt', 'a', encoding='utf-8')
appendFile.write(l_text)
appendFile.write("\n")
appendFile.close()
现在我们知道了管道的功能,让我们来创建它。
要创建data-clean.py管道,请完成以下步骤:
-
打开终端并验证 Pachyderm 是否正常运行:
pachctl version
系统输出如下:
COMPONENT VERSION
pachctl 2.0.0
pachd 2.0.0
-
创建数据仓库:
pachctl create repo data -
验证数据仓库是否已创建:
pachctl list repo
系统输出如下:
NAME CREATED SIZE (MASTER) DESCRIPTION
data 10 seconds ago ≤ 0B
-
从你存放
data.txt文件的目录,将其放入数据仓库:pachctl put file -f data.txt data@master
系统输出如下:
data.txt 49.00b / 49.00 b [==============] 0s 0.00 b/s
该文件只有一行——一个指向古腾堡网站上《沉睡山庄的传说》文本的链接:www.gutenberg.org/files/41/41-h/41-h.htm。
-
检查文件是否已放入具有
file类型的仓库:pachctl list file data@master
系统输出如下:
NAME TYPE SIZE
/data.txt file 49B
-
创建
data-clean流水线:pachctl create pipeline -f data-clean.yaml
不会返回任何输出。
-
检查流水线是否已创建并且开始运行:
pachctl list pipeline
系统输出如下:
NAME VERSION INPUT CREATED STATE / LAST JOB DESCRIPTION
data-clean 1 data:/data.txt 4 seconds ago running / - A pipeline that tokenizes the text.
-
大约一分钟后,流水线应完成运行并将结果上传到输出仓库。请检查仓库:
pachctl list repo
你应该能看到以下输出:
NAME CREATED SIZE (MASTER) DESCRIPTION
data-clean 15 seconds ago ≤ 315.8KiB Output repo for pipeline data-clean.
data 1 minute ago ≤ 49B
如你所见,Pachyderm 自动创建了一个名为data-clean的输出仓库,并将 315.8 KiB 的数据上传到该仓库的主分支。
-
让我们列出仓库中的文件:
pachctl list file data-clean@master
系统输出如下:
NAME TYPE SIZE
/lemmatized.txt file 42.25KiB
/no_punctuation.txt file 42.99KiB
/no_stopwords.txt file 47.88KiB
/stemmed.txt file 38.01KiB
/text.txt file 75.18KiB
/tokens.txt file 69.54KiB
-
你可以看到,流水线已经将六个文件上传到输出仓库。我们故意将它们保存在不同的文件中,这样你可以看到它们之间的差异。你可以查看每个文件的内容并进行比较。例如,在 macOS 上打开
lemmatized.txt文件,可以运行以下命令:pachctl get file data-clean@master:/lemmatized.txt | open -f -a TextEdit.app
你应该能看到以下输出:

图 8.3 – 词形还原的单词
在本节中,我们已经创建了一个清理文本的流水线。接下来的章节,我们将创建下一个流水线,应用 POS 标签到我们的词形还原文本。
创建 POS 标注流水线
POS 标注是一种 NLP 技术,它为每个单词标记相关的词性。这个过程在许多 NLP 问题中都非常有用,比如文本歧义消解和文本转语音。
对于这项任务,我们使用了spaCy,这是一款免费的库,能够执行 POS 标注、命名实体识别(NER)等任务。例如,假设你有如下句子:
任何快乐的人都会让别人也感到快乐。
下面是使用 spaCy 进行 POS 标注的示例:

图 8.4 – POS 标注示例
我们将使用 spaCy 从data-clean流水线中找到我们词形还原文本的 POS 标签。
下面是我们 POS 标注流水线规范的样子:
---
pipeline:
name: pos-tag
description: A pipeline that performs POS tagging.
input:
pfs:
glob: "/lemmatized.txt"
repo: data-clean
transform:
cmd:
- python3
- "/pos-tag.py"
image: svekars/nlp-example:1.0
该流水线执行以下操作:
-
从
data-clean仓库获取lemmatized.txt文件 -
使用
svekars/nlp-example:1.0Docker 镜像 -
运行
pos-tag.py脚本处理我们的词形还原文本 -
输出一张表格,其中包含在
pos_table.txt文件中找到的所有 POS 标签,另有一份包含每种 POS 标签总数的文件pos_number.txt,并创建一个依赖关系图,保存为pos-tag-dependency.svg文件
现在我们已经回顾了流水线的工作内容,接下来让我们看看pos-tag.py脚本。
该脚本导入了以下组件和库:
import spacy
import en_core_web_sm
from spacy import displacy
import IPython
from pathlib import Path
import spacy.attrs
from contextlib import redirect_stdout
我们需要spacy及其模块来执行词性标注、统计它们并可视化结果。我们导入en_core_web_sm预训练的 spaCy 模型来完成标注任务。我们需要 IPython 作为 spaCy 的依赖。最后,我们使用pathlib和redirect_stdout来保存结果。
代码的第一部分导入了一个名为en_core_web_sm的预训练 spaCy 模型。词性标注要求你使用预训练模型或自定义模型。en_core_web_sm模型在词性标注方面表现良好。因此,我们将直接使用它。然后,脚本打开我们的lematized.txt文件,对文件中的所有单词进行词性标注,并将结果输出到pos-table.txt文件:
sp = spacy.load('en_core_web_sm')
textfile = sp(open('pfs/data-clean/lematized.txt', "r", encoding='utf-8').read())
with open('/pfs/out/pos-table.txt', 'w') as f:
with redirect_stdout(f):
for word in textfile:
print(f'{word.text:{12}} {word.pos_:{10}} {word.tag_:{8}} {spacy.explain(word.tag_)}')
代码的下一部分统计处理过的文本中每个标签的数量,并将结果输出到pos-number.txt文件:
with open('/pfs/out/pos-number.txt', 'w') as file:
with redirect_stdout(file):
count_tags = textfile.count_by(spacy.attrs.IDS['POS'])
for i, count in count_tags.items():
tags = textfile.vocab[i].text
print(tags, count)
最后,脚本的最后部分生成一个依赖图,并将其保存为 SVG 图像pos-tag-dependency.svg:
image = displacy.render(textfile, style='dep', options={"compact": True, "distance": 70})
f = open('/pfs/out/pos-tag-dependency.svg', "w")
f.write(image)
f.close()
现在,让我们创建我们的管道。
要创建一个词性标注管道,请执行以下操作:
-
打开你的终端并验证 Pachyderm 是否已启动并运行:
pachctl version
你应该看到以下输出:
COMPONENT VERSION
pachctl 2.0.0
pachd 2.0.0
-
创建词性标注管道:
pachctl create pipeline -f pos-tag.yaml
没有返回系统输出。
-
检查管道是否已创建并正在运行:
pachctl list pipeline
这是此命令返回的输出:
NAME VERSION INPUT CREATED STATE / LAST JOB DESCRIPTION
pos-tag 1 data-clean:/lemmatized.txt 2 seconds ago running / - A pipeline that performs POS tagging.
data-clean 1 data:/data.txt 1 minute ago running / success A pipeline that tokenizes the text.
-
当管道运行完成后,检查输出仓库:
pachctl list repo
这个命令返回以下输出:
NAME CREATED SIZE (MASTER) DESCRIPTION
pos-tag 22 seconds ago ≤ 10.82MiB Output repo for pipeline pos-tag.
data-clean 2 minutes ago ≤ 315.8KiB Output repo for pipeline data-clean.
data 3 minutes ago ≤ 49B
Pachyderm 创建了一个名为pos-tag的输出仓库,并将 10.82 MiB 文件上传到该仓库的主分支。
-
现在,让我们查看上传到输出仓库的文件:
pachctl list file pos-tag@master
这个命令返回以下系统输出:
NAME TYPE SIZE
/pos-number.txt file 132B
/pos-table.txt file 564.1KiB
/pos-tag-dependency.svg file 10.27MiB
-
让我们看看我们文本中每个标签的数量:
pachctl get file pos-tag@master:/pos-number.txt
你应该看到以下输出:
ADP 154
SPACE 6291
NOUN 3110
NUM 67
ADJ 789
PROPN 346
VERB 1053
ADV 374
DET 98
AUX 69
PRON 130
PART 9
SCONJ 59
CCONJ 15
INTJ 7
X 11
-
最后,让我们看看依赖图。如果你使用的是 macOS,请运行以下命令:
pachctl get file pos-tag@master:/pos-tag-dependency.svg > pos-tag-dependency.svg | open -f pos-tag-dependency.svg -a "Google Chrome"
Google Chrome 打开文件:

图 8.5 – 词性依赖图
重要提示
你可能需要在浏览器中向下滚动才能看到图表。由于我们对整本书进行了词性标注,这个图表非常长。你需要横向滚动才能查看完整内容。
在本节中,我们使用 Pachyderm 和 spaCy 配置了一个词性标注管道,并通过依赖图进行了可视化。接下来,我们将配置一个命名实体识别(NER)管道,帮助我们找到故事中的主要人物。
创建命名实体识别(NER)管道
命名实体识别(NER)是一种信息提取技术,它能够识别文本中的实体,并将它们归类为特定类别,如人物、地点和组织。例如,假设我们有以下短语:
Snap Inc.宣布 2021 年第一季度财务结果
如果你对这个短语使用 spaCy 的en_core_web_lg模型,你将得到以下结果:
Snap Inc. - 0 - 9 - ORG - Companies, agencies, institutions, etc.
First Quarter 2021 - 20 - 38 - DATE - Absolute or relative dates or periods
名字识别可以在多种任务中派上用场。在本节中,我们将使用它来提取《沉睡谷传说》中的主要人物。
这是我们 NER 管道规范的样子:
---
pipeline:
name: ner
description: A NER pipeline
input:
pfs:
glob: "/text.txt"
repo: data-clean
transform:
cmd:
- python3
- "/ner.py"
image: svekars/nlp-example:1.0
这个管道执行以下操作:
-
从
data-clean仓库获取The Legend of Sleepy Hollow的原始文本 -
使用
svekars/nlp-example:1.0Docker 镜像 -
运行
ner.py脚本 -
将结果输出到
ner仓库
现在,让我们看看ner.py脚本的功能。以下是脚本导入的组件列表:
import spacy
from spacy import displacy
from contextlib import redirect_stdout
我们需要spacy来执行 NER 任务,displacy模块用于可视化结果。redirect_stdout是一种将打印输出重定向到文件的便捷方法。
其余的代码导入了 spaCy 的预训练模型en_core_web_lg。这个模型似乎在 NER 任务上的表现优于我们在 POS 标注管道中使用的模型。接着,脚本从data-clean仓库中的text.txt文件中获取原始文本,并执行 NER 任务:
sp = spacy.load("en_core_web_lg")
def display_entities(text):
with open ('/pfs/out/ner-list.txt', 'w') as f:
with redirect_stdout(f):
if text.ents:
for i in text.ents:
print(i.text+' - '+str(i.start_char)+' - '+str(i.end_char)+' - '+i.label_+' - '+str(spacy.explain(i.label_)))
text = sp(open('/pfs/data-clean/text.txt', "r", encoding='utf-8').read())
display_entities(text)
最后,脚本使用displacy可视化结果并将其保存为 HTML 格式:
with open ('/pfs/out/ner-labels.html', 'w') as f:
with redirect_stdout(f):
for i in text.ents:
html=displacy.render(text, style="ent", page=True)
print(html)
现在我们知道了脚本的功能,接下来我们来创建管道。
要创建 NER 管道,完成以下步骤:
-
打开终端,验证 Pachyderm 是否已启动并正在运行:
pachctl version
此命令返回以下输出:
COMPONENT VERSION
pachctl 2.0.0
pachd 2.0.0
-
创建 POS 标注管道:
pachctl create pipeline -f ner.yaml
没有返回系统输出。
-
检查管道是否创建并已开始运行:
pachctl list pipeline
你应该会看到以下输出:
NAME VERSION INPUT CREATED STATE / LAST JOB DESCRIPTION
ner 1 data-clean:/text.txt 5 seconds ago running / running A NER pipeline
pos-tag 1 data-clean:/lematized.txt 1 minutes ago running / success A pipeline that performs POS tagging.
data-clean 1 data:/data.txt 2 minutes ago running / success A pipeline that tokenizes the text.
-
当管道运行完毕后,检查输出仓库:
pachctl list repo
该命令返回以下系统输出:
NAME CREATED SIZE (MASTER) DESCRIPTION
ner 36 seconds ago ≤ 43.49MiB Output repo for pipeline ner.
pos-tag 2 minutes ago ≤ 10.82MiB Output repo for pipeline pos-tag.
data-clean 3 minutes ago ≤ 315.8KiB Output repo for pipeline data-clean.
data 4 minutes ago ≤ 49B
Pachyderm 创建了一个名为ner的输出仓库,并上传了 43.49 MiB 的数据到主分支。
-
让我们看看上传到输出仓库的文件:
pachctl list file ner@master
返回以下输出:
NAME TYPE SIZE
/ner-labels.html file 43.47MiB
/ner-list.txt file 19.36KiB
该仓库有两个文件。一个是文件中找到的所有实体的列表,另一个是所有实体的可视化结果。
-
将
ner-list.txt文件的前 10 行打印到终端:pachctl get file ner@master:/ner-list.txt | awk 'FNR <= 10'
此命令返回以下输出:
one - 36 - 39 - CARDINAL - Numerals that do not fall under another type
Hudson - 108 - 114 - LOC - Non-GPE locations, mountain ranges, bodies of water
Dutch - 186 - 191 - NORP - Nationalities or religious or political groups
the Tappan Zee - 203 - 217 - EVENT - Named hurricanes, battles, wars, sports events, etc.
St. Nicholas - 303 - 315 - ORG - Companies, agencies, institutions, etc.
Greensburgh - 417 - 428 - PERSON - People, including fictional
Tarry Town - 498 - 508 - GPE - Countries, cities, states
former days - 547 - 558 - DATE - Absolute or relative dates or periods
about two miles - 891 - 906 - QUANTITY - Measurements, as of weight or distance
first - 1330 - 1335 - ORDINAL - "first", "second", etc. NUM 67
如你所见,NER 模型已经识别了文本中的许多实体。让我们打开 HTML 文件,查看所有实体。
-
打开 HTML 文件:
pachctl get file ner@master:/ner-labels.html > ner-labels.html | open -f ner-labels.html -a "Google Chrome"
文件将在 Google Chrome 中打开:

图 8.6 – NER 标签
你可以看到,spaCy 模型已经正确地识别了文本中的许多实体。然而,如果你开始浏览,你会注意到它遗漏了一些实体。例如,在某些情况下,它没有将Headless Horseman标记为PERSON。这是预训练模型的一个已知准确性问题。在下一节中,我们将通过重新训练模型来修正这个问题,以便使用这些实体。
重新训练 NER 模型
NER(命名实体识别)管道结果的不准确性是一个常见问题。解决这个问题的唯一方法是重训练现有模型,或者从头开始完全训练一个新的模型。从头训练一个模型是一个既困难又耗时的操作。在我们的案例中,我们不一定需要训练一个完全新的模型,而是可以重训练现有模型,以理解缺失的上下文。为了完成这个任务,我们将把训练数据放入 data-clean 仓库,创建一个训练管道在该数据上进行训练,将模型保存到输出仓库中,然后再次运行重训练后的模型对原始文本进行处理。
在 Pachyderm 的术语中,这意味着我们将创建两个管道:
-
第一个管道,名为
retrain,将训练我们的模型并将新模型输出到train输出仓库。 -
第二个管道,名为
my-model,将使用新模型分析我们的文本,并将结果上传到my-model仓库。
现在,让我们创建重训练管道。
创建重训练管道
对于这个管道,我们将创建以下管道规范:
---
pipeline:
name: retrain
description: A pipeline that retrains the NER model.
input:
pfs:
glob: "/training-data.json"
repo: data
transform:
cmd:
- python3
- "/ner-improved.py"
image: svekars/nlp-example:1.0
这个管道采用包含我们训练数据的 training-data.json 文件,并运行 ner-improved.py 脚本以改进现有模型。结果将保存到 retrain 仓库中。对于这个示例,我们不需要太多的训练实例,但在实际使用中,你可能需要成百上千的示例来提高模型的准确性。
以下是 ner-improved.py 脚本导入的组件列表:
import spacy
import random
from spacy.util import minibatch
from spacy.training import Example
from contextlib import redirect_stdout
import simplejson as json
我们需要 spacy 库中的 minibatch 和 Example.from_dict 方法来训练模型。我们使用 random 来打乱文件顺序,以便更好地训练。需要 simplejson Python 解码器来读取 JSON 格式的训练数据文件,并且需要 redirect_stdout 来保存输出结果。
脚本的下一部分加载 spaCy 模型,读取训练数据文件,并打开 spaCy NER 管道:
nlp=spacy.load("en_core_web_lg")
ner=nlp.get_pipe("ner")
data = open("/pfs/data/training-data.json")
data = json.loads(data.read())
这部分代码使用了一个优化器,它执行梯度下降计算。然后,脚本指定只需训练 NER 管道,忽略其他管道。接下来的 for 循环执行实际的训练,更新模型,并打印损失值。我们将训练模型 30 次:
optimizer = nlp.create_optimizer()
other_pipes = [p for p in nlp.pipe_names if p != "ner"]
with nlp.disable_pipes(*other_pipes):
for i in range(30):
random.shuffle(data)
losses = {}
for text, annotations in data:
doc = nlp.make_doc(text)
example = Example.from_dict(doc, annotations)
nlp.update([example], drop=0.1, sgd=optimizer, losses=losses)
print(losses)
脚本的最后一部分测试重训练管道在测试文本上的效果,并将结果输出到 ner-improved.txt 文件。重训练后的模型将使用 pickle.dump 保存在 output 仓库中的 ner-improved-model.p 文件目录中:
test_text = 'Headless Horseman came to see Ichabod Crane.'
doc = nlp(test_text)
with open ('/pfs/out/ner-improved.txt', 'w') as f:
with redirect_stdout(f):
for i in doc.ents:
print(i.label_, " -- ", i.text)
pickle.dump(nlp, open('/pfs/out/ner-improved-model.p', 'wb'))
现在,让我们创建管道:
-
打开终端并验证 Pachyderm 是否正在运行:
pachctl version
系统输出如下:
COMPONENT VERSION
pachctl 2.0.0
pachd 2.0.0
-
将
training-data.json放入数据仓库:pachctl put file -f training-data.json data@master -
创建重训练管道:
pachctl create pipeline -f retrain.yaml
没有系统输出返回。
-
检查管道是否已创建,并且正在启动或运行:
pachctl list pipeline
系统输出如下:
NAME VERSION INPUT CREATED STATE / LAST JOB DESCRIPTION
retrain 1 data:/training-data.json About a minute ago running / success A pipeline that retrains the NER model.
ner 1 data-clean:/text.txt 2 minutes ago running / success A NER pipeline
pos-tag 1 data-clean:/lemmatized.txt 3 minutes ago running / success A pipeline that performs POS tagging.
data-clean 1 data:/data.txt 5 minutes ago running / success A pipeline that tokenizes the text.
-
一段时间后,检查输出仓库:
pachctl list repo
系统输出如下:
NAME CREATED SIZE (MASTER) DESCRIPTION
retrain About a minute ago ≤ 821.8MiB Output repo for pipeline retrain.
ner 2 minutes ago ≤ 43.49MiB Output repo for pipeline ner.
pos-tag 3 minutes ago ≤ 10.82MiB Output repo for pipeline pos-tag.
data-clean 5 minutes ago ≤ 315.8KiB Output repo for pipeline data-clean.
data 6 minutes ago ≤ 205B
如你所见,Pachyderm 将 816.7 MiB 上传到 retrain 仓库。这是我们重新训练的模型,占用了这么多空间。
-
列出
retrain仓库中的文件:pachctl list file retrain@master
系统输出如下:
NAME TYPE SIZE
/ner-improved-model.p file 821.8MiB
/ner-improved.txt file 56B
-
查看
ner-improved.txt文件,它应该包含重新训练的模型对测试文本运行的结果:pachctl get file retrain@master:/ner-improved.txt
系统输出如下:
PERSON -- Headless Horseman
PERSON -- Ichabod Crane
很棒!Headless Horseman 和 Ichabod Crane 被定义为 PERSON。
现在我们已经重新训练了模型,接下来让我们部署最终的流水线,它将提供改进后的 NER,并将故事中的所有人物输出到一个文件中。
部署重新训练的流水线
我们的重新训练流水线需要是一个跨流水线,以便将我们新的重新训练模型与文本结合起来:
---
pipeline:
name: my-model
description: A retrained NER pipeline
input:
cross:
- pfs:
repo: data-clean
glob: "/text.txt"
- pfs:
repo: retrain
glob: "/ner-improved-model.p"
transform:
cmd:
- python3
- "/ner-my-model.py"
image: svekars/nlp-example:1.0
这个流水线将使用与原始 NER 流水线相同的 text.txt 文件,并将我们重新训练的模型与该文本的交叉产品生成。它将结果输出到 my-model 仓库中。生成的文件将包含一个改进了 NER 标记的 HTML 文件和一个包含 The Legend of Sleepy Hollow 中人物列表的文本文件。
ner-my-model.py 与原始的 ner.py 脚本非常相似,主要有以下区别:
它通过使用 pickle.load 而不是原始的 spaCy 模型来加载我们的改进模型:
nlp = pickle.load(open('/pfs/retrain/ner-improved-model.p', 'rb')))
它统计每个 /pfs/out/person-label-count.txt 文件中实例的总数:
with open ('/pfs/out/person-label-count.txt', 'w') as f:
with redirect_stdout(f):
person_label=[]
for i in text.ents:
if i.label_ =='PERSON':
person_label.append(i.text)
count = Counter(person_label)
for key, counter in count.most_common():
它将 HTML 可视化保存到 ner-improved-labels.html 文件中。它将所有实体保存到 ner-improved-list.txt 文件中,该文件位于 my-model 仓库。
让我们创建最终的流水线:
-
打开终端并确认 Pachyderm 正在运行:
pachctl version
系统输出如下:
COMPONENT VERSION
pachctl 2.0.0
pachd 2.0.0
-
创建
my-model流水线:pachctl create pipeline -f my-model.yaml
这个命令不会返回任何输出。
-
检查流水线是否已创建并正在启动或运行:
pachctl list pipeline
系统输出如下:
NAME VERSION INPUT CREATED STATE / LAST JOB DESCRIPTION
my-model 1 (data-clean:/text.txt ⨯ retrain:/ner-improved-model.p) 6 seconds ago running / running A retrained NER pipeline
retrain 1 data:/training-data.json 9 minutes ago running / success A pipeline that retrains the NER model.
ner 1 data-clean:/text.txt 10 minutes ago running / success A NER pipeline
pos-tag 1 data-clean:/lemmatized.txt 11 minutes ago running / success A pipeline that performs POS tagging.
data-clean 1 data:/data.txt 13 minutes ago running / success A pipeline that tokenizes the text.
请注意,my-model 流水线正在启动。它不同于我们为此示例创建的所有其他流水线。因为我们将模型保存在 retrain 仓库中,并且需要将其与数据仓库中的文本结合,所以标准流水线无法完成这个任务。为了实现这一目标,我们创建了一个跨流水线,将两个输入结合起来。
-
让我们检查输出仓库:
pachctl list repo
系统输出如下:
NAME CREATED SIZE (MASTER) DESCRIPTION
my-model About a minute ago ≤ 31.44MiB Output repo for pipeline my-model.
retrain 10 minutes ago ≤ 821.8MiB Output repo for pipeline retrain.
ner 11 minutes ago ≤ 43.49MiB Output repo for pipeline ner.
pos-tag 12 minutes ago ≤ 10.82MiB Output repo for pipeline pos-tag.
data-clean 14 minutes ago ≤ 315.8KiB Output repo for pipeline data-clean.
data 15 minutes ago ≤ 205B
Pachyderm 将 26.15 MiB 上传到 my-model 仓库。这是我们计算的结果。
-
列出
my-model仓库中的文件:pachctl list file my-model@master
系统输出如下:
NAME TYPE SIZE
/ner-improved-labels.html file 26.14MiB
/ner-improved-list.txt file 13.43KiB
/person-label-count.txt file 654B
-
查看
person-label-count.txt文件,它应该提供每个独特 PERSON 实例的总计数:pachctl get file my-model@master:/person-label-count.txt | awk 'FNR <= 15'
系统输出如下:
Ichabod: 35
Brom Bones: 9
Ichabod Crane: 8
Van Tassel: 5
Hans Van: 5
Galloping Hessian: 4
André: 4
Headless Horseman: 3
Brom: 3
Hans Van Ripper: 3
Brouwer: 3
Tarry Town: 2
Cotton Mather: 2
Mather: 2
Baltus Van: 2
如你所见,输出结果仍然不完全准确,因为我们看到 Ichabod 和 Ichabod Crane 分别出现。如果我们提供更多的训练数据,就能改善这些结果。不过,你已经能看到这个列表中最常出现的人物,并且可以理解 Ichabod Crane 很可能是这个故事的主要人物。
-
打开 HTML 文件以查看高亮版本的结果:
pachctl get file my-model@master:/ner-improved-labels.html > ner-improved-labels.html | open -f ner-labels.html -a "Google Chrome"
这结束了我们关于 spaCy NER 模型的实验。你可以添加更多的训练数据,看看在更多训练样本的情况下,准确度会如何提高。
现在,让我们清理我们的集群。
清理中
完成实验后,你可能想要清理集群,以便以全新安装开始下一个实验。要清理环境,请执行以下操作:
-
删除所有的管道和仓库:
pachctl delete pipeline –all && pachctl delete repo --all -
验证你的集群中没有仓库和管道:
pachctl list repo && pachctl list pipeline
你应该看到以下输出:
NAME CREATED SIZE (MASTER) DESCRIPTION
NAME VERSION INPUT CREATED STATE / LAST JOB DESCRIPTION
你已成功清理了你的集群。
总结
在本章中,我们学习了如何使用 NER 管道示例构建一个复杂的机器学习工作流。我们学习了如何使用 NLTK 库清理数据,如何进行词性标注(POS tagging),以及如何在 Pachyderm 中重新训练 spaCy 模型并输出结果以供预览。你可以做更多的操作,通过添加更多训练数据和调整模型训练参数,进一步提升 NER 的准确度。
在下一章中,我们将学习如何在 Pachyderm 中进行超参数调优,以预测房价为例。
进一步阅读
-
NLTK 文档:
www.nltk.org/ -
spaCy 文档:
spacy.io/api/doc -
睡谷的传说 在古腾堡项目网站上的链接:
www.gutenberg.org/files/41/41-h/41-h.htm
第九章:第九章:使用 Pachyderm 进行分布式超参数调优
在第八章中,创建端到端机器学习工作流,我们基于命名实体识别(NER)管道示例实现了一个端到端(E2E)机器学习(ML)工作流。这是一个多步骤的管道,包含许多计算阶段,包括数据清理、词性(POS)标注、模型训练,以及将新模型应用于不同数据。我们的目标是找出故事中的主要角色,这一点我们成功地实现了。
在本章中,我们将探讨可以实施的各种策略,以选择适用于机器学习问题的最佳参数。这个技术叫做超参数调优或优化。在本章的第二部分,我们将基于房价预测示例实现一个超参数调优管道。
本章包括以下主题:
-
审查超参数调优技术和策略
-
创建一个超参数调优管道在 Pachyderm 中
技术要求
本章要求您安装并配置特定组件。
对于本地 macOS 安装,您应具备以下条件:
-
macOS Mojave、Catalina、Big Sur 或更高版本
-
Docker Desktop for Mac 10.14
-
minikubev1.9.0 或更高版本 -
pachctl2.0.0 或更高版本 -
Pachyderm 2.0.0 或更高版本
对于本地 Windows 安装,您应具备以下条件:
-
Windows Pro 64 位 v10 或更高版本
-
Windows 子系统 for Linux(WSL)2 或更高版本
-
Microsoft PowerShell v6.2.1 或更高版本
-
Hyper-V
-
minikubev1.9.0 或更高版本 -
kubectlv1.18 或更高版本 -
pachctl2.0.0 或更高版本 -
Pachyderm 2.0.0 或更高版本
对于Amazon 弹性 Kubernetes 服务(Amazon EKS)安装,您应具备以下条件:
-
kubectlv.18 或更高版本 -
eksctl -
aws-iam-authenticator -
pachctl2.0.0 或更高版本 -
Pachyderm 2.0.0 或更高版本
对于 Microsoft Azure 云安装,您应该具备以下条件:
-
kubectlv.18 或更高版本 -
Azure 命令行接口(Azure CLI)
-
pachctl2.0.0 或更高版本 -
Pachyderm 2.0.0 或更高版本
-
jq1.5 或更高版本
对于Google Kubernetes 引擎(GKE)云安装,您应具备以下条件:
-
Google Cloud 软件开发工具包(SDK)v124.0.0 或更高版本
-
kubectlv.18 或更高版本 -
pachctl2.0.0 或更高版本 -
Pachyderm 2.0.0 或更高版本
要运行本章中的管道,您不需要任何特殊硬件。如果您是在本地运行 Pachyderm 集群,任何现代笔记本电脑都应该支持本节中的所有操作。如果您在云平台上运行 Pachyderm,您将需要有一个持久卷(PV)。有关更多细节,请参见第五章,在云平台上安装 Pachyderm。
本章中描述的所有脚本和数据都可以在github.com/PacktPublishing/Reproducible-Data-Science-with-Pachyderm/tree/main/Chapter09-Distributed-Hyperparameter-Tuning-with-Pachyderm找到。
现在我们已经回顾了本章的技术要求,让我们更详细地了解一下我们的工作流。
回顾超参数调优技术和策略
超参数调优(hyperparameter tuning)或超参数优化(hyperparameter optimization)是一种机器学习专业人员用来确定最佳参数以解决特定机器学习问题的技术。在不同的问题中,你需要调节不同类型的参数,比如神经网络中的权重,随机森林算法中的树的数量,或者模型的学习率。最终,选择最佳参数有助于你确定最适合解决问题的方法。数据科学家需要理解他们所使用算法中的可调参数,以便正确地优化它们。
有许多机器学习算法可以帮助解决超参数优化问题。让我们回顾一下最常见的几种。
网格搜索
网格搜索是最简单的算法,有时被称为暴力搜索方法用于超参数优化。该方法计算超参数的最佳值。
在网格搜索中,你通常会定义诸如学习率、丢弃率或批次大小等超参数。然后,定义一个可能的值范围。接下来,算法运行并搜索所有可能的配置。
网格搜索的一个缺点是它计算开销大,通常只用于较小的超参数集。
尽管如此,网格搜索(Grid search)仍然是一种流行的超参数调优算法,也是最容易理解的。
以下图表展示了网格搜索:

图 9.1 – 网格搜索
现在,让我们来看看另一种超参数优化技术——随机搜索。
随机搜索
随机搜索与网格搜索相似,但不同之处在于,它不是检查所有可能的组合,而是随机选择它们,这通常能带来更好的性能并减少计算时间和资源。在许多情况下,随机搜索比网格搜索方法更快地找到最佳组合。
该图展示了随机搜索:

图 9.2 – 随机搜索
现在我们知道了随机搜索(Random search)和网格搜索(Grid search)方法,接下来我们将了解一种稍微复杂一点的超参数调优方法——贝叶斯优化。
贝叶斯优化
贝叶斯优化是一种超参数调整技术,用于找到一个函数的最小值。贝叶斯优化与网格搜索/随机搜索的主要区别在于它会跟踪之前的迭代和评估结果,因此使用概率(P)来预测最佳组合。
使用贝叶斯优化训练的模型在数据更多的情况下能提供更好的结果。由于它考虑了过去的结果,像这样的模型可以通过较少的迭代找到最佳结果。基于之前的迭代,贝叶斯优化构建了一个更接近现实的后验模型。
该图示范了贝叶斯优化的概念:

图 9.3 – 贝叶斯优化
我们已经了解了三种主要的超参数优化技术。虽然还有更多方法,但这三种似乎是最受欢迎和广泛使用的。现在,让我们来看看可以用于确定模型表现的模型评估指标。由于我们将在本章后面讨论的问题是回归问题,我们将只考虑回归评估指标。
回归评估指标
仅选择正确的算法只是成功的一半。我们需要使用一个评估指标来确定模型的表现。评估指标可以应用于各种参数,以确定最佳参数。它们还可以应用于多个算法,以便进行比较并为进一步分析提供依据。
由于房价预测示例是回归问题,我们将只考虑回归评估指标。最常见的评估指标包括以下几种:
-
R 平方(R2)
-
均方误差(MSE)
-
平均绝对误差(MAE)
这些指标是已知的统计方法,用于评估性能。
R2
R2 是一个用于统计学中的评估指标,用于确定因变量的方差或数据与回归线的接近程度。该参数以百分比形式衡量。如果你得到 100%的 R2 值,意味着数据完美地拟合回归模型。然而,其他值也是可以接受的,包括 75%、50%等等。
有许多方法可以用公式表示 R2,但最简单的表示方式如下:

如果你不太熟悉数学,不必太担心,因为在我们的代码中,我们使用scikit-learn模块来计算 R2。
现在你对 R2 有了大致了解,让我们学习另一种评估指标——MSE。
MSE
MSE 是一种评估指标,用于估算预测值与观察值之间的差异。MSE 受到离群值的影响很大,离群值指的是超出标准范围的值。因此,在评估模型之前,你必须去除离群值。
MSE 值越低,结果越接近真实值。
例如,如果你有一个根据服务年限预测薪资的模型,模型的 MSE 可能是 200,这意味着预测值比实际值美元(USD)高出 200 美元。根据样本大小、整体规模和期望的精度,这个数字可能具有不同的重要性。
以下公式用于计算 MSE:

以下值用于该公式:
-
n:样本大小
-
observed:实际值
-
predicted:模型预测的值
与 R2 一样,不必过于担心公式,因为我们将使用 scikit-learn 的 MSE 模块来计算 MSE。
现在,让我们了解 MAE。
MAE
MAE 是另一种常用于回归模型的评估指标。它计算模型中的总误差平均值,或者实际值与预测值之间的绝对差异。如果我们要用最简单的公式表示 MAE,它的形式如下:

这个指标仅供参考。我们在计算中不会使用它。但是,如果你愿意,也可以尝试使用 scikit-learn 的 MAE 模块来计算。
除了这些指标外,还有许多其他指标可以帮助你评估模型,包括根均方误差(RMSE)和调整后的 R2。然而,我们之前提到的这些是最常用的,也是最容易理解的。
现在我们已经了解了方法论、评估指标以及我们将用来配置 Pachyderm 中超参数调优的算法,让我们回顾实际的示例、模型、代码和管道规范。在下一节结束时,我们将拥有一个在 Pachyderm 中工作的超参数调优示例。
在 Pachyderm 中创建超参数调优管道
在本节中,我们将探讨超参数调优管道,并将在 Pachyderm 中创建所有必要的属性,以运行我们的示例。
示例概述
房价预测挑战是超参数调优优化的经典机器学习示例之一。它听起来可能并不复杂,甚至可以根据你的经验进行简单预测。很可能,你对自己所住的地区相当了解,可以根据房屋的平方英尺数、房间数量、相邻土地面积等参数估算房价。
这些信息可以以二维(2D)数组或表格的形式表示,包含上述参数。以下是此类表格的示例:

图 9.4 – 示例房屋数据
基于这些信息,你可以仅通过观察这些数字来预测一栋具有相似特征的房子的价格,而无需使用任何机器学习模型。
但想象一下,你所拥有的所有数据只是一个逗号分隔值(CSV)文件,里面包含成千上万行和 60 多个列。你对这个区域一无所知,而且你从未住在那里。想象一下,你希望根据不断变化的数据,持续预测房价。此时,创建一个高效的机器学习模型就显得非常有用。
在我们的示例中,我们将使用一个免费的数据集,train.csv版本的数据集,因为我们将对其进行修改以清理数据。
train.csv数据集包括81列和1,461行。你可以查看data_description.txt文件来回顾列的描述。列中包含了影响房价的各种参数。每一行代表一个房屋销售实例,并带有一个具体的销售价格。
这是数据集中的一个摘录:

图 9.5 – 房屋数据集摘录
我们将尝试创建一个模型,利用我们的训练数据对其进行训练,预测房价,并通过使用我们在前一节中讨论的 R2 和 MSE 评估指标来评估模型的性能。
以下图表展示了我们的模型:

图 9.6 – 超参数调优管道
现在我们已经对管道有了一个基本的了解,让我们更详细地回顾一下管道工作流的每个步骤。
创建探索性分析管道
我们的第一个管道探索了数据,并为我们提供了有关所用数据集的一些基本信息。以下是探索性分析管道的规范:
---
pipeline:
name: data-explore
description: A pipeline that performs exploratory analysis.
input:
pfs:
glob: "/*"
repo: data
transform:
cmd:
- python3
- "/data-explore.py"
image: svekars/hyperparameter-example:1.0
该管道从位于/*下的数据仓库中获取所有数据,并运行data-explore.py脚本。该管道使用hyperparameter-example:1.0 Docker 镜像。
让我们回顾一下data-explore.py脚本的作用。该脚本导入了以下组件:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
我们将使用pandas来操作 CSV 表格,并将其表示为DataFrame结构。pandas是一个开源的 Python 库,广泛应用于数据科学家进行数据操作,尤其是二维表格数据。
我们将使用之前章节中介绍过的matplotlib,结合seaborn库来可视化我们的计算结果。seaborn基于matplotlib,但提供了更复杂且视觉上更吸引人的图表。
data-explore.py脚本的第一部分从data仓库中读取housing-train.csv文件,并通过使用pandas.DataFrame.corr()方法计算数据集中所有列之间的相关性矩阵。代码接着创建了一个相关性矩阵的热图,并将其保存在管道输出仓库中。相关代码如下所示:
plt.subplots(figsize=(20,15))
data = pd.read_csv("/pfs/data/housing-train.csv", delimiter=',')
dataset = data.corr().round(2)
plt.subplots(figsize=(20,15))
my_plot = sns.heatmap(dataset, annot=True,cmap='YlGnBu', linecolor='white')
fig = my_plot.get_figure()
fig.savefig('/pfs/out/heatmap.png', dpi=400)
代码的第二部分保存列中数据对象的类型。通常,分析和处理数值数据与类别数据采用不同的方法,因此获取这些信息可能很重要。代码将这些信息保存到data-types.csv文件中,如下所示:
data_types = data.dtypes.to_frame('dtypes').reset_index()
data_types.to_csv('/pfs/out/data-types.csv', index=False)
脚本的第三部分检查缺失数据的列,创建一个包含缺失数据列百分比的表格,并将其保存为no-data.csv,如下代码片段所示:
cols_no_data = data.isnull().sum() / data.shape[0] * 100.00
no_data = pd.DataFrame({'Column': data.columns, 'Percentage Missing': cols_no_data})
no_data.sort_values(by=['Percentage Missing'], inplace=True, ascending=False)
header = ["Column", "Percentage Missing"]
no_data.to_csv('/pfs/out/no-data.csv', columns = header, index=False)
我们来创建这个管道,步骤如下:
-
通过执行以下命令,验证 Pachyderm 是否正常运行:
pachctl version
该命令返回以下输出(你的pachctl和pachd版本可能不同):
COMPONENT VERSION
pachctl 2.0.0
pachd 2.0.0
-
通过运行以下命令创建数据仓库:
pachctl create repo data
该命令不会返回任何输出。
-
通过运行以下命令,将
housing-train.csv文件移至data仓库的主分支:pachctl put file data@master -f housing-train.csv
系统响应应如下所示:
housing-train.csv 460.68KB / 460.68 KB [=========] 0s 0.00 b/s
-
通过运行以下命令,验证文件是否已以
file类型添加到仓库:pachctl list file data@master
系统响应应如下所示:
NAME TYPE SIZE
/housing-train.csv file 449.9KiB
-
通过使用
data-explore.yaml文件创建data-explore管道,步骤如下:pachctl create pipeline -f data-explore.yaml
该命令不会返回任何响应。
-
通过运行以下命令,验证管道是否已创建:
pachctl list pipeline
这是你应该看到的系统响应:
NAME VERSION INPUT CREATED STATE / LAST JOB DESC
data-explore 1 data:/* 34 seconds ago running / running A pipeline that performs exploratory data analysis.
等待管道运行完毕,并显示最后一个作业的success状态。
-
列出仓库,命令如下:
pachctl list repo
你应该看到data-explore管道已上传3.361MiB的数据到data-explore仓库,输出如下所示:
NAME CREATED SIZE (MASTER) DESCRIPTION
data-explore 46 seconds ago 3.361MiB Output repo for pipeline data-explore.
data 26 minutes ago 449.9KiB
-
通过运行以下命令,我们来探索仓库中的数据:
pachctl list file data-explore@master
你应该能看到以下三个文件:
NAME TYPE SIZE
/data-types.csv file 1.37KiB
/heatmap.png file 3.359MiB
/no-data.csv file 1.447KiB
-
我们来打开
/data-types.csv文件,如下所示:pachctl get file data-explore@master:/data-types.csv
文件包含每一列的数据类型,如下代码片段所示:
index,dtypes
Id,int64
MSSubClass,int64
MSZoning,object
LotFrontage,float64
...
-
通过运行以下命令,我们来查看
no-data.csv文件中的内容:pachctl get file data-explore@master:/no-data.csv
另外,你也可以在你的电脑上用应用程序打开该文件。例如,在 macOS 中,你可以在Numbers应用中打开它,如下所示:
pachctl get file data-explore@master:/no-data.csv | open -f -a "Numbers"
该文件包含有关列和这些列中缺失数据百分比的信息。这对于数据清理非常有用。一些列的缺失数据超过了 80%。这些列可以被删除,以避免干扰我们的计算。我们将在下一个管道中进行处理。以下是缺失数据大部分的列列表:

图 9.7 – 缺失数据的列
-
现在,通过运行以下命令,我们来查看热图:
pachctl get file data-explore@master:/heatmap.png | open -f -a "Preview.app"
你应该看到以下热图,它展示了数据集中所有列之间的相关性:

图 9.8 – 所有参数的热图
这个热图参数太多,难以阅读。但即便在这个热图上,我们也能看到有些参数对销售价格的影响大于其他参数。例如,看起来OverallQuality参数对价格的影响最大,还有GrLivArea参数(即大居住区)。我们将在下一个管道步骤中尝试将数据集缩小到这些参数。
我们已经探索了数据集并对数据有了基本了解。现在,让我们回顾一下下一个管道,它将根据我们的发现清理数据。
创建数据清理管道
我们的下一步是创建一个清理数据的管道。这个管道将根据上一部分的发现清理数据。以下是管道的规范:
---
pipeline:
name: data-clean
description: A pipeline that removes empty cells from the CSV.
input:
pfs:
glob: "/"
repo: data
transform:
cmd:
- python3
- "/data-clean.py"
image: svekars/hyperparameter-example:1.0
这是一个标准的 Pachyderm 管道,它从data仓库中获取数据,并对这些数据运行data-clean.py脚本。在这种情况下,数据是我们的housing-train.csv数据集。
让我们来看一下data-clean.py脚本。该脚本导入了以下组件:
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from pandas import Series
这些组件与data-explore管道中的组件相似。唯一新增的组件是pandas.Series,我们需要它来将数据保存到 CSV 文件中。
我们脚本的第一部分读取来自housing-train.csv数据集的数据,作为DataFrame。然后,我们删除那些有超过 40%缺失数据的列,并将被删除的列保存到col_drop.csv文件中,如下所示:
data = pd.read_csv("/pfs/data/housing-train.csv", delimiter=',')
col_drop = set(data.count()[data.count()<0.60*max(data.count())].index.tolist())
pd.Series(list(col_drop)).to_csv('/pfs/out/col_drop.csv', index=False)
接下来,我们创建一个新的相关矩阵,仅包括对SalePrice列影响系数为 0.5 或更大的参数。我们绘制一个新的热图,并将其保存在heatmap2.png文件中,如下所示:
data = data.drop((col_drop), axis=1)
corr = data.corr()
r_var = corr.SalePrice[(corr.SalePrice > 0.5)]
r_col = list(r_var.index.values)
new_corr = data[r_col].corr()
plt.subplots(figsize=(20,15))
my_plot2 = sns.heatmap(new_corr, annot=True,cmap='YlGnBu', linecolor='white')
fig = my_plot2.get_figure()
fig.savefig('/pfs/out/heatmap2.png', dpi=400)
最后,我们移除不属于新相关矩阵的列,并将它们保存在一个名为cleaned-data.csv的新数据集里,放在管道输出仓库中,如下所示:
new_data = data.loc[:, data.columns.intersection(r_col)]
new_data.to_csv('/pfs/out/cleaned-data.csv', index=True)
现在,让我们创建这个数据清理管道,如下所示:
-
通过执行以下命令验证 Pachyderm 是否正在运行:
pachctl version
这里是输出:
COMPONENT VERSION
pachctl 2.0.0
pachd 2.0.0
你使用的 Pachyderm 版本可能不同。
-
创建一个
data-clean管道,如下所示:pachctl create pipeline -f data-clean.yaml
没有系统响应返回。
-
通过运行以下命令,验证 Pachyderm 是否成功创建了管道:
pachctl list pipeline
这是你应该看到的系统响应:
NAME VERSION INPUT CREATED STATE / LAST JOB DESCRIPTION
data-clean 1 data:/ 6 seconds ago running / running A pipeline that removes empty cells from the CSV.
data-explore 1 data:/* 4 minutes ago running / success A pipeline that performs exploratory analysis.
你需要等待管道的状态变为success。
-
当管道成功运行完毕后,通过运行以下命令列出仓库:
pachctl list repo
你应该能看到data-clean管道添加了780.4KiB的数据,如下所示的输出所示:
NAME CREATED SIZE (MASTER) DESCRIPTION
data-clean 42 seconds ago ≤ 780.4KiB Output repo for pipeline data-clean.
data-explore 3 minutes ago ≤ 3.361MiB Output repo for pipeline data-explore.
data 12 minutes ago ≤ 449.9KiB
-
让我们通过运行以下命令查看仓库中的数据:
pachctl list file data-clean@master
输出应该如下所示:
NAME TYPE SIZE
/cleaned-data.csv file 67.14KiB
/col_drop.csv file 45B
/heatmap2.png file 713.2KiB
-
让我们通过运行以下命令查看被删除的列:
pachctl get file data-clean@master:/col_drop.csv
该文件包括每列的数据类型,正如我们在这里看到的:
0
PoolQC
Alley
FireplaceQu
MiscFeature
Fence
这些是那些有超过 40%空列的列。
-
我们还去除了新相关矩阵中映射的所有列,这些列的相关系数小于 0.5。运行以下命令查看我们的新相关矩阵:
pachctl get file data-clean@master:/heatmap2.png | open -f -a "Preview.app"
这是新的热图:

图 9.9 – 精细化热图
这个热图更有意义了。我们可以清晰地看到在确定房屋销售价格时最显著的参数。我们的数据集已被大幅度减少,仅剩 11 列,并已保存到新的cleaned-data.csv文件中。现在,这个策略可能并不适用于所有的用例——你可能决定保留更多的参数,以确保并检查是否在更多参数下模型表现更好。但就这个示例而言,这应该足够了。
现在我们已经清理了数据,还需要确保去除任何异常值或超出标准范围的参数。我们将在下一部分进行这个操作。
创建一个去除异常值的管道
我们的下一个管道将评估数据集中的异常值,并将其去除,以确保模型的表现不受影响。我们将再次使用标准的 Pachyderm 管道规范来实现这一目标。以下是管道规范:
---
pipeline:
name: remove-outliers
description: A pipeline that removes outliers from the dataset.
input:
pfs:
glob: "/"
repo: data-clean
transform:
cmd:
- python3
- "/outliers.py"
image: svekars/hyperparameter-example:1.0
该管道规范从data-clean代码库获取清理后的数据,并将outliers.py Python 脚本应用于这些数据。管道使用与前两个相同的 Docker 镜像。
outliers.py脚本导入了与我们前面管道步骤中的脚本相同的组件列表,包括seaborn、matplotlib和pandas。
脚本从cleaned-data.csv文件读取数据。然后,它创建一个直方图,显示数据集中的异常值,并将该直方图保存为histogram.png文件。接着,我们只保留中间范围内 50%的数据,并去除其余部分。我们创建另一个直方图,显示这些新数据。我们从数据集中删除数据并将其保存为一个名为removed-outliers-data.csv的新 CSV 文件。代码如下所示:
data = pd.read_csv("/pfs/data-clean/cleaned-data.csv", delimiter=',', encoding='utf-8')
my_plot=sns.boxplot(x=data['SalePrice'])
fig = my_plot.get_figure()
fig.savefig('/pfs/out/histogram.png', dpi=400)
q1 = data['SalePrice'].quantile(0.25)
q3 = data['SalePrice'].quantile(0.75)
iqr = q3-q1
lw = q1 - 1.5*iqr
uw = q3 + 1.5*iqr
dataset = data[(data['SalePrice']>lw)&(data['SalePrice']<uw)]
plt.figure(figsize=(20,10))
my_plot2 = sns.histplot(data=dataset, x="SalePrice", color="orange", element="poly")
fig = my_plot2.get_figure()
fig.savefig('/pfs/out/histogram-outliers.png', dpi=400)
dataset.to_csv('/pfs/out/removed-outliers-data.csv', index=True)
现在,让我们创建这个管道,步骤如下:
-
通过执行以下命令验证 Pachyderm 是否正常运行:
pachctl version
你应该得到类似以下的输出:
COMPONENT VERSION
pachctl 2.0.0
pachd 2.0.0
你的版本可能会有所不同。
-
创建一个
data-clean管道,步骤如下:pachctl create pipeline -f remove-outliers.yaml
这个命令没有返回任何输出。
-
通过运行以下命令检查管道是否已创建:
pachctl list pipeline
这是你应该看到的系统响应:
NAME VERSION INPUT CREATED STATE / LAST JOB DESCRIPTION
remove-outliers 1 data-clean:/ 5 seconds ago running / starting A pipeline that removes outliers from the dataset.
data-clean 1 data:/ 4 minutes ago running / success A pipeline that removes empty cells from the CSV.
data-explore 1 data:/* 8 minutes ago running / success A pipeline that performs exploratory analysis.
remove-outliers管道正在启动。你可以多次运行pachctl list pipeline命令,直到管道成功。
-
通过运行以下命令列出代码库:
pachctl list repo
remove-outliers代码库应该上传了413.7KiB的数据,以下输出显示了这一点:
NAME CREATED SIZE (MASTER) DESCRIPTION
remove-outliers About a minute ago 413.7KiB Output repo for pipeline remove-outliers.
data-clean 49 minutes ago 780.4KiB Output repo for pipeline data-clean.
data-explore 53 minutes ago 3.361MiB Output repo for pipeline data-explore.
data About an hour ago 449.9KiB
-
通过运行以下命令列出代码库中的文件:
pachctl list file remove-outliers@master
输出应如下所示:
NAME TYPE SIZE
/histogram-outliers.png file 290.8KiB
/histogram.png file 52.8KiB
/removed-outliers-data.csv file 70.04KiB
-
让我们先通过运行以下命令打开
histogram.png文件:pachctl get file remove-outliers@master:/histogram.png | open -f -a "Preview.app"
这是您应该看到的内容:

图 9.10 – 数据集中的异常值
这个箱线图显示,大多数房屋的售价在 50,000 美元到 350,000 美元之间,其中大部分集中在 110,000 美元到 220,000 美元之间。还有少数房屋的售价远远超出了这个范围,可能被视为一个单独的类别。我们的流水线会移除位于主箱体之外的异常值。
-
现在,让我们看看去除异常值后的直方图。我们可以通过运行以下命令来实现:
pachctl get file remove-outliers@master:/histogram-outliers.png | open -f -a "Preview.app"
这是新的直方图:

图 9.11 – 去除异常值后的直方图
我们已经从数据集中移除了一些行,现在我们有了 1,400 行数据,而不是之前的 1,481 行。
现在我们已经完成了数据清洗,接下来可以训练我们的模型了。
创建训练流水线
我们的下一个流水线将对数据集中的训练部分进行模型训练。以下是流水线的规范:
---
pipeline:
name: train
description: A pipeline that trains the model with a selected estimator.
input:
pfs:
glob: "/"
repo: remove-outliers
transform:
cmd:
- python3
- "/train.py"
image: svekars/hyperparameter-example:1.0
如您所见,这是另一个标准的 Pachyderm 流水线。它从 remove-outliers 仓库中获取数据,并应用 train.py 脚本。它使用与本节其他流水线相同的 Docker 镜像。
以下是 train.py 脚本导入的组件列表:
from sklearn.model_selection import train_test_split
from sklearn import metrics
import pandas as pd
from sklearn.metrics import r2_score, mean_squared_error, make_scorer
from sklearn.linear_model import Ridge
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from contextlib import redirect_stdout
我们从 sklearn 库中导入 train_test_split、metrics、r2_score、mean_squared_error 和 make_scorer 模块,以将数据拆分为训练数据和测试数据,并计算模型的 R2 和 MSE 指标。我们从 sklearn.linear_model 导入 Ridge 回归模型,使用 Ridge 回归来训练我们的模型。Ridge 回归是线性回归的一种变体,是您可以用于这种回归问题的算法之一。我们导入 seaborn 和 matplotlib 来可视化结果,导入 pandas 和 numpy 来处理数据。redirect_stdout 用于将输出重定向到文件。
我们脚本的第一部分从 remove-outliers 仓库读取 removed-outliers-data.csv 文件,并将其作为 DataFrame 处理。然后,我们使用 train_test_split 将数据集分为训练集和测试集。训练集用于训练数据,测试集用于在交叉验证阶段测试模型的性能。以下是代码示例:
data = pd.read_csv("/pfs/remove-outliers/removed-outliers-data.csv", delimiter=',')
X=data.drop('SalePrice', axis=1)
y=data['SalePrice']
train_X, test_X, train_y, test_y = train_test_split(X,y,test_size=0.4, random_state=0)
接下来,我们定义了我们的估算器,它是 Ridge 回归。alpha 是我们将调优的参数,以提高性能。我们最初将 alpha 设置为 1,进行预测,并将我们的 R2 和 MSE 分数保存在 r_squared_mse.txt 文件中,以下是代码示例:
estimator = Ridge(alpha=1).fit(train_X, train_y)
prediction = estimator.predict(test_X)
with open('/pfs/out/r_squared_mse.txt', 'w', encoding='utf-8') as f:
with redirect_stdout(f):
print('R-squared:', metrics.r2_score(test_y, prediction))
print('MSE:', np.sqrt(metrics.mean_squared_error(test_y, prediction)))
最后,我们将绘制数据并将其保存在 prediction.png 文件中,如下所示:
plt.figure(figsize=(20,10))
myplot1 = sns.distplot(test_y, hist=True, kde=False)
myplot2 = sns.distplot(prediction, hist=True, kde=False)
plt.legend(labels=['Real Price', 'Predicted Price'])
plt.xlim(0,)
fig1 = myplot1.get_figure()
fig1.savefig('/pfs/out/prediction.png', dpi=400)
让我们按照以下步骤创建这个流水线:
-
通过执行以下命令检查 Pachyderm 集群是否正在运行:
pachctl version
这是输出结果:
COMPONENT VERSION
pachctl 2.0.0
pachd 2.0.0
-
通过运行以下命令创建一个
train管道:pachctl create pipeline -f train.yaml
不返回任何输出。
-
通过运行以下命令列出所有管道:
pachctl list pipeline
你应该看到以下输出:
NAME VERSION INPUT CREATED STATE / LAST JOB DESCRIPTION
train 1 remove-outliers:/ 34 seconds ago running / success A pipeline that trains the model with a selected estimator.
remove-outliers 1 data-clean:/ 5 seconds ago running / starting A pipeline that removes outliers from the dataset.
data-clean 1 data:/ 4 minutes ago running / success A pipeline that removes empty cells from the CSV.
data-explore 1 data:/* 8 minutes ago running / success A pipeline that performs exploratory analysis.
输出应列出train管道。等待管道运行完毕。
-
让我们查看一下仓库。我们可以通过运行以下命令来实现:
pachctl list repo
你应该看到一个名为train的新仓库,并且数据量为186.3KiB,如以下输出所示:
NAME CREATED SIZE (MASTER) DESCRIPTION
train 2 minutes ago 186.3KiB Output repo for pipeline train.
remove-outliers About a minute ago 413.7KiB Output repo for pipeline remove-outliers.
data-clean 49 minutes ago 780.4KiB Output repo for pipeline data-clean.
data-explore 53 minutes ago 3.361MiB Output repo for pipeline data-explore.
data About an hour ago 449.9KiB
-
现在,让我们查看上传到仓库中的文件。我们可以通过运行以下命令来完成:
pachctl list file train@master
输出应该像这样:
NAME TYPE SIZE
/prediction.png file 186.2KiB
/r_squared_mse.txt file 54B
应该有两个文件。
-
打开
r_squared_mse.txt文件以检查 MSE 和 R2 分数。你可以通过运行以下命令来完成:pachctl get file train@master:/r_squared_mse.txt
输出应该像这样:
R-squared: 0.7803812645495943
MSE: 29521.138357806965
我们的 R2 值相当高,这意味着计算应该相当精确。
-
现在,让我们通过运行以下命令打开
prediction.png文件:pachctl get file train@master:/prediction.png | open -f -a "Preview.app"
你应该看到如下内容:

图 9.12 – 预测价格与实际价格
如你所见,预测价格与实际价格非常接近,只有少数几个小的例外。
在我们最后一个管道步骤中,我们将尝试找到最佳的alpha值,并使用网格搜索对我们的参数进行交叉验证。
创建一个评估管道
我们的评估管道规范如下:
---
pipeline:
name: evaluate
description: A pipeline that evaluates the performance of the model.
input:
pfs:
glob: "/"
repo: remove-outliers
transform:
cmd:
- python3
- "/grid-search.py"
image: svekars/hyperparameter-example:1.0
既然你已经见过这些内容,你可能猜到它是一个标准的 Pachyderm 管道,它从remove-outliers仓库获取数据,并将grid-search.py文件应用于这些数据。这个管道使用与所有其他管道相同的 Docker 镜像。
grid-search.py文件导入了我们在前面章节中已经熟悉的组件。此外,它还导入了sklearn.model_selection库中的GridSearchCV和joblib,后者用于将模型保存为pickle文件。
脚本的第一部分执行与train.py相同的数据处理——它打开数据文件并将其分割成两个数据集。
接下来,我们设置estimator属性为Ridge回归,并指定scoring值和alpha参数,如下所示:
estimator = Ridge(alpha=10)
scoring={'R_squared':'r2','MSE':'neg_mean_squared_error'}
params = {'alpha':[1,0.1,0.01,0.001,0.0001,0,10,100,1000]}
脚本的下一部分使用GridSearchCV来训练并确定最佳的alpha参数,并将最佳分数和最佳alpha参数保存在best_score.txt文件中。模型也保存在my_model.pkl文件中。代码如下所示:
with open('/pfs/out/best_score.txt', 'w', encoding='utf-8') as f:
with redirect_stdout(f):
for i, v in scoring.items():
grid = GridSearchCV(estimator, params, cv=10, scoring= "r2")
grid.fit(train_X, train_y)
print(i)
print('Best params:', grid.best_params_)
if grid.best_score_ > 0:
print('Best score:', grid.best_score_)
else:
print('Best score:', np.sqrt(abs(grid.best_score_)))
print()
joblib.dump(estimator, '/pfs/out/my_model.pkl', compress =1)
最后,我们绘制我们的性能图并将其保存为performance-plot.png。
按照以下步骤创建此管道:
-
通过执行以下命令验证 Pachyderm 是否正在运行:
pachctl version
你应该看到以下输出。请注意,你的pachctl和pachd版本可能有所不同:
COMPONENT VERSION
pachctl 2.0.0
pachd 2.0.0
-
通过运行以下命令创建一个
evaluate管道:pachctl create pipeline -f evaluate.yaml
此命令不会返回任何输出。
-
通过运行以下命令查看活动管道:
pachctl list pipeline
你应该看到以下输出:
NAME VERSION INPUT CREATED STATE / LAST JOB DESCRIPTION
evaluate 1 remove-outliers:/ 5 seconds ago running / running A pipeline that evaluates the performance of the model.
train 1 remove-outliers:/ 34 seconds ago running / success A pipeline that trains the model with a selected estimator.
remove-outliers 1 data-clean:/* 5 seconds ago running / starting A pipeline that removes outliers from the dataset.
data-clean 1 data:/* 4 minutes ago running / success A pipeline that removes empty cells from the CSV.
data-explore 1 data:/* 8 minutes ago running / success A pipeline that performs exploratory analysis.
您应该看到evaluate管道正在运行或已完成,并显示成功状态。
-
查看通过运行以下命令创建的
evaluate管道所生成的仓库:pachctl list repo
您应该看到一个名为train的新仓库,里面有121KiB的数据,具体如下所示:
NAME CREATED SIZE (MASTER) DESCRIPTION
evaluate 2 minutes ago 121KiB Output repo for pipeline evaluate.
train 2 minutes ago 186.3KiB Output repo for pipeline train.
remove-outliers About a minute ago 413.7KiB Output repo for pipeline remove-outliers.
data-clean 49 minutes ago 780.4KiB Output repo for pipeline data-clean.
data-explore 53 minutes ago 3.361MiB Output repo for pipeline data-explore.
data About an hour ago 449.9KiB
-
通过运行以下命令列出
evaluate仓库中的文件:pachctl list file evaluate@master
输出应如下所示:
NAME TYPE SIZE
/best_score.txt file 132B
/my_model.pkl file 187B
/performance-plot.png file 120.7KiB
这些文件是我们的模型、最佳的 MSE 和 R2 得分、最佳的alpha参数,以及展示训练数据与测试数据对比的图表。
-
让我们通过运行以下命令来查看我们的最佳得分:
pachctl get file evaluate@master:/best_score.txt
输出应如下所示:
R_squared
Best params: {'alpha': 10}
Best score: 0.7040913319322766
MSE
Best params: {'alpha': 10}
Best score: 0.7040913319322766
Alpha 10 是我们最佳的alpha参数。它应该用于预测房价。
-
performance-plot.png文件应该展示我们的训练数据与测试数据的对比。我们可以通过运行以下命令查看:pachctl get file evaluate@master:/performance-plot.png | open -f -a "Preview.app"
这是它输出的图表:

图 9.13 – 性能图
如您所见,alpha=10很可能是在我们提供的范围内最佳的参数。此管道结束了我们的示例。生成的模型可以用于使用训练过的alpha超参数预测房价。
这就结束了我们的示例。现在,让我们清理集群。
清理
完成实验后,您可能希望清理集群,以便在下一个实验时从全新安装开始。要清理环境,请按以下步骤操作:
-
通过运行以下命令删除所有管道和仓库:
pachctl delete pipeline –all && pachctl delete repo --all -
通过运行以下命令验证集群中是否存在仓库和管道:
pachctl list repo && pachctl list pipeline
您应该看到以下输出:
NAME CREATED SIZE (MASTER) DESCRIPTION
NAME VERSION INPUT CREATED STATE / LAST JOB DESCRIPTION
您已经成功清理了集群。
总结
在本章中,我们学习了如何实现一个机器学习管道,用于对房价预测示例进行超参数调优。我们创建了该管道的五个步骤,每个步骤都会将相关的文件和信息输出到 Pachyderm 的输出仓库中。在第一个管道中,我们进行了探索性分析,收集了关于数据集的总体理解,并构建了一个热图,帮助我们勾画出数据集中各种参数之间的相关性。在第二个管道中,我们清理了缺失信息的列,并移除了对房屋销售价格影响较小的参数。在第三个管道中,我们去除了异常值——那些超出标准范围的值。我们的第四个管道将数据集分为两部分——一部分用于测试,另一部分用于训练。最后,第五个管道对alpha参数进行了超参数调优,并找到了最适合我们用例的 alpha 值。最后一个管道将我们的模型输出为一个.pkl文件,并创建了一个图表,展示了我们的模型在训练数据和测试数据上的表现。
在下一章,我们将学习 Pachyderm 语言客户端。虽然你可以在 Pachyderm 中使用纯 Python、R 或 Scala,你还可以利用我们提供的语言客户端,甚至自己构建一个,进一步发挥 Pachyderm 的优势。
进一步阅读
-
Kaggle 房价数据集:
www.kaggle.com/lespin/house-prices-dataset -
seaborn:seaborn.pydata.org/
第三部分:Pachyderm 客户端与工具
本节重点介绍了 Pachyderm 可以集成的工具和库,并提供了如何使用 Pachyderm 语言客户端的实际示例,还将教你如何使用 Pachyderm Hub 和 Pachyderm Notebooks。
本节包含以下章节:
-
第十章,Pachyderm 语言客户端
-
第十一章,使用 Pachyderm Notebooks
第十章:第十章: Pachyderm 语言客户端
在前面的章节中,我们已经学习了如何通过pachctl来使用 Pachyderm。我们简要地介绍了 Pachyderm 的用户界面(UI)—或称为仪表板—虽然我们没有广泛使用它。Pachyderm CLI 允许您执行所有 Pachyderm 管理操作,并且通常提供比 Pachyderm UI 更多的功能。
然而,许多用户可能决定通过使用 Pachyderm pachctl或仪表板进一步扩展 Pachyderm 的功能。许多 Pachyderm 用户开发脚本,并通过这些脚本直接调用 Pachyderm API。到目前为止,Pachyderm 提供了两个官方的 Pachyderm 编程语言客户端,Golang(Go)和 Python,以便高级用户进一步扩展 Pachyderm 的功能。
此外,如果您熟悉pps.proto文件,可以通过 C、C++和 Java 等语言访问 Pachyderm。
在本章中,您将学习如何使用 Python 和 Go Pachyderm 客户端。您将学习如何通过这两种客户端运行基本操作,包括如何创建仓库和管道。
本章旨在展示如何使用官方 Pachyderm 语言客户端。
我们将涵盖以下主题:
-
使用 Pachyderm Go 客户端
-
克隆 Pachyderm 源代码库
-
使用 Pachyderm Python 客户端
技术要求
您应该已经安装了接下来列出的组件。
对于本地 macOS 安装,您需要以下组件:
-
macOS Mojave、Catalina、Big Sur 或更高版本
-
Docker Desktop for Mac 10.14
-
minikubev1.9.0 或更高版本 -
pachctl2.0.0 或更高版本 -
Pachyderm 2.0.0 或更高版本
对于本地 Windows 安装,您需要以下组件:
-
Windows Pro 64 位 v10 或更高版本
-
Windows 子系统 Linux(WSL)2 或更高版本
-
Microsoft PowerShell v6.2.1 或更高版本
-
Hyper-V
-
minikubev1.9.0 或更高版本 -
kubectlv1.18 或更高版本 -
pachctl2.0.0 或更高版本 -
Pachyderm 2.0.0 或更高版本
对于Amazon 弹性 Kubernetes 服务(Amazon EKS)的安装,您需要以下组件:
-
kubectlv1.18 或更高版本 -
eksctl -
aws-iam-authenticator -
pachctl2.0.0 或更高版本 -
Pachyderm 2.0.0 或更高版本
对于 Microsoft Azure Kubernetes Service(AKS)云端安装,您需要以下组件:
-
kubectlv1.18 或更高版本 -
Azure CLI
-
pachctl2.0.0 或更高版本 -
Pachyderm 2.0.0 或更高版本
-
jq1.5 或更高版本
对于Google Kubernetes Engine(GKE)云端安装,您需要以下组件:
-
Google Cloud 软件开发工具包(SDK)v124.0.0 或更高版本
-
kubectlv1.18 或更高版本 -
pachctl2.0.0 或更高版本 -
Pachyderm 2.0.0 或更高版本
下载源文件
本章的所有脚本可以在github.com/PacktPublishing/Reproducible-Data-Science-with-Pachyderm/tree/main/Chapter10-Pachyderm-Language-Clients获取。
我们将使用我们在第六章中的图像处理示例,创建你的第一个 Pipeline。如果你还没有这些文件,可以从这里下载该示例的文件:github.com/PacktPublishing/Reproducible-Data-Science-with-Pachyderm/tree/main/Chapter06-Creating-Your-First-Pipeline。
使用 Pachyderm Go 客户端
Pachyderm Go 客户端使你能够通过 Go API 与 Pachyderm 进行通信。Go 是一种由 Google 开发的流行编程语言,近年来在开发者社区中变得广泛流行。在本章中,我们将学习如何启用 Pachyderm Go 客户端,并如何使用 Go 客户端执行基本的 Pachyderm 操作。
你可以参考的主要源文件位于 Pachyderm 源代码库的github.com/pachyderm/pachyderm/tree/master/src/client目录下。这些文件包含了你可以用来与 Pachyderm 对象和原语进行通信的所有方法——具体来说,包括以下文件:
-
github.com/pachyderm/pachyderm/blob/master/src/client/client.go -
github.com/pachyderm/pachyderm/blob/master/src/client/pfs.go -
github.com/pachyderm/pachyderm/blob/master/src/client/pps.go
这些文件包括了大部分重要的 Pachyderm 方法,以及我们在接下来的章节中将使用的方法。
在你的计算机上安装 Go
为了开始使用,我们需要验证环境中是否有有效的 Go 安装。Go 支持所有主要操作系统,包括 Microsoft Windows、Linux 和 macOS。通过运行以下命令,检查你的计算机上是否安装了 Go:
go version
你应该能看到类似下面的输出:
go version go1.16.4 darwin/amd64
如果你的计算机上没有安装 Go,请按照以下步骤进行安装:
-
访问
golang.org/doc/install并下载适用于你操作系统的 Go 版本。 -
打开下载的包并按照提示在系统中安装 Go。安装完成后,你应该能看到如下屏幕:
![图 10.1 – Go 安装]
图 10.1 – Go 安装
-
根据你操作系统的说明,验证 Go 是否已按
golang.org/doc/install中的描述安装。 -
重启你的终端,并再次运行
go version来验证你的安装。你应该能看到类似下面的输出:go version go1.16.4 darwin/amd64
现在我们已经安装了 Go,接下来配置$GOPATH。
配置$GOPATH
如果你以前从未使用过 Go,你需要确保你的$GOPATH目录已正确设置;否则,本节中描述的任何脚本都无法正常工作。安装 Go 时,它可能已经被配置好了。不过,你可能还是想要配置以下内容:
-
验证你在
~/.bash_profile、~/.profile或~/.zsh_profile文件中有以下内容:export GOPATH="$HOME/go" PATH="$GOPATH/bin:$PATH" -
如果你的 shell 配置文件中没有这个配置,请添加它,然后像这样执行你的 shell 配置文件:
source ~/.<shell-profile> -
通过运行以下命令检查你的
$GOPATH目录:go env
此命令将打印出你的 Go 环境配置。如果你使用的是 macOS,$GOPATH目录应该是`GOPATH="/Users/<username>/go"`.
-
如果你还没有这个目录,请在你的
$GOPATH目录下创建一个src目录,如下所示:mkdir $GOPATH/src -
在
$GOPATH/src下创建一个github.com目录,如下所示:mkdir $GOPATH/src/github.com
你需要将 Pachyderm 仓库克隆到这个目录中,具体步骤将在下一章节中描述。
-
更新到最新版本的
grpc,如下所示:go get google.golang.org/grpc
配置好$GOPATH后,你需要克隆 Pachyderm 源代码仓库。
克隆 Pachyderm 源代码仓库
在使用 Pachyderm 语言客户端之前,你需要将 Pachyderm 源代码仓库克隆到你的机器上,以便使用 API。你将通过客户端方法与现有的 Pachyderm 集群进行交互。Pachyderm 仓库存储在 GitHub 上,地址为github.com/pachyderm/pachyderm。此外,你还需要确保切换到与 pachd 和 pachctl 版本相匹配的分支和标签。在本节中,我们将学习如何克隆 Pachyderm 仓库,以及如何切换到所需的分支和标签。
为了能够运行本节脚本中使用的 Go 模块,你需要在计算机上的$GOPATH目录下克隆 Pachyderm 仓库。在 Mac 上,Go 安装在/Users/<username>/go目录下,你可以在/Users/<username>/go/src/github.com/路径下克隆 Pachyderm 仓库。
克隆 Pachyderm 仓库,请完成以下步骤:
-
点击代码标签,如下图所示:

图 10.2 – Pachyderm 源代码仓库
-
在下拉菜单中,选择使用HTTPS或SSH进行克隆,并点击克隆图标。
重要说明
如果你决定使用安全外壳(SSH)进行克隆,并且这是你第一次从 GitHub 克隆,可能需要配置一个 SSH 密钥对。有关更多信息,请参见
docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh。 -
打开终端,使用您在步骤 3中复制的超文本传输协议安全 (HTTPS) 或 SSH 地址运行
git clone命令,如下所示:git clone git@github.com:pachyderm/pachyderm.git
您应该看到类似于以下的输出:
Cloning into 'pachyderm'...
remote: Enumerating objects: 226153, done.
remote: Counting objects: 100% (171/171), done.
...
Pachyderm 源代码将被克隆到 pachyderm 目录。
-
通过运行以下命令进入
pachyderm目录:cd pachyderm -
通过运行以下命令检查您所在的分支:
git branch -
通过运行以下命令获取标签列表:
git fetch –tags -
通过运行以下命令验证您正在使用的
pachctl和pachd版本:pachctl version -
您的输出可能如下所示:
COMPONENT VERSION pachctl 2.0.1 pachd 2.0.1 -
查看与您使用的
pachctl和pachd版本相对应的标签。在这个例子中,我们需要查看2.0.1标签:git checkout tags/v2.0.1 -
通过运行以下命令检查您是否切换到了正确的版本:
git branch
您应该看到以下输出:
* (HEAD detached at v2.0.1)
master
我们现在有了有效的 Pachyderm 源代码,我们将用它来访问我们的 Pachyderm 集群。接下来,让我们使用 Go 客户端连接到 Pachyderm。
使用 Go 客户端连接到 Pachyderm
您必须有一个正在运行的 Pachyderm 集群才能使用 Go API 客户端。如果您已经按照前面的步骤操作,您可能已经在您选择的云平台或本地运行了一个集群。如果没有,请返回到 第四章,本地安装 Pachyderm,或者 第五章,在云平台上安装 Pachyderm,并部署一个集群。
我们将使用 access.go 脚本来访问 Pachyderm。让我们看看这个脚本,了解它是如何工作的。脚本的第一部分导入了所需的组件,如我们在这里看到的:
package main
import (
"fmt"
"log"
"github.com/gogo/protobuf/types"
"github.com/pachyderm/pachyderm/v2/src/client"
)
脚本的第二部分定义了一个 main 函数。您必须在 Go 中使用 main 函数,否则它将无法工作。main 函数定义了 localhost 或 127.0.0.1。30650 是 pachd 端口:
func main() {
c, err := client.NewFromURI("grpc://localhost:30650")
if err != nil {
log.Fatal(err)
}
脚本的第三部分,如下所示,获取您的集群版本:
version, err := c.VersionAPIClient.GetVersion(c.Ctx(), &types.Empty{})
if err != nil {
panic(err)
}
fmt.Println(version)
}
要连接到 Pachyderm 集群,您需要知道集群的 IP 地址。如果在本地机器上运行这些示例,grpc://localhost:30650 应该有效。
现在,让我们运行脚本。请按照以下步骤操作:
-
除非您已经部署了一个负载均衡器,以便访问您的集群,否则在通过 API 访问集群时,您还需要确保始终运行 Pachyderm 的端口转发。要启动 Pachyderm 端口转发,请在另一个终端窗口中运行以下命令:
pachctl port-forward -
运行
access.go脚本,如下所示:go run access.go
这是一个您应该获得的示例响应:
major:2 micro:1
我们已经通过 Go API 成功访问了我们的集群。我们的集群正在运行版本 2.0.1\。您的版本可能不同。
现在,让我们使用 Go API 创建一个 Pachyderm 仓库。
使用 Go 客户端创建仓库
现在我们知道如何连接到 Pachyderm,让我们使用 create-repo.go 脚本中的代码来创建一个仓库。
下面是脚本导入的内容:
package main
import (
"fmt"
"log"
"github.com/pachyderm/pachyderm/v2/src/client"
"github.com/pachyderm/pachyderm/v2/src/pfs"
)
脚本的下一部分定义了一个main函数,执行以下操作:
-
连接到 Pachyderm 集群。
-
创建了一个名为
photos的仓库。 -
列出了该集群上的所有仓库。
它的样子如下:
func main() {
c, err := client.NewOnUserMachine("user")
if err != nil {
log.Fatal(err)
}
if _, err := c.PfsAPIClient.CreateRepo(
c.Ctx(),
&pfs.CreateRepoRequest{
Repo: client.NewRepo("photos"),
Description: "A repository that stores images.",
Update: true,
},
); err != nil {
panic(err)
}
repos, err := c.ListRepo()
if err != nil {
log.Fatal(err)
}
fmt.Println(repos)
}
你必须运行端口转发,并确保将脚本中列出的 IP 地址替换为你的集群 IP 地址。如果你在minikube中运行集群,你可能不需要更改任何内容。
-
运行
create-repo.go脚本,具体如下:go run create-repo.go
该命令返回以下输出:
[repo:<name:"photos" type:"user" > created:<seconds:1637264349 nanos:440180000 > description:"A repository that stores images." auth_info:<permissions:REPO_READ permissions:REPO_INSPECT_COMMIT permissions:REPO_LIST_COMMIT permissions:REPO_LIST_BRANCH permissions:REPO_LIST_FILE permissions:REPO_INSPECT_FILE permissions:REPO_ADD_PIPELINE_READER permissions:REPO_REMOVE_PIPELINE_READER permissions:PIPELINE_LIST_JOB permissions:REPO_WRITE permissions:REPO_DELETE_COMMIT permissions:REPO_CREATE_BRANCH permissions:REPO_DELETE_BRANCH permissions:REPO_ADD_PIPELINE_WRITER permissions:REPO_MODIFY_BINDINGS permissions:REPO_DELETE roles:"repoOwner" > ]
现在我们已经创建了一个仓库,接下来让我们往里面添加一些数据。
使用 Go 客户端将数据放入 Pachyderm 仓库
在前一部分中,我们创建了一个名为photos的 Pachyderm 仓库。接下来,我们将把我们在第六章中使用的文件,创建你的第一个管道,添加到这个仓库。我们将使用put-files.go脚本添加这些文件。下面是脚本导入的内容:
package main
import (
"fmt"
"log"
"os"
"github.com/pachyderm/pachyderm/v2/src/client"
)
脚本的下一部分连接到 Pachyderm 集群,并将landscape.png、red_vase.png和hand.png文件添加到photos仓库的master分支中。
这是连接到仓库的部分。确保你将 IP 地址替换为集群的地址:
func main() {
c, err := client.NewOnUserMachine("user")
if err != nil {
log.Fatal(err)
}
这一部分添加了文件:
myCommit := client.NewCommit("photos","master", "")
f1, err := os.Open("landscape.png")
if err != nil {
panic(err)
}
if err := c.PutFile(myCommit, "landscape.png", f1); err != nil {
panic(err)}
f2, err := os.Open("brown_vase.png")
if err != nil {
panic(err)
}
if err := c.PutFile(myCommit, "brown_vase.png", f2); err != nil {
panic(err)
}
f3, err := os.Open("hand.png")
if err != nil {
panic(err)
}
if err := c.PutFile(myCommit, "hand.png", f3); err != nil {
panic(err)
}
最后一部分,如下所示,列出了photos仓库master分支中的文件:
files, err := c.ListFileAll(myCommit, "/")
if err != nil {
panic(err)
}
fmt.Println(files)
}
让我们通过以下命令运行这个脚本:
go run put-files.go
这个脚本返回了以下输出:
[file:<commit:<branch:<repo:<name:"photos" type:"user" > name:"master" > id:"2c15226b838f48cabd2ae13b43c26517" > path:"/brown_vase.png" datum:"default" > file_type:FILE committed:<seconds:1637299733 nanos:503150000 > size_bytes:93481 hash:"\2061\023\026\376O&\323\313\212\215\226Ra\346\245=Er\r_@E\023\360\352\240\275}\204\235\346" file:<commit:<branch:<repo:<name:"photos" type:"user" > name:"master" > id:"2c15226b838f48cabd2ae13b43c26517" > path:"/hand.png" datum:"default" > file_type:FILE committed:<seconds:1637299733 nanos:503150000 > size_bytes:856063 hash:"\014X\224\032\0251\260(\263\267\234\345{\016\353a\0310\3579\354\323\372\013\357yFg\274\256\000}" file:<commit:<branch:<repo:<name:"photos" type:"user" > name:"master" > id:"2c15226b838f48cabd2ae13b43c26517" > path:"/landscape.png" datum:"default" > file_type:FILE committed:<seconds:1637299733 nanos:503150000 > size_bytes:54009 hash:"\320:\265\036\3363z&\264\324]\364unfv\243\300\001[\206\347\344b\257\274\366\220JnR\004" ]
太好了!我们已经有一个包含数据的仓库了。现在,让我们学习如何创建管道。
使用 Go 客户端创建管道
最后,我们可以从第六章,创建你的第一个管道,为我们的示例创建管道。
下面是create-pipeline.go脚本导入的内容:
package main
import (
"fmt"
"log"
"github.com/pachyderm/pachyderm/v2/src/client"
"github.com/pachyderm/pachyderm/v2/src/pps""
)
脚本的第二部分通过使用pachd的 IP 地址连接到 Pachyderm 集群,具体如下:
func main() {
c, err := client.NewFromAddress("127.0.0.1:30650")
if err != nil {
log.Fatal(err)
}
脚本的下一部分创建了一个contour管道。你可以看到脚本使用了svekars/contour-histogram:1.0镜像,并通过/全局模式从photos仓库中获取数据。这里需要注意的一点是,你需要为所有管道指定parallelism_spec:
if err := c.CreatePipeline(
"contour",
"svekars/contour-histogram:1.0 ",
[]string{"python3", "/contour.py"},
[]string{},
&pps.ParallelismSpec{
Constant: 1,
},
client.NewPFSInput("photos", "/"),
"",
false,
); err != nil {
panic(err)
}
接下来,脚本创建了一个histogram管道,具体如下:
if err := c.CreatePipeline(
"histogram",
"svekars/contour-histogram:1.0",
[]string{"python3", "/histogram.py"},
[]string{},
&pps.ParallelismSpec{
Constant: 1,
},
client.NewPFSInput("contour", "/"),
"",
false,
); err != nil {
panic(err)
}
最后,脚本列出了所有已创建的管道,具体如下:
pipelines, err := c.ListPipeline(true)
if err != nil {
panic(err)
}
fmt.Println(pipelines)
}
运行以下命令:
go run create-pipeline.go
这是一个示例响应:
[pipeline:<name:"histogram" > version:1 spec_commit:<branch:<repo:<name:"histogram" type:"spec" > name:"master" > id:"44945b0d0e2944e3b1015617e224e3e3" > state:PIPELINE_STARTING job_counts:<key:1 value:1 > last_job_state:JOB_CREATED parallelism:1 type:PIPELINE_TYPE_TRANSFORM details:<transform:<image:"svekars/contour-histogram:1.0" cmd:"python3" cmd:"/histogram.py" > parallelism_spec:<constant:1 > created_at:<seconds:1637300756 nanos:806783300 > output_branch:"master" input:<pfs:<name:"contour" repo:"contour" repo_type:"user" branch:"master" glob:"/" > > salt:"0715a02027ba4489a79bd8a400f349ad" datum_tries:3 reprocess_spec:"until_success" >
pipeline:<name:"contour" > version:1 spec_commit:<branch:<repo:<name:"contour" type:"spec" > name:"master" > id:"f3f8bf226e5a4dda8a9f27da10b7fd87" > state:PIPELINE_STARTING job_counts:<key:1 value:1 > last_job_state:JOB_CREATED parallelism:1 type:PIPELINE_TYPE_TRANSFORM details:<transform:<image:"svekars/contour-histogram:1.0 " cmd:"python3" cmd:"/contour.py" > parallelism_spec:<constant:1 > created_at:<seconds:1637300756 nanos:592992600 > output_branch:"master" input:<pfs:<name:"photos" repo:"photos" repo_type:"user" branch:"master" glob:"/" > > salt:"98c0a867ea56439eb1f2466fbf1aa838" datum_tries:3 reprocess_spec:"until_success" > ]
你可以看到脚本已经创建了我们预期的两个管道。我们已经将整个示例上传到这一章的 GitHub 仓库中的contour-go-example.go文件里。现在你已经学会了如何做,你可以只运行这个脚本,通过一个命令创建一个完整的轮廓管道示例。接下来,我们将学习如何清理我们的集群。
使用 Go 客户端清理集群
cleanup.go 脚本会清理集群并删除所有管道、数据和仓库。只有在你不再希望保留数据时,才运行它。
这个脚本只需要从 Pachyderm 仓库中导入客户端。为此,需要以下代码:
package main
import (
"fmt"
"log"
"github.com/pachyderm/pachyderm/v2/src/client"
)
脚本的下一部分删除所有的仓库和管道。我们将所有管道和仓库的 force 标志设置为 true,以便 Pachyderm 不会因为下游管道的依赖关系而中断删除。代码如下所示:
if err := c.DeleteRepo("contour", true); err != nil {
panic(err)
}
if err := c.DeleteRepo("photos", true); err != nil {
panic(err)
}
if err := c.DeleteRepo("histogram", true); err != nil {
panic(err)
}
if err := c.DeletePipeline("contour", true); err != nil {
panic(err)
}
if err := c.DeletePipeline("histogram", true); err != nil {
panic(err)
}
脚本的最后部分返回空列表,因为我们删除了所有的管道和仓库,如以下代码片段所示:
pipelines, err := c.ListPipeline(true)
if err != nil {
panic(err)
}
fmt.Println(pipelines)
repos, err := c.ListRepo()
if err != nil {
log.Fatal(err)
}
fmt.Println(repos)
}
运行以下命令:
go run cleanup.go
这个命令会返回以下输出:
[]
[]
在这一部分中,我们学习了如何使用 Go 客户端创建 Pachyderm 管道和仓库。接下来,让我们学习如何使用 Pachyderm Python 客户端来实现这一点。
使用 Pachyderm Python 客户端
Python 可能是软件工程和数据科学社区中最受欢迎的编程语言之一。Pachyderm 通过 python-pachyderm 包提供了一个官方支持的 Python 客户端。你可以在 GitHub 上找到 Python Pachyderm 的源代码仓库,网址为 github.com/pachyderm/python-pachyderm,也可以在 Python 包索引 (PyPI) 上找到,网址为 pypi.org/project/python-pachyderm/。
作为 Python 客户端参考的主要文件位于 Pachyderm 源代码仓库的 github.com/pachyderm/python-pachyderm/tree/master/src/python_pachyderm/mixin 目录下,最重要的文件如下:
-
github.com/pachyderm/python-pachyderm/blob/master/src/python_pachyderm/client.py -
github.com/pachyderm/python-pachyderm/blob/master/src/python_pachyderm/mixin/pfs.py -
github.com/pachyderm/python-pachyderm/blob/master/src/python_pachyderm/mixin/pps.py
在继续之前,你的机器上必须配置以下组件:
-
Pachyderm 仓库的一个副本(参见 克隆 Pachyderm 源代码仓库 部分)。使用 Python Pachyderm,你可以将仓库克隆到机器上的任何目录。它不必在
$GOPATH中。 -
机器上安装了 Python 3.6 或更高版本。
-
访问一个活动的 Pachyderm 集群。如果是本地安装,你需要在通过 API 与仓库交互时保持 Pachyderm 的端口转发始终运行。如果是云安装,你需要启用负载均衡器以允许访问集群,或者你也可能能够使用 Pachyderm 的端口转发。
我们已经回顾了本节的先决条件。现在,让我们安装 python-pachyderm 客户端。
安装 Pachyderm Python 客户端
在开始使用 Pachyderm Python 客户端之前,你需要在你的机器上安装它。
要安装 Python Pachyderm 客户端,请完成以下步骤:
-
打开一个终端窗口。
-
如果你使用的是 macOS 或 Linux,请运行以下命令:
pip install python-pachyderm
你应该看到以下输出:
Collecting python-pachyderm
Downloading python-pachyderm-6.2.0.tar.gz (409 kB)
...
Successfully installed grpcio-1.38.0 protobuf-3.17.0 python-pachyderm-6.2.0
你安装的 python-pachyderm 包的版本可能不同。
现在我们已经安装了 python-pachyderm,让我们通过使用 python-pachyderm 连接到 Pachyderm。
使用 Python 客户端连接到你的 Pachyderm 集群
为了开始,我们使用 access.py 脚本连接到你的集群。确保端口转发在你的机器上正在运行。这里是脚本:
import python_pachyderm
client = python_pachyderm.Client()
print(client.get_remote_version())
这个脚本通过使用 python_pachyderm.Client() 调用连接到运行在 localhost:30650 上的 pachd,并打印出你正在运行的 Pachyderm 版本。
让我们运行这个脚本,看看它返回什么输出。
使用以下命令运行 access.py 脚本:
python access.py
你应该看到类似于以下的输出:
major: 2
micro: 1
这个输出意味着我们正在使用版本 2.0.1。你的输出可能不同。
现在我们知道如何访问集群了,接下来让我们创建一个 Pachyderm 仓库。
使用 Python 客户端创建一个 Pachyderm 仓库
我们将使用 create-repo.py 脚本创建一个名为 photos 的 Pachyderm 仓库。
这是脚本的代码:
import python_pachyderm
client = python_pachyderm.Client()
client.create_repo("photos")
print(list(client.list_repo()))
使用以下命令运行 create-repo.py 脚本:
python create-repo.py
这是一个示例输出:
repo {
name: "photos"
type: "user"
}
created {
seconds: 1637207890
nanos: 80987000
}
auth_info {
permissions: REPO_READ
permissions: REPO_INSPECT_COMMIT
...
现在我们已经创建了一个仓库,让我们把一些数据放入其中。
使用 Python 客户端将数据放入 Pachyderm 仓库
我们将把在 [第六章 中使用的相同文件,即 创建你的第一个管道,放入我们刚刚创建的 photos 仓库中。以下是我们将使用的脚本:
import python_pachyderm
client = python_pachyderm.Client()
with client.commit('photos', 'master') as i:
client.put_file_url(i, 'landscape.png', 'https://i.imgur.com/zKo9Mdl.jpg')
client.put_file_url(i, 'hand.png', 'https://i.imgur.com/HtZ8FyG.png')
client.put_file_url(i, 'red_vase.png', 'https://i.imgur.com/d45jop9.jpg') print(list(client.list_file(("photos","master"), "/")))
该脚本使用 client.commit 方法开始提交到 photos 仓库的主分支,client.put_file_bytes 向仓库添加三个文件。请注意,client.list_file 需要是 list 类型,而不是 string,以便命令能够正确运行。
让我们运行这个脚本。
使用以下命令运行 put-files.py 脚本:
python put-files.py
这是你应该得到的系统响应:
[file {
commit {
branch {
repo {
name: "photos"
type: "user"
}
name: "master"
}
id: "e29c6f5c49244ce193fe5f86c9df0297"
}
path: "/hand.png"
datum: "default"
}
file_type: FILE
committed {
seconds: 1637208291
nanos: 161527000
}
size_bytes: 856063
hash: "\014X\224\032\0251\260(\263\267\234\345{\016\353a\0310\3579\354\323\372\013\357yFg\274\256\000}"
...
]
上面的输出被截断了。你应该会看到我们添加到仓库的每个文件的相同输出。
现在我们已经添加了文件,让我们为这个示例创建管道。
使用 Pachyderm Python 客户端创建管道
现在我们已经上传了仓库和文件,让我们使用create-pipeline.py脚本根据我们在第六章中介绍的示例,创建两个管道,创建你的第一个管道。
python-pachyderm提供了两种方法来创建管道,具体如下:
-
create_pipeline:此方法适用于所有语言,等同于pachctl create pipeline方法。 -
create_python_pipeline:此管道旨在与 Python 代码一起运行,并提供稍微不同的用户体验(UX)。你可以在 Pachyderm 文档中了解更多关于此方法的信息,访问docs.pachyderm.com。
我们将使用标准的create_pipeline方法来创建这个管道。
脚本的第一部分创建一个contour管道,代码如下:
import python_pachyderm
from python_pachyderm.service import pps_proto
client = python_pachyderm.Client()
client.create_pipeline(
pipeline_name="contour",
transform=pps_proto.Transform(
cmd=["python3", "contour.py"],
image="svekars/contour-histogram:1.0",
),
input=pps_proto.Input(
pfs=pps_proto.PFSInput(glob="/", repo="photos")
),
)
脚本的第二部分创建一个histogram管道,代码如下:
client.create_pipeline(
pipeline_name="histogram",
transform=pps_proto.Transform(
cmd=["python3", "histogram.py"],
image="svekars/contour-histogram:1.0",
),
input=pps_proto.Input(
pfs=pps_proto.PFSInput(glob="/", repo="contour")
),
)
脚本的最后一部分返回一个列表,显示已创建的管道,如以下代码片段所示:
Print(list(client.list_pipeline()))
让我们运行这个脚本。
使用以下命令运行create-pipeline.py脚本:
python create-pipeline.py
这是输出的一部分:
[pipeline {
name: "histogram"
}
version: 1
spec_commit {
branch {
repo {
name: "histogram"
type: "spec"
}
name: "master"
}
id: "94286ef36318425c8177bd4e0f959c57"
}
state: PIPELINE_STARTING
job_counts {
key: 1
value: 1
}...
在本节中,我们已经学习了如何使用python-pachyderm客户端创建管道。接下来,让我们清理我们的集群。
使用 Python 客户端清理集群
我们已经成功地重建了我们的轮廓(contour)和直方图(histogram)管道示例。整个示例作为一个文件contour-histogram-example.py,可以在 GitHub 代码库中找到。你可以通过github.com/PacktPublishing/Reproducible-Data-Science-with-Pachyderm/tree/main/Chapter10-Pachyderm-Language-Clients下载并根据需要多次重建。
在本节中,我们将清理集群,以便为第十一章《使用 Pachyderm 笔记本》提供一个干净的安装环境。我们将使用cleanup.py脚本来实现这一点,代码如下:
import python_pachyderm
client.delete_repo("photos", force=True)
client.delete_pipeline(pipeline_name="contour", force=True, keep_repo=False)
client.delete_pipeline(pipeline_name="histogram", force=True, keep_repo=False)
print(list(client.list_repo()))
print(list(client.list_pipeline()))
该脚本使用了delete_all_pipelines方法,它会删除集群中的所有管道。你还可以使用delete_all来删除集群中的所有对象和原始数据。
让我们运行这个脚本。
使用以下命令运行cleanup.py脚本:
python cleanup.py
该命令应该返回以下输出:
[]
[]
就这样!我们已经成功地清理了我们的集群。
总结
在本章中,我们学习了如何使用两个官方支持的 Pachyderm 语言客户端——Pachyderm Go 客户端和 Python 客户端。我们学习了如何克隆 Pachyderm 代码库并切换到正确的分支和标签。我们学习了如何连接、创建仓库、将文件放入仓库并创建管道,以及完成后删除所有对象。你可以使用这两个语言客户端做更多事情,但本章中的示例为你提供了如何使用它们的一般思路。
在下一章节,我们将学习如何将 Pachyderm 与流行的数据科学 python-pachyderm 客户端集成到 JupyterHub 中。
进一步阅读
-
使用 Traefik 设置 Ingress 以访问 Pachyderm UI:
docs.pachyderm.com/latest/deploy-manage/deploy/ingress/pach-ui-ingress/#traefik-ingress-controller-on-pachyderm-uis-cluster-in-one-diagram -
使用 SSH 连接 GitHub:
docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh -
Go 文档:
golang.org/doc/ -
Python 3 文档:
docs.python.org/3/ -
Python Pachyderm 客户端文档:
python-pachyderm.readthedocs.io/en/stable/
第十一章:第十一章:使用 Pachyderm Notebooks
在 第十章《Pachyderm 语言客户端》中,我们学习了如何使用 Pachyderm 语言客户端,包括 Pachyderm Go 客户端和 Pachyderm Python 客户端。后者可能在数据科学家中更受欢迎,因为 Python 是许多数据科学家使用的语言。而且如果你使用 Python 编写代码,你可能对开源工具 JupyterLab 很熟悉。
JupyterLab 是一个开源平台,提供 交互式开发环境(IDE),你不仅可以编写代码,还可以执行代码。这个优点使得 JupyterLab 成为数据科学实验的理想工具。然而,尽管 JupyterLab 为其笔记本提供了基本的版本控制系统,但它的版本控制系统并不具备 Pachyderm 所提供的数据来源级别。Pachyderm Hub,作为 Pachyderm 的 SaaS 版本,提供了一种将 Pachyderm 集群与 Pachyderm Notebooks 集成的方式,后者是 JupyterLab 的内置版本,并与 Pachyderm 配合使用。
本章旨在演示如何在 Pachyderm Hub 中配置 Pachyderm 集群,并使用 Pachyderm Notebooks。在本章结束时,我们将学习如何在 Pachyderm Notebooks 中运行基本的 Pachyderm 操作,并创建一个情感分析管道。
本章内容包括以下主题:
-
在 Pachyderm Hub 中启用 Pachyderm Notebooks
-
在 Pachyderm Notebooks 中运行基本的 Pachyderm 操作
-
在 Pachyderm Notebooks 中创建并运行一个示例管道
技术要求
你应该已经安装了以下组件:
-
pachctl2.0.0 或更高版本 -
访问 Pachyderm Hub
-
一个 GitHub 或 Gmail 账户
下载源文件
本节中使用的所有代码示例都存储在为本书创建的 GitHub 仓库中,链接为 github.com/PacktPublishing/Reproducible-Data-Science-with-Pachyderm/tree/main/Chapter11-Using-Pachyderm-Notebooks。
本节中使用的 Dockerfile 存储在 hub.docker.com/repository/docker/svekars/pachyderm-ide。
在 Pachyderm Hub 中启用 Pachyderm Notebooks
在你能使用 Pachyderm Notebooks 之前,你需要在 Pachyderm Hub 创建一个账户和一个 Pachyderm 工作区。Pachyderm Hub 为所有用户提供试用期,供其测试功能。
试用期结束后,你需要升级到 Pachyderm Pro 版本才能继续使用 Pachyderm Notebooks。
创建一个工作区
在 Pachyderm Hub 中,你的工作是以 工作区(workspaces)形式组织的。一个工作区是一个容器,其中可以运行多个 Pachyderm 集群。你的组织可能决定将每个工作区分配给一组工程师。
在创建工作区之前,你需要一个 Pachyderm Hub 帐户,所以我们来创建一个。Pachyderm Hub 支持使用 Gmail 和 GitHub 进行身份验证。你必须拥有其中之一才能在 Pachyderm Hub 创建帐户。
创建 Pachyderm Hub 帐户,请完成以下步骤:
-
访问
www.pachyderm.com/try-pachyderm-hub#,并填写提供的表单以申请 Pachyderm Hub 的免费试用。你的帐户激活可能需要一些时间,你将收到包含指示的电子邮件。 -
使用你在注册表单中提供的 Gmail 或 GitHub 帐户登录 Pachyderm Hub 帐户。
-
填写开始使用表单并点击开始使用。
-
点击创建工作区,填写弹出表单,内容如下面的截图所示,然后点击创建:

图 11.1 – 创建一个新工作区
创建工作区时,你将自动部署一个 Pachyderm 集群。如果你正在使用 Pachyderm 的试用版,你将部署一个单节点集群,这应该足够进行测试。
现在你已经创建了第一个工作区,接下来你需要使用pachctl连接到你的集群。
使用 pachctl 连接到你的 Pachyderm Hub 工作区
如果这不是你在本书中阅读的第一章,你应该已经在计算机上安装了pachctl。否则,请按照第四章中的说明,在本地安装 Pachyderm。
要连接到 Pachyderm Hub 工作区,请执行以下步骤:
-
在 Pachyderm Hub UI 中,找到你的工作区,然后点击 CLI 链接。
-
按照界面中的指示,切换你的 Pachyderm 上下文,并启用计算机与 Pachyderm Hub 上工作区之间的通信。
-
在身份验证后,运行以下命令:
pachctl version
你应当得到以下响应:
COMPONENT VERSION
pachctl 2.0.1
pachd 2.0.1
-
通过运行以下命令检查是否已切换到正确的上下文:
pachctl config get active-context
该命令应返回你在 Pachyderm Hub 工作区的名称。
现在你可以通过计算机终端中的pachctl与部署在 Pachyderm Hub 上的集群进行通信。
现在我们已经配置好了集群,接下来让我们连接到 Pachyderm 笔记本。
连接到 Pachyderm 笔记本
Pachyderm 笔记本是一个IDE,为数据科学家提供便捷访问常用的 Python 库。你可以在单元格中运行和测试代码,而 Pachyderm 会为你的管道提供支持。
要连接到 Pachyderm 笔记本,请完成以下步骤:
- 在 Pachyderm Hub UI 中,进入你的工作区,点击笔记本:

图 11.2 – 访问 Pachyderm 笔记本
-
当提示时,点击使用 OAuth 2.0 登录,然后使用具有 Pachyderm Hub 访问权限的帐户登录。
-
在服务器选项页面,选择默认服务器:

图 11.3 – 服务器选项
- 点击 开始 然后点击 启动服务器。
你应该看到以下屏幕:

图 11.4 – Pachyderm 笔记本首页
现在我们可以访问 Pachyderm 笔记本了,我们可以直接从 Pachyderm 笔记本 UI 创建 Pachyderm 管道,实验 Python 代码和 python-pachyderm,运行 pachctl 命令,甚至创建 Markdown 文件来记录我们的实验。我们将在下一部分详细了解此功能。
在 Pachyderm 笔记本中运行基本的 Pachyderm 操作
Pachyderm 笔记本的主要优势是它提供了统一的体验。你不仅可以在其中运行实验,还可以通过集成终端使用 pachctl 和 python-pachyderm 访问你的 Pachyderm 集群。你通过 JupyterLab UI 创建的所有管道将在你的 Pachyderm 集群中反映出来,无论它是在本地运行还是在云平台上。
现在,让我们看看如何使用 Pachyderm 笔记本访问我们的 Pachyderm 集群。
使用集成终端
你可以在 Pachyderm 笔记本中运行集成终端,并使用它执行 pachctl 或任何其他 UNIX 命令。
要使用集成终端,请完成以下步骤:
-
在 Pachyderm 笔记本首页,点击 终端。
-
点击 终端 图标以启动一个新的终端窗口:

图 11.5 – 在 Pachyderm 笔记本中启动终端
-
获取 Pachyderm 的版本:
pachctl version
尝试运行你在前几章中学习的其他 Pachyderm 命令,看看它是如何工作的。
重要提示
pachctl 和 pachd 的版本与从你计算机终端直接运行的版本不同,因为 Pachyderm 笔记本有一个预安装的 pachctl 版本,而这个版本有时可能与集群的版本不匹配。这个差异不应影响你使用 Pachyderm 的工作。
现在我们知道如何使用终端了,让我们尝试创建一个 Pachyderm 笔记本。
使用 Pachyderm 笔记本
笔记本是一个交互式文档,用户可以在其中编写 Python 代码,运行它并可视化结果。这些功能使得笔记本成为许多数据科学家在工作中使用的优秀实验工具。实验完成后,你可能希望将笔记本导出为 Python 脚本或库。
Pachyderm 笔记本支持以下类型的笔记本:
-
Python 笔记本
-
Julia 笔记本
-
R 笔记本
这三种语言似乎是数据科学家中最受欢迎的。你可以创建 Julia 和 R 笔记本,专门实验你想在管道中使用的代码。通过 Python 笔记本,你不仅可以测试代码,还可以使用 python-pachyderm 客户端与 Pachyderm 集群进行交互。
重要提示
本节中描述的代码可以在 github.com/PacktPublishing/Reproducible-Data-Science-with-Pachyderm/blob/main/Chapter11-Using-Pachyderm-Notebooks/example.ipynb 文件中找到。
让我们创建一个 Python 笔记本并运行几个命令:
-
在 Pachyderm 笔记本主页屏幕上,点击 Python 3 笔记本图标以创建一个新的笔记本。
-
我们可以在这个笔记本中使用常规 Python 和
python-pachyderm。例如,要获取当前 Pachyderm 集群的版本并列出所有仓库,可以将以下内容粘贴到笔记本的单元格中:import python_pachyderm client = python_pachyderm.Client() print(client.get_remote_version()) print(list(client.list_repo())) -
点击运行图标以运行脚本并获得结果:

图 11.6 – 在笔记本中运行 python-pachyderm
-
通过将以下代码粘贴到下一个单元格并运行,创建一个仓库:
client.create_repo("data") print(list(client.list_repo()))
这是你应该看到的输出:

图 11.7 – 列出仓库
请注意,你不需要在第二个及后续单元格中导入 python_pachyderm 并定义客户端,因为你已经在第一个单元格中定义过了。
-
让我们向数据仓库中添加一些文件:
with client.commit('data', 'master') as i: client.put_file_url(i, 'total_vaccinations_dec_2020_24-31.csv', 'https://raw.githubusercontent.com/PacktPublishing/Reproducible-Data-Science-with-Pachyderm/main/Chapter11-Using-Pachyderm-Notebooks/total_vaccinations_dec_2020_24-31.csv') print(list(client.list_file(("data", "master"), "")))
这是你应该看到的输出:

图 11.8 – 上传文件输出
这个数据集包含了从 2020 年 12 月 24 日到 12 月 31 日的 COVID-19 疫苗接种统计数据。
-
你可以通过运行以下代码打印文件内容:
import pandas as pd pd.read_csv(client.get_file(("data", "master"), "total_vaccinations_dec_2020_24-31.csv"))
你应该看到以下输出:

图 11.9 – 总疫苗接种数
这个 CSV 文件包含以下列:位置、日期、疫苗(生产商)和 总疫苗接种数。
-
让我们还打印文件的前五行,以查看列名:
import pandas as pd df = pd.read_csv(client.get_file(("data", "master"), "total_vaccinations_dec_2020_24-31.csv")) data_top = df.head() print(data_top)
你应该看到以下输出:

图 11.10 – 前五行
-
最后,让我们创建一个简单的管道,它将告诉我们在观察期内,某一天哪一个国家进行了最多的疫苗接种:
from python_pachyderm.service import pps_proto client.create_pipeline( pipeline_name="find-vaccinations", transform=pps_proto.Transform( cmd=["python3"], stdin=[ "import pandas as pd", "df = pd.read_csv('/pfs/data/total_vaccinations_dec_2020_24-31.csv')", "max_vac = df['total_vaccinations'].idxmax()", "row = df.iloc[[max_vac]]", "row.to_csv('/pfs/out/max_vaccinations.csv', header=None, index=None, sep=' ', mode='a')", ], image="amancevice/pandas", ), input=pps_proto.Input( pfs=pps_proto.PFSInput(glob="/", repo="data") ), ) print(list(client.list_pipeline()))
你应该看到以下输出:

图 11.11 – 创建管道输出
-
让我们通过执行以下代码来获取管道的结果:
client.get_file(("find-vaccinations", "master"), "/max_vaccinations.csv").read()
你应该看到以下输出:

图 11.12 – 管道的结果
我们的管道已经确定,在 12 月 24 日至 12 月 31 日期间,德国在 12 月 31 日进行了最多的疫苗接种。接种的数量是 206443,生产商是 Pfizer/BioNTech。
-
要清理你的集群,请运行以下命令:
client.delete_repo("data", force=True) client.delete_pipeline("find-vaccinations") print(list(client.list_repo())) print(list(client.list_pipeline()))
你应该看到以下输出:

图 11.13 – 集群清理
在本节中,我们学习了如何在 Pachyderm Python Notebooks 中执行基本的 Pachyderm 操作。接下来,我们将创建另一个示例流水线。
在 Pachyderm Notebooks 中创建并运行一个示例流水线
在上一节中,我们学习了如何使用 Pachyderm Notebooks,创建仓库,存放数据,甚至创建了一个简单的流水线。在本节中,我们将创建一个对 Twitter 数据集进行情感分析的流水线。
重要提示
本节中描述的代码可以在github.com/PacktPublishing/Reproducible-Data-Science-with-Pachyderm/blob/main/Chapter11-Using-Pachyderm-Notebooks/sentiment-pipeline.ipynb文件中找到。
我们将使用 Kaggle 上的修改版国际妇女节推文数据集,数据集链接为www.kaggle.com/michau96/international-womens-day-tweets。我们的修改版仅包含两列——推文编号#和文本。该数据集包含51,480行数据。
以下是数据集前几行的提取:
# text
0 3 "She believed she could, so she did." #interna...
1 4 Knocking it out of the park again is\r\n@marya...
2 5 Happy International Women's Day! Today we are ...
3 6 Happy #InternationalWomensDay You're all power...
4 7 Listen to an experimental podcast recorded by ...
下面是工作流程的图示:

图 11.14 – 情感分析流水线
在下一节中,我们将学习构建该流水线所使用的方法论。
流水线方法论
我们将使用TextBlob,一个用于文本处理的开源 Python 库,对数据集中的推文进行情感分析。
情感分析是一种帮助理解特定对话中涉及个体整体情绪的技术,讨论特定的产品和服务,或评估一部电影。情感分析在各种类型的商业和行业中被营销人员和社会学家广泛使用,用于快速评估客户情绪。在本例中,我们将查看有关国际妇女节的一些推文中表达的情感。
TextBlob提供了两种情感分析指标——极性和主观性。句子中的每个单词都被分配一个分数,然后将该分数的平均值分配给整个句子。在本例中,我们将只确定推文的极性。极性根据预定义的单词强度来定义句子的积极性或消极性。
极性值范围从-1 到 1,其中-1 表示负面情感,0 表示中性,1 表示正面。如果我们将其显示在一个刻度上,它会是这样的:

图 11.15 – 极性
如果我们将这些单词放入表格中并分配极性分数,可能会得到如下结果:

图 11.16 – 极性分数
让我们快速运行一个简单句子的TextBlob示例,看看它是如何工作的。使用sentiment-test.py文件中的代码尝试这个示例:
from textblob import TextBlob
text = '''Here is the most simple example of a sentence. The rest of the text is autogenerated. This gives the program some time to perform its computations and then tries to find the shortest possible possible sentence. Finally, let's look at the output that is used for the rest of the process.'''
blob = TextBlob(text)
blob.tags
blob.noun_phrases
for i in blob.sentences:
print(i.sentiment.polarity)
要运行这个脚本,完成以下步骤:
-
你需要在 Pachyderm 笔记本终端中安装
TextBlob:pip install textblob && python -m textblob.download_corpora
这是你应该看到的输出:
![图 11.17 – 安装 TextBlob]
图 11.17 – 安装 TextBlob
- 在本地终端或 Jupyter Notebook 中运行
sentiment-test.py:
![图 11.18 – sentiment-test.py 脚本的输出]
图 11.18 – sentiment-test.py 脚本的输出
如输出所示,TextBlob会为每个句子分配一个评分。
现在我们已经回顾了示例的方法论,让我们创建我们的管道。
创建管道
我们的第一个管道将使用 NLTK 来清理data.csv文件中的 Twitter 数据。我们将使用python-pachyderm创建一个标准的 Pachyderm 管道。该管道将从数据存储库中获取文件,运行data-clean.py脚本,并将清理后的文本输出到data-clean输出存储库。该管道将使用svetkar/pachyderm-ide:1.0 Docker 镜像来运行代码。
data-clean.py的第一部分导入了我们在第八章中熟悉的组件,创建端到端机器学习工作流。这些组件包括 NLTK 和pandas,我们将用它们来预处理数据。我们还将导入re来指定正则表达式:
import nltk
import pandas as pd
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize
nltk.download('wordnet')
nltk.download('punkt')
import re
脚本的第二部分使用 NLTK 的word_tokenize方法、stopwords和lambda函数,以及re.split来移除 URL,进行数据清理。最后,脚本将清理后的文本保存到cleaned-data.csv文件中,存放在输出存储库:
stopwords = stopwords.words("english")
data = pd.read_csv("/pfs/data/data.csv", delimiter=",")
tokens = data['text'].apply(word_tokenize)
remove_stopwords = tokens.apply(lambda x: [w for w in x if w not in stopwords and w.isalpha()])
remove_urls = remove_stopwords.apply(lambda x: re.split('https:\/\/.*', str(x))[0])
remove_urls.to_csv('/pfs/out/cleaned-data.csv', index=True)
我们的第二个管道将使用TextBlob Python 库对清理后的数据执行情感分析。sentiment.py脚本导入了以下组件:
from textblob import TextBlob
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from contextlib import redirect_stdout
我们将使用pandas来操作数据框。我们将使用matplotlib和seaborn来可视化结果,并使用redirect_stdout将结果保存到文件中。
接下来,我们的脚本执行情感分析并创建两个新列——polarity_score和sentiment。结果表格保存为一个名为polarity.csv的新 CSV 文件:
data = pd.read_csv('/pfs/data-clean/cleaned-data.csv', delimiter=',')
data = data[['text']]
data["polarity_score"] = data["text"].apply(lambda data: TextBlob(data).sentiment.polarity)
data['sentiment'] = data['polarity_score'].apply(lambda x: 'Positive' if x >= 0.1 else ('Negative' if x <= -0.1 else 'Neutral'))
print(data.head(10))
data.to_csv('/pfs/out/polarity.csv', index=True)
然后,脚本将情感类别的推文保存到其自己的变量中,计算每个类别的总数,并将总数保存到number_of_tweets.txt文件:
positive = [ data for index, t in enumerate(data['text']) if data['polarity_score'][index] > 0]
neutral = [ data for index, tweet in enumerate(data['text']) if data['polarity_score'][index] == 0]
negative = [ data for index, t in enumerate(data['text']) if data['polarity_score'][index] < 0]
with open('/pfs/out/number_of_tweets.txt', 'w') as file:
with redirect_stdout(file):
print("Number of Positive tweets:", len(positive))
print("Number of Neutral tweets:", len(neutral))
print("Number of Negative tweets:", len(negative))
脚本的最后部分绘制了一个饼图,显示每个类别推文的百分比,并将其保存到plot.png文件中:
colors = ['#9b5de5','#f15bb5','#fee440']
figure = pd.DataFrame({'percentage': [len(positive), len(negative), len(neutral)]},
index=['Positive', 'Negative', 'Neutral'])
plot = figure.plot.pie(y='percentage', figsize=(5, 5), autopct='%1.1f%%', colors=colors)
circle = plt.Circle((0,0),0.70,fc='white')
fig = plt.gcf()
fig.gca().add_artist(circle)
plot.axis('equal')
plt.tight_layout()
plot.figure.savefig("/pfs/out/plot.png")
让我们创建这些管道:
-
创建一个新的 Pachyderm Python 笔记本。
-
创建一个 Pachyderm
data存储库:import python_pachyderm client = python_pachyderm.Client() client.create_repo("data") print(list(client.list_repo()))
你应该看到以下输出:
![图 11.19 – 创建的存储库的输出]
图 11.19 – 创建的存储库的输出
-
将
data.csv文件放入这个存储库:with client.commit('data', 'master') as i: client.put_file_url(i, 'data.csv', 'https://raw.githubusercontent.com/PacktPublishing/Reproducible-Data-Science-with-Pachyderm/main/Chapter11-Using-Pachyderm-Notebooks/data.csv') print(list(client.list_file(("data", "master"), "")))
该脚本返回以下输出:

图 11.20 – 放置文件输出
-
列出数据库中的文件:
list(client.list_file(("data", "master"), ""))
你应该看到以下响应:

图 11.21 – 列表文件输出
-
创建
data-clean管道:from python_pachyderm.service import pps_proto client.create_pipeline( pipeline_name="data-clean", transform=pps_proto.Transform( cmd=["python3", "data-clean.py"], image="svekars/pachyderm-ide:1.0", ), input=pps_proto.Input( pfs=pps_proto.PFSInput(glob="/", repo="data") ), ) client.create_pipeline( pipeline_name="sentiment", transform=pps_proto.Transform( cmd=["python3", "sentiment.py"], image="svekars/pachyderm-ide:1.0", ), input=pps_proto.Input( pfs=pps_proto.PFSInput(glob="/", repo="data-clean") ), ) print(list(client.list_pipeline()))
你应该看到以下输出:

图 11.22 – 创建管道输出
输出被截断,仅显示 data-clean 管道的内容。你应该也能看到 sentiment 管道的类似输出。
-
让我们查看
data-clean库中包含我们清洗数据的文件的前几行:import pandas as pd pd.read_csv(client.get_file(("data-clean", "master"), "cleaned-data.csv"), nrows=10)
该脚本返回以下输出:

图 11.23 – 清洗后的数据
你可以看到文本已被分解为标记。
-
让我们获取情感库中的文件列表:
list(client.list_file(("sentiment","master"), ""))
你应该看到一长串输出。文件将位于 path: 下,类似于以下响应:

图 11.24 – 情感库中的文件列表
应该有三个文件,如下所示:
-
number_of_tweets.txt:一个文本文件,包含每个类别的推文总数 -
plot.png:一个饼图,显示每个类别中推文的百分比 -
polarity.csv:一个新的 CSV 表格,包含polarity_score和sentiment列
-
现在,让我们来看一下
polarity.csv表格的前几行:pd.read_csv(client.get_file(("sentiment","master"), "polarity.csv"), nrows=10)
该脚本返回以下输出:

图 11.25 – 极性和情感结果
你可以看到原始表格中新增的两列,提供了一个范围为 [-1;1] 的极性分数和一个情感类别。
-
让我们来看一下每个情感类别的总数:
client.get_file(("sentiment", "master"),"number_of_tweets.txt").read()
你应该看到以下输出:

图 11.26 – 每个类别的推文总数
-
最后,让我们来看一下带有情感类别百分比的饼图:
from IPython.display import display from PIL import Image display(Image.open(client.get_file(("sentiment", "master"), "/plot.png")))
该脚本返回以下输出:

图 11.27 – 正面、负面和中性情感的百分比
根据这张图,我们可以看出大多数推文包含正面情感,负面推文的百分比可以认为微不足道。
这就是我们情感分析示例的全部内容。
总结
在本章中,我们学习了如何在 Pachyderm Hub 中创建 Pachyderm 笔记本,这是 Pachyderm 的一个强大功能,能够让数据科学家利用集成环境与 Pachyderm 数据血统功能和管道的优势。数据科学家花费数小时进行探索性数据分析,并且是在笔记本中完成的。将 Pachyderm 与笔记本结合,能够将数据科学家和数据工程师汇聚在同一平台,让他们讲同样的语言,使用相同的工具。
除了上述内容外,我们还创建了一个管道,用于对 Twitter 数据进行基本的情感分析,并且完全在 Pachyderm 笔记本中运行。我们扩展了对 Python Pachyderm 的知识,并了解了它如何与其他工具和库结合使用。
进一步阅读
-
JupyterLab 文档:
jupyterlab.readthedocs.io/en/stable/ -
TextBlob文档:textblob.readthedocs.io/en/dev/ -
python-pachyderm文档:python-pachyderm.readthedocs.io/en/stable/

订阅我们的在线数字图书馆,全面访问超过 7,000 本书籍和视频,并获得行业领先的工具,帮助您规划个人发展并推动职业生涯。有关更多信息,请访问我们的网站。
第十二章:为什么订阅?
-
通过超过 4,000 名行业专业人士的实用电子书和视频,花更少的时间学习,更多的时间编码
-
通过专门为您构建的技能计划提升您的学习
-
每月获得一本免费电子书或视频
-
完全可搜索,便于访问重要信息
-
复制、粘贴、打印和书签内容
您知道 Packt 提供所有出版书籍的电子书版本,且提供 PDF 和 ePub 文件吗?您可以在 packt.com 升级为电子书版本,作为印刷书籍的客户,您有资格获得电子书折扣。有关更多信息,请联系我们 customercare@packtpub.com。
在 www.packt.com 上,您还可以阅读一系列免费的技术文章,注册各种免费的新闻通讯,并获得 Packt 书籍和电子书的独家折扣和优惠。
其他您可能喜欢的书籍
如果您喜欢本书,您可能会对 Packt 出版的以下书籍感兴趣:
工程化 MLOps
Emmanuel Raj
ISBN:9781800562882
-
制定机器学习训练和部署的数据治理策略和流程
-
熟悉实施机器学习管道、持续集成/持续交付(CI/CD)管道和机器学习监控管道
-
设计一个健壮且可扩展的微服务和 API,适用于测试和生产环境
-
为相关用例和组织策划您的自定义持续集成/持续交付(CD)流程
-
监控机器学习模型,包括监控数据漂移、模型漂移和应用性能
-
构建和维护自动化的机器学习系统
开始使用 Streamlit 进行数据科学
Tyler Richards
ISBN:9781800565500
-
设置您的第一个开发环境,并从零开始创建一个基本的 Streamlit 应用
-
探索在 Streamlit 应用中上传、下载和操作数据的方法
-
使用内建和导入的 Python 库在 Streamlit 中创建动态可视化
-
发现创建和部署机器学习模型在 Streamlit 中的策略
-
使用 Streamlit 分享功能进行一键部署
-
使用主题、Streamlit 组件和 Streamlit 侧边栏美化 Streamlit 应用
-
实现最佳实践,用 Streamlit 原型化您的数据科学工作
Packt 正在寻找像您一样的作者
如果你有兴趣成为 Packt 的作者,请访问authors.packtpub.com并立即申请。我们已经与成千上万的开发者和技术专业人士合作,帮助他们与全球技术社区分享见解。你可以提交一般申请、申请我们目前正在招聘作者的特定热门话题,或者提交你自己的想法。
分享您的想法
现在你已经完成了《可复现的数据科学与 Pachyderm》,我们非常希望听到你的想法!如果你是在 Amazon 上购买的此书,请点击这里直接前往 Amazon 的书籍评价页面,分享你的反馈或在购买网站上留下评论。
你的评论对我们和技术社区都非常重要,将帮助我们确保提供优质的内容。
你可能喜欢的其他书籍
你可能喜欢的其他书籍


浙公网安备 33010602011771号