使用 lakeFS 和 MinIO 实现 AI/ML 可重复性

AI/ML Reproducibility with lakeFS and MinIO

这篇文章是与来自 lakeFS 的 Amit Kesarwani 共同撰写的。

运行多个机器学习实验的现实情况是,管理它们可能变得不可预测且复杂,尤其是在团队环境中。通常发生的情况是,在研究过程中,团队会不断更改实验之间的配置和数据。例如,尝试多个训练集和多个超参数值,并且——当涉及大型数据集时——还会尝试 Apache Spark 等分布式计算引擎的不同配置。

机器学习工程师的一部分工作需要在这些实验之间来回切换,以进行比较和优化。当工程师手动管理所有这些实验时,他们的效率会降低。

工程师如何才能自信且高效地运行机器学习实验?

在本文中,我们将深入探讨可重复性,向您展示它为什么值得您花时间以及如何使用 lakeFS 和 MinIO 实现它。

为什么数据从业人员需要可重复性

什么是可重复性?

可重复性确保团队可以使用相同的程序重复实验并获得相同的结果。它是科学方法的基础,因此在机器学习中是一种非常实用的方法。

在数据方面,可重复性意味着您拥有重建模型及其结果所需的一切,例如数据、工具、库、框架、编程语言和操作系统。这样,您就可以生成相同的结果。

为什么数据团队需要可重复性?

机器学习流程不是线性的。工程师通常会迭代和增量地尝试各种机器学习方法和参数,以获得更准确的机器学习模型。由于开发的迭代性质,机器学习中最困难的挑战之一是确保工作是可重复的。例如,训练用于检测癌症的机器学习模型应该在所有输入和使用的系统都相同的情况下返回相同的模型。

此外,可重复性是法规遵从、审计和验证的关键要素。它还可以提高团队生产力,改善与非技术利益相关者的合作,并提升对机器学习产品和服务的透明度和信心。

如前所述,机器学习管道可能会变得复杂。您必须管理代码、数据集、模型、超参数、管道、第三方包和环境特定的配置。准确重复实验是一项挑战。您需要重新创建生成模型所使用的确切条件。

可重复数据的优势

一致性

在给定相同数据的情况下,您希望模型能够提供相同的结果。这将帮助您对数据产品建立信心。如果您通过重复实验获得相同的结果,用户的体验也会保持一致。

此外,作为研究过程的一部分,您希望能够更新单个元素,例如模型的核心,同时保持其他所有内容不变,然后观察结果如何变化。

安全性和合规性

另一个需要考虑的是安全性和合规性。在许多业务领域,如银行、医疗保健和安全,组织需要维护和报告生成给定模型及其结果的确切过程。确保可重复性是这些领域中的常见做法。

要实现此目标,您需要对机器学习管道的所有输入进行版本控制,以便可以还原到先前版本以重现先前的结果。法规通常要求您重新创建管道的先前状态。这包括模型、数据和先前结果。

更轻松地管理更改数据

数据总是在变化。这使得很难跟踪其随时间的精确状态。人们通常只保留数据的单一状态:当前状态。

这对工作有负面影响,因为它会使以下任务变得极其困难

  • 调试数据问题。
  • 验证机器学习训练的正确性(在不同数据上重新运行模型会产生不同的结果)。
  • 观察数据审计。

如何实现可重复性?

为了实现可重复性,数据从业人员通常会保留机器学习管道和数据的多个副本。但每次想要探索大量训练数据集时都复制它们成本高昂,而且不可扩展。

此外,还没有方法可以保存许多模型工件及其伴随的训练数据的原子副本。再加上处理各种类型的组织、半结构化和非结构化训练数据的挑战,例如视频、音频、物联网传感器数据、表格数据等等。

最后,当机器学习团队为协作而创建相同数据的重复副本时,很难实施数据隐私最佳实践和数据访问限制。

您需要的是一个具有零复制机制的 数据版本控制 工具,它允许您创建和跟踪数据的多个版本。版本控制是指记录和控制对代码、数据、标签、模型、超参数、实验、依赖项、文档和环境等工件的更改的过程,以进行训练和推理。

您能使用 Git 来进行数据版本控制吗?这听起来可能是个好主意,但 Git 对于数据来说既不安全,也不充分,也不可扩展。

用于数据科学的版本控制组件比软件项目的版本控制组件更复杂,这使得可重复性更具挑战性。此外,由于原始训练数据通常存储在云对象存储(S3、GCS、Azure Blob)中,因此团队需要一个适用于就地数据(在对象存储中)的版本控制解决方案。

幸运的是,有一个开源工具可以做到这一点:lakeFS。

