Karrot 为什么使用 TFX 以及如何提高 ML 管道开发的效率
2022 年 5 月 6 日
来自 Karrot 的 Ukjae Jeong、Gyoung-yoon Yoo 和 Myeonghyeon Song 发布

Karrot(韩国 Danggeun Market 的全球服务)是一款基于二手市场的本地社区服务应用程序,连接着邻居。Danggeun Market 于 2015 年推出,超过 2300 万韩国人正在其当地社区使用 Danggeun Market。目前,Karrot 在四个国家/地区的 440 个本地社区运营:英国、美国、加拿大和日本。在我们的服务中,滚动浏览信息流以寻找物美价廉的物品已成为用户的一种日常乐趣。为了提供更好的用户体验,我们一直在应用各种机器学习模型,例如推荐模型。

我们还在努力寻找有效且高效地应用 ML 模型的方法。特别是,我们正在投入大量精力构建用于定期部署、快速实验和持续模型改进的机器学习管道。

对于 ML 管道,我们一直在生产中使用 TFX(TensorFlow Extended)。因此,在本文中,我们将简要介绍我们使用 TFX 的原因以及我们如何利用 TFX 来提高生产力。

Karrot 中的机器学习

Karrot 内部有很多 ML 项目。ML 模型在服务内部运行。例如,我们使用自动化模型来检测欺诈,还有推荐模型来改善我们的应用程序信息流上的用户体验。如果您有兴趣详细了解这些模型,请参阅 我们的团队博客,这些博客是用韩语编写的。

由于我们一直在为 ML 模型使用 Kubeflow,因此我们能够定期训练、实验和部署模型,但我们仍然遇到了一些痛点。自从去年我们开始将 TFX 与 Kubeflow 结合使用以来,TFX 将此进一步提升,使团队能够轻松使用我们的生产管道。

TFX 如何帮助我们进行生产 ML

TFX 通过开放且可扩展的设计帮助轻松构建和部署生产 ML 管道。

TFX 于 2019 年完全开源,是一个用于生产 ML 管道的端到端平台。它支持在组件单元中编写 ML 工作流,然后可以在多个环境中运行 - Apache BeamDataflowKubeflowAirflow。它还附带了针对数据摄取/转换、训练和部署的编写良好的标准组件。

标准组件

TFX 提供了多个标准组件。如果您正在寻找用于数据摄取的组件,有基于本地 CSV 文件的 CsvExampleGenPrestoExampleGenBigQueryExampleGen,它们可以通过一些自定义直接从 Presto、BigQuery 和许多其他来源摄取数据。因此,您只需将预构建的组件连接到您的 TFX 管道,就可以轻松地处理来自多个来源的数据。

它还可以平稳地处理大规模数据处理。由于执行特征工程的 Transform 组件是在 Apache Beam 上实现的,因此您可以在 GCP Dataflow 或其他计算集群上以分布式方式执行它。

当然,还存在许多其他方便的组件,并且会不断添加更多组件。

组件可重用性

为了使 TFX 适应我们的产品,需要自定义组件。TFX 具有结构良好的组件设计,使我们能够自然且轻松地创建自定义组件并将它们连接到现有的 TFX 管道。一个简单的 Python 函数或容器可以转换为 TFX 组件,或者您可以像编写标准组件一样完全编写整个组件。有关更多详细信息,请查看 自定义组件指南

为了通过提供这些优势来提高生产力,我们将具有类似用例的自定义组件共享为 Karrot Market 的内部库,供我们的 ML 管道使用。

支持各种运行器

TFX 与各种环境兼容。它可以在您的笔记本电脑上本地运行,也可以在 DataFlow 上运行,DataFlow 是与 Apache Beam 兼容的 GCP 批量数据处理服务。您可以通过在 Jupyter Notebook 中手动运行每个组件来可视化输出。TFX 还支持 KubeFlow 和 Vertex AI,它们最近也发布了新功能。因此,管道代码只需编写一次,然后几乎可以在任何地方运行。我们可以同时轻松创建开发、实验和部署环境。因此,通过在我们的服务中使用 TFX,将模型部署到生产中的负担大大减轻。

技术经验教训

当我们使用 TFX 设置 ML 管道时,代码质量和我们在模型开发方面的经验都得到了提升。

但是,也有一些困难。我们的团队没有统一的项目结构或最佳实践。这可能是因为 TFX 本身相对较新,我们一直在使用它之前的版本 1。这使得代码更难理解,也更难开始贡献。随着管道越来越大越来越复杂,理解自定义组件、相应的配置值和依赖项的含义变得越来越困难。此外,将一些最新功能引入团队也很困难。

改进开发体验

我们决定为 TFX 管道创建和使用模板,以更轻松地理解彼此的代码、使用相同模式实现管道以及相互分享专业知识。我们将 Karrot 中经常使用的组件合并并放入共享库中,以便可以非常快速地开发 ML 管道。

预计该模板将加速新项目的开发。此外,如上所述,我们预计每个项目都将具有类似的结构,从而更轻松地理解彼此的项目。

到目前为止,我们简要介绍了模板项目。以下是一些我们在该项目中更好地利用 TFX 的考虑因素。

优先配置

我们优先考虑配置。通过阅读配置应该足以了解管道的工作原理。如果我们可以非常轻松地理解特定设置,那么我们可以设置各种实验并继续进行 A/B 测试。

