Karrot为什么使用TFX以及如何提高ML管道开发的生产力

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

我们也在努力研究如何有效和高效地应用ML模型。特别是,我们正在投入大量精力建立机器学习管道,用于定期部署、快速实验和持续改进模型。

对于ML管道,我们一直在使用TFX(TensorFlow Extended)进行生产。因此,在这篇文章中,我们将简要介绍我们为什么使用TFX,以及我们如何利用TFX来提高生产力。

Karrot中的机器学习

在Karrot内部有许多ML项目。ML模型在服务内部运行。例如,我们使用自动化模型来检测欺诈行为,还有推荐模型来改善我们应用程序上的用户体验。如果你对这些模型的详细描述感兴趣,请参考我们的团队博客,这些博客是用韩语写的。

由于我们一直在使用Kubeflow来处理我们的ML模型,我们能够定期地训练、实验和部署模型,但仍然有一些痛点。随着我们去年开始将TFX与Kubeflow一起使用,TFX进一步推动了这条线路,让团队轻松使用我们的生产管道。

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

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

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

标准组件

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

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

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

组件的可重用性

为了使TFX适应我们的产品,需要定制组件。TFX有一个结构良好的组件设计,使我们能够自然地创建自定义组件,并轻松地将它们连接到现有的TFX管道。一个简单的Python函数或容器可以转化为TFX组件,或者你可以用与标准组件完全相同的方式编写整个组件。更多细节,请查看自定义组件指南

为了通过提供这些优势来提高我们的生产力,我们在我们的ML管道中分享有类似使用情况的自定义组件,作为Karrot Market的内部库。

支持各种运行程序

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

技术教训

随着我们用TFX建立起我们的ML管道,代码质量和我们在模型开发方面的经验都有所提高。

然而,也有一些困难。我们的团队中没有统一的项目结构或最佳实践。也许这是因为TFX本身比较新,我们在第一版之前就已经在使用它了。理解代码和开始贡献变得更加困难。随着管道越来越大,越来越复杂,越来越难理解自定义组件的含义、相应的配置值和依赖性。此外,向团队介绍一些最新的功能也很困难。

改善开发经验

我们决定为TFX管道创建并使用一个模板,以便更容易理解对方的代码,以相同的模式实现管道,并相互分享专业知识。我们合并了Karrot中经常使用的组件,并把它们放在一个共享库中,这样就可以非常迅速地开发ML管道。

预计该模板将加速新项目的开发。此外,如上所述,我们期望每个项目都有一个类似的结构,使之更容易理解彼此的项目。

到目前为止,我们已经简单地介绍了模板项目。下面是我们为了在这个项目中更好地使用TFX的一些考虑。

配置第一

我们优先考虑我们的配置第一。通过阅读管道的配置,应该足以了解管道如何工作。如果我们能够非常容易地理解具体的设置,我们就可以设置各种实验,并进行AB测试。

example_gen_config.proto 写在协议缓冲区(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作为配置工具。这有几个原因,我们将与YAML比较优势,YAML是配置的常见做法之一。

首先,Protobuf有一个健壮的接口,而且类型检查等验证工作也很方便。由于Protobuf事先定义了对象结构,所以不需要检查是否有任何字段被定义。此外,在一个正在开发的项目中,支持前向/后向兼容是非常有用的。

另外,你可以很容易地检查管道结构。YAML 具有分层结构,但在机器学习生态系统中经常使用的 hydra 的情况下,阶段(如生产、开发、阿尔法)设置被分为几个文件,所以我们认为 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模块(特别是自定义组件)建立一个内部库。卡洛特的任何人都可以添加他们的组件并与团队分享。

例如,我们正在使用ArgoCD来管理Kubernetes集群中的应用程序(如TF Serving),因此,如果有人开发了一个用于与ArgoCD部署的组件,我们可以很容易地通过内部库分享它。这个库现在包含了几个自定义模块,供我们的团队提高工作效率。

我们之所以能以内部共享库的形式分享我们的定制功能,可能要归功于TFX的模块化结构。通过这一点,我们能够轻松提高团队的整体生产力。我们可以重复使用从几个项目中开发的大部分组件,并非常容易地开发新项目。

总结

TFX为开发生产型ML管线提供了很多很棒的功能。我们在Kubeflow上使用TFX进行ML管道的开发、实验,并以更好的方式进行部署,它给我们带来了很多好处。所以我们决定在这篇博文中介绍我们是如何使用TFX的。

猜你喜欢

转载自juejin.im/post/7125719932980969485