数据版本控制 与 lakeFS

lakeFS 是一款开源工具,它使团队能够使用类似 Git 的过程(提交、合并、分支)来管理其数据,支持数十亿个文件和 PB 级的数据。lakeFS 为您的对象存储(如 S3)添加了一个管理层,并将您的整个存储桶转换为类似于代码库的东西。此外,虽然 lakeFS 仅处理机器学习运维流程的一部分,但它力求成为机器学习运维生态系统中的一个好公民,与下面所示的所有工具进行交互——尤其是 数据质量工具

可重复性意味着团队成员能够在数据的多个版本之间进行时间旅行,在不同时期和不同修改程度下对数据进行快照。

为了确保数据可重复性,我们建议在数据发生变化时始终提交 lakeFS 存储库。只要进行了提交,复制给定状态就与从包含为提交生成的唯一 commit_id 的路由中读取数据一样简单。

获取存储库的当前状态很简单。我们使用一个包含存储库名称和分支名称的静态路由。例如,如果您有一个名为 example 的存储库,其中包含一个名为 main 的分支,将此数据的最新状态读取到 Spark 数据帧中看起来像这样

df = spark.parquet("s3://example/main/")

注意:此代码段假设此路径下存储库中的所有项目都采用 Parquet 格式。如果您使用的是其他格式,请使用相应的 Spark 读取方法。

但是,我们也可以查看 lakeFS 存储库中的任何先前提交。任何提交都可以重现。如果可以重现提交,那么结果就是可重复的。

在上面的存储库中,每次执行模型训练脚本时,都会向存储库进行新的提交,并且提交消息会指定确切的运行编号。如果我们想重新运行模型训练脚本并从之前的运行中获得相同的结果会怎么样?例如,假设我们想要重现运行 #435 的结果。为此,我们只需复制与运行关联的 commit ID 并将数据读入数据帧,如下所示

df = spark.parquet("s3://example/296e54fbee5e176f3f4f4aeb7e087f9d57515750e8c3d033b8b841778613cb23/training_dataset/")

在代码中引用单个 commit_id 的能力可以简化复制数据集合或多个集合的特定状态的过程。这在许多典型的数据开发用例中都非常有用,例如历史调试、发现数据集合中的差异、审计合规性等等。

MinIO 的对象存储

MinIO 是一款高性能、与 S3 兼容的对象存储。它专为大规模 AI/ML、数据湖和数据库工作负载而构建。它可以在本地和任何云(公共或私有)上运行,从数据中心到边缘。MinIO 是软件定义的,并在 GNU AGPL v3 下开源。企业使用 MinIO 来满足 ML/AI、分析、备份和存档工作负载的要求,所有这些都来自单个平台。MinIO 安装和管理非常简单,提供了一套丰富的企业级功能,针对安全性、弹性、数据保护、可扩展性和身份管理。在本演示中,MinIO 用于存储客户的文档。

将所有内容整合在一起:lakeFS + MinIO

lakeFS 为基于对象存储的数据湖提供版本控制功能,以 Git 的形式进行操作。它可以在您的 MinIO 存储环境之上工作,并与所有当代数据框架集成,例如 Apache Spark、Hive、Presto、Kafka、R 和 Native Python 等。

在 MinIO 之上使用 lakeFS,您可以

  • 创建一个跟踪实验的开发环境
  • 有效地修改和版本化数据,为每次实验进行零复制分支和提交。
  • 构建一个强大的数据管道,将新数据交付到生产环境。

以下是如何在 MinIO 上设置 lakeFS 并简化数据处理。

先决条件

安装

让我们从在您的机器上本地安装 lakeFS 开始。更多安装选项可在lakeFS 文档中找到。

适合生产的安装需要持久化的 PostgreSQL 安装。但在本示例中,我们将使用 Docker 容器内的本地键值存储。

通过用您 MinIO 安装中的值替换 <minio_access_key_id>、<minio_secret_access_key> 和 <minio_endpoint> 来运行以下命令

docker run --name lakefs \
            --publish 8000:8000 \
            -e LAKEFS_BLOCKSTORE_TYPE=s3 \
            -e LAKEFS_BLOCKSTORE_S3_FORCE_PATH_STYLE=true \
            -e LAKEFS_BLOCKSTORE_S3_ENDPOINT=<minio_endpoint> \
            -e LAKEFS_BLOCKSTORE_S3_CREDENTIALS_ACCESS_KEY_ID=<minio_access_key_id> \
            -e LAKEFS_BLOCKSTORE_S3_CREDENTIALS_SECRET_ACCESS_KEY=<minio_secret_access_key> \
            treeverse/lakefs:latest \
            run --local-settings