example_gen_config.proto 以 Protocol Buffer(Protobuf)编写,表示配置的规范。config.pbtxt 保存值,pipeline.py 构建管道。

// config.pbtxt
example_gen_config {
    big_query_example_gen_config {
        query: "# query for example gen"
    }


    ...
}

...
// example_gen_config.proto
message ExampleGenConfig {
    oneof config {
        BigQueryExampleGenConfig big_query_example_gen_config = 1;
        CsvExampleGenConfig csv_example_gen_config = 2;
    }

    ...
}

// When BigQueryExampleGen is used
message BigQueryExampleGenConfig {
    optional string query = 1;
}

// When CsvExampleGenConfig is used
message CsvExampleGenConfig {
    optional string input_base = 1;
}
# pipeline.py
def create_pipeline(config):
   ...
   example_gen = _create_example_gen(config.example_gen_config)
   ...




def _create_example_gen(config: example_gen_config_pb2.ExampleGenConfig):
    ...

    if config.HasField("big_query_example_gen_config"):
        ...
        return ...


    if config.HasField("csv_example_gen_config"):
        ...
        return ...


    raise ...

ExampleGen 的所有配置都由单个 ExampleGenConfig 消息确定。类似地,所有管道组件都只依赖于其配置,并从这些配置创建。这样一来,您只需查看配置文件即可了解管道的结构。还有意通过分离定义每个组件的部分来使自定义和代码理解更容易。

例如,假设以下情况:为了在以后测试数据转换,Transform 组件需要支持各种数据处理方法。您可能希望在转换组件中添加数据增强过程。然后应该通过添加与数据增强函数相关的配置来完成。类似地,您可以扩展预定义的 Protobuf 规范,以轻松支持多种处理方法,并让您轻松查看要使用哪种处理方法。

使用 Protobuf 管理配置

关于上面的示例代码,有些人可能想知道为什么他们使用 Protobuf 作为配置工具。这样做有几个原因,我们将比较 Protobuf 与 YAML 的优势,YAML 是配置的常用做法之一。

首先,Protobuf 具有健壮的接口,类型检查等验证非常方便。由于 Protobuf 预先定义了对象结构,因此无需检查是否定义了任何字段。此外,它有助于在处于积极开发中的项目中支持向后/向前兼容性。

此外,您可以轻松检查管道结构。YAML 具有层次结构,但在机器学习生态系统中经常使用的 hydra 的情况下,阶段(例如生产、开发、alpha)设置被分成多个文件,因此我们认为 Protobuf 具有更好的稳定性和可视性。

如果您使用 Protobuf 作为项目设置工具,则可以重复使用 TFX 中定义的许多 Protobuf 定义。

带有 Bazel 的 TensorFlow 生态系统

Bazel 是一种与语言无关的构建系统,易于扩展,支持多种语言和工具。从简单的项目到使用多种语言和工具的大型项目,它可以在大多数情况下快速简洁地使用。有关更多信息,请参阅 Bazel 文档页面上的 Bazel Vision

在 Python 项目中使用 Bazel 是一种不常见的设置,但我们将 Bazel 用作 TFX 模板项目。下面简要介绍原因。

首先,它与 Protobuf 配合得很好。因为 Bazel 是一种与语言无关的构建系统,所以您可以轻松地将 Protobuf 构建工件作为依赖项与其他构建捆绑在一起,而无需担心。此外,Protocol Buffer 存储库本身使用 Bazel,因此它很容易集成到基于 Bazel 的项目中。

第二个原因是 TensorFlow 生态系统的特殊环境。TensorFlow 生态系统中的许多项目都使用 Bazel,而 TFX 也使用 Bazel,因此您可以使用 Bazel 轻松地将构建与其他项目(TensorFlow、TFX)链接起来。

内部自定义 TFX 模块

如前所述,我们一直在构建一个内部库,用于多个项目中经常使用的自定义 TFX 模块(尤其是自定义组件)。Karrot 中的任何人都可以添加他们的组件并与团队共享。

例如,我们使用 ArgoCD 在 Kubernetes 集群中管理应用程序(例如 TF Serving),因此如果有人开发了用于使用 ArgoCD 部署的组件,我们可以轻松地通过内部库共享它。该库现在包含多个用于我们团队的自定义模块,以提高生产力。

我们能够将自定义功能作为内部共享库共享的原因可能是由于 TFX 的模块化结构。通过这种方式,我们能够轻松地提高团队的整体生产力。我们可以重用从多个项目开发的大多数组件,并非常轻松地开发新项目。

结论

TFX 提供了许多很棒的功能来开发生产 ML 管道。我们在 Kubeflow 上使用 TFX 来开发、实验和以更好的方式部署 ML 管道,它为我们带来了许多好处。因此,我们决定在本博文中介绍我们如何使用 TFX。

要了解有关 Karrot 的更多信息,请查看我们的网站(韩国美国加拿大)。对于 TFX,请查看 TFX 文档页面

下一篇文章
Why Karrot Uses TFX, and How to Improve Productivity on ML Pipeline Development

由 Karrot 的 Ukjae Jeong、Gyoung-yoon Yoo 和 Myeonghyeon Song 发表 Karrot(韩国 Danggeun Market 的全球服务)是一款本地社区服务应用程序,它基于二手市场连接邻居。Danggeun Market 于 2015 年推出,韩国超过 2300 万人正在他们的本地社区使用 Danggeun Market。目前,Karrot 在 440 个本地社区运营……