配置

转到 lakeFS 并创建一个管理员用户:http://127.0.0.1:8000/setup

记下生成的访问密钥和密钥。

使用访问密钥和密钥登录 lakeFS:http://127.0.0.1:8000

我们将使用 lakectl 二进制文件来执行 lakeFS 操作。您需要在这里找到适合您的操作系统的发行版here,并从 tar.gz 存档中提取 lakectl 二进制文件。将其放在 $PATH 中的某个位置并运行 lakectl --version 进行验证。

然后运行以下命令来配置 lakectl,使用您之前在设置中获得的凭据

lakectl config
# output:
# Config file /home/janedoe/.lakectl.yaml will be used
# Access key ID: <LAKEFS_ACCESS_KEY_ID>
# Secret access key: <LAKEFS_SECRET_KEY>
# Server endpoint URL: http://127.0.0.1:8000/api/v1

确保 lakectl 可以使用以下命令访问 lakeFS

lakectl repo list

如果您没有收到任何错误通知,那么您就可以为 lakeFS 设置 MinIO 别名

mc alias set lakefs http://s3.local.lakefs.io:8000 <LAKEFS_ACCESS_KEY_ID> <LAKEFS_SECRET_KEY>

如果您还没有,也请为 MinIO 存储设置 MinIO 别名

mc alias set myminio <minio_endpoint> <minio_access_key_id> <minio_secret_access_key>

现在我们已经了解了基本概念并安装了所有内容,让我们逐步完成一个端到端示例,演示将此轻松地整合到您的 AI/ML 工程工作流程中的方式。您还会注意到使用 lakeFS 非常像使用 Git。如果您的工程师了解 Git,他们将很容易学习 lakeFS。

零克隆复制和可重复性示例

将 MinIO 与 lakeFS 相结合的主要优势之一是能够实现并行性而无需产生额外的存储成本。lakeFS 利用一种独特的方法(零克隆复制),其中您的 ML 数据集和模型的不同版本可以在不复制数据的情况下有效地管理。本节将演示此功能。

让我们从在 MinIO 中创建一个桶开始!

请注意,此桶将直接在您的 MinIO 安装中创建。稍后,我们将使用 lakeFS 为此桶启用版本控制。

mc mb myminio/example-bucket

因此,让我们从在 lakeFS 中创建一个仓库开始

lakectl repo create lakefs://example-repo s3://example-bucket

生成两个示例文件

echo "my first file" > myfile.txt
echo "my second file" > myfile2.txt

创建一个名为 experiment1 的分支,将文件复制到该分支并提交

lakectl branch create lakefs://example-repo/experiment1 --source lakefs://example-repo/main

mc cp ./myfile.txt lakefs/example-repo/experiment1/

lakectl commit lakefs://example-repo/experiment1 -m "my first experiment"

让我们为 experiment1 分支中提交的数据创建一个标签(您的 ML 模型稍后可以通过标签访问您的数据)

lakectl tag create lakefs://example-repo/my-ml-experiment1 lakefs://example-repo/experiment1

现在,让我们将分支合并回 main

lakectl merge lakefs://example-repo/experiment1 lakefs://example-repo/main

创建一个名为 experiment2 的分支,将文件复制到该分支,提交并标记它

lakectl branch create lakefs://example-repo/experiment2 --source lakefs://example-repo/main

mc cp ./myfile2.txt lakefs/example-repo/experiment2/

lakectl commit lakefs://example-repo/experiment2 -m "my second experiment"

lakectl tag create lakefs://example-repo/my-ml-experiment2 lakefs://example-repo/experiment2

现在,让我们将分支合并回 main

lakectl merge lakefs://example-repo/experiment2 lakefs://example-repo/main

使用标签列出不同实验的数据

mc ls lakefs/example-repo/my-ml-experiment1
# 应该只列出 myfile.txt

mc ls lakefs/example-repo/my-ml-experiment2
# 两个文件都应该列出

完整示例

您可以查看 ML 可重复性示例以及多个 ML 实验,此处

此示例的设置说明 此处

下一步

如果您准备好使用 Git 类功能扩展您的 MinIO 对象存储,请按照上述安装和配置步骤进行操作,并亲自尝试!

前往 此文档页面 开始。

总结

通过将 lakeFS 和 MinIO 结合在一起,您可以利用 Git 分支的强大功能来创建可重复的实验。

查看 lakeFS 文档 了解更多信息,并加入他们活跃的 lakeFS 社区 公共 Slack 频道

如果您对 MinIO 有任何疑问,请通过 hello@min.io 与我们联系,或加入 MinIO 的讨论 通用 Slack 频道