Chronon — 一个用于开发机器学习模型的生产级特征的开源框架。本博客的目的是提供 Chronon 的核心概念的概述。
背景
爱彼迎在几乎每个产品中都使用机器学习,从搜索结果排序到房源智能定价以及将用户引导到正确的客服。
我们发现,对于这些项目的机器学习工程师来说,特征管理一直是一个痛点。他们把大量的时间花费在解决管理特征数据基础设施,而不是专注于机器学习模型,但是仍然会遇到其他问题。
一个常见的问题是在生成训练数据时所采用的记录和等待 (log-and-wait) 方法,机器学习工程师在服务端记录下特征值数据,然后等待积累足够的数据来训练模型。对于需要捕获季节性数据的模型,这个等待期可能会超过一年。这是机器学习从业者一个主要的痛点,影响了他们快速响应用户行为和产品需求的变化。
解决等待时间过长的常见方法是使用 ETL 任务将仓库中的原始数据转换为训练数据。然而,当机器学习工程师试图将他们的模型投入生产使用时,出现了另一个关键问题 —— 他们需要编写复杂的流处理任务或复制 ETL 逻辑来提供他们的特征数据,而且经常遇到提供模型推理的特征分布与他们训练数据保持一致。这样的在训练和服务 (training-serving) 时出现的数据偏经常差导致难以调试的模型退化,以及比预期的模型性能更差。
Chronon 就是解决这些痛点而开发的。它允许机器学习从业者定义特征并集中处理模型训练和生产推理的数据,同时保证两者之间的一致性。
介绍 Chronon
这篇文章主要介绍 Chronon 的 API 和功能。主要包括:
从各种来源输入数据 —— 事件流,仓库中的事实/维度表,表快照,缓慢变化维度表 (SCD),数据流等。
转换这些数据 —— 它支持标准的类 SQL 转换以及更强大的基于时间的聚合。
在线和离线产生结果 —— 在线,用于提供特征服务的低延迟接口,或者离线生产到Hive表,用于生成训练数据。
灵活选择更新结果 —— 你可以选择是否要实时更新特征值,或者通过设置 “accuracy” 参数选择在固定间隔内更新。回填 (Backfill) 时也保持一致。
Python API —— 它支持基于时间的聚合和窗口,同时保留了类似于 Group-By, Join, Select 等的 SQL 原语,并且保留了 Python 提供的灵活性和可组合性。
API 概述
首先,让我们从一个例子开始。以下代码片段计算了用户在活动流中最后五个小时内查看某个项目的次数,同时应用了一些额外的转换和过滤,用到了 GroupBy, Aggregation, EventSource 等概念。
在下面的部分中,我们将深入探索这些概念。
理解 Accuracy 参数
一些使用场景需要派生数据尽可能及时地更新,而一些其他的使用场景的则只需按日更新。例如,理解用户搜索的意图需要考虑尽可能及时的用户活动数据。而计算在报表使用的收入数字,通常只需要在固定间隔内刷新结果就足够了。
Chronon 允许用户通过设置计算的 ‘accuracy’ 来表达派生数据需要在近实时还是按日间隔更新,来选择是 ‘Temporal’ 还是 ‘Snapshot’。在 Chronon 中,accuracy 参数即应用于通过低延迟接口在线提供数据,也应用于通过批处理计算任务进行离线回填。
理解数据源
真实世界数据被连续不断地采集到数据仓库中。在 Chronon 中支持三种采集模式,通过声明数据源的“类型”来指定。
事件型数据源
像查看、点击、传感器读数、股票价格等带时间戳的活动事件 —— 发布到例如 Kafka 这样的数据流中。
在数据湖中,这些事件被存储在按日期分区的 Hive 表中。假设时间戳精确到毫秒,数据采集按日期分区 —— 一个日期分区 ‘2023–07–04’,包含了发生在 ‘2023–07–04 00:00:00.000’ 和 ‘2023–07–04 23:59:59.999’ 之间的点击事件。用户可以根据你的仓库设置,全局配置一次日期分区,作为 Spark 参数。
— conf "spark.chronon.partition.column=date_key"
在 Chronon 中,你可以通过指定 Hive ‘Table’ 和可选的 Kafka ‘Topic’ 来声明一个 EventSource。当 accuracy 设置为 Temporal 时,Chronon 可以使用‘表’来回填数据。当提供了一个 ‘Topic’ 时,Chronon 可以实时更新键值对,为应用程序和 ML 模型提供实时的数据。
实体型数据源
与业务实体相关的属性元数据。例如在零售业中,用户信息 —— 具有地址、国家等属性,或者商品信息 —— 具有价格、可用数量等属性。这些数据通常通过像 MySQL 这样的 OLTP 数据库提供给在线应用程序。这些表通常以每日间隔的方式快照到仓库中。所以一个 ‘2023–07–04’ 的分区包含了在 ‘2023–07–04 23:59:59.999’ 记录的商品信息表的快照。
然而,这些快照只能支持 ‘Snapshot’’ 精度的计算,但对于 ‘Temporal’ 精度来说是不够的。如果你有一个变更数据捕获 (change data capture) 机制,Chronon 可以利用表的变更数据流来维护计算的近实时刷新视图。如果你也在你的仓库中捕获这个变更数据流,Chronon 可以在历史时间点回填 ‘Temporal’ 精度的计算。
你可以通过指定 ‘snapshotTable’ 和可选的 ‘mutationTable’ 和 ‘mutationTopic’ 来创建一个实体数据源,以获取 ‘Temporal’ 精确度的数据。当你指定 ‘mutationTopic’ (实体变更数据流) 时,Chronon 能够维护一个延时的实时更新视图。当你指定 ‘mutationTable’ 时,Chronon 能够在历史时间点以毫秒精度回填数据。
累积事件型数据源
这种数据模型通常用于采集缓慢变化维度的值历史数据。除了唯一标识符之外,基础数据库表的条目只插入从不更新(SCD2)。
累积事件型数据源也使用与实体源相同的机制保存快照数据到数据仓库中。但是因为它们在快照中跟踪了所有的变化,所以只需要最新的分区就足够回填计算。并且不需要 ‘mutationTable’。
在 Chronon 中,你可以通过创建一个事件源,并指定 ‘Table’、‘Topic’ 和启用 ‘isCumulative’ 标志来定义一个累积事件源。‘Table’ 是应用程序流量服务的在线数据库表的快照。‘Topic’ 是包含所有插入事件的数据流。
理解计算环境
Chronon 可以在两种环境中进行计算,即在线和离线,并使用相同的计算规则。
离线计算是在仓库数据集(Hive 表)上使用批处理作业完成的,这些作业会输出新的数据集。Chronon 是为处理变化的数据集而设计的 - 新到达的数据以 Hive 表分区的形式进入仓库。
在线计算是用于为低延迟(约10ms)和高 QPS 的应用程序提供服务。Chronon 通过生成 “lambda架构” 的 pipeline 维护了可以提供实时更新的特征数据的接口。你可以在 Python 中设置一个参数 “online = True” 来启用此功能。
在底层,Chronon 使用 Kafka,Spark/Spark Streaming,Hive,Airflow 和可定制的 key-value 存储来管理 pipeline,为在线系统和训练数据生成提供服务。
理解计算类型
所有的 Chronon 计算都分为三类 - GroupBy,Join 和 StagingQuery。
GroupBy — 是一个与 SQL 类似的聚合操作,支持窗口聚合和分桶聚合。它同时支持在线和离线环境以及两种精度模式 - Temporal(实时刷新)和 Snapshot(每日刷新)的计算。GroupBy 根据 keys 进行聚合。
Join — 将来自各种 GroupBy 计算的数据连接在一起。在在线模式下,使用 keys 来连接的语句被分发到每个 groupBy 和外部服务的查询,计算结果将被连接在一起并作为 map 返回。在离线模式下,连接可以被认为是多个历史时间点的查询,因此需要使用正确的时间点计算结果。如果连接左侧是 Entities,Chronon 则选用零点的数据计算结果。
StagingQuery — 允许使用 Spark SQL 表达的任意计算,该计算每天离线计算。Chronon 生成分区数据集。主要适用于数据预处理或后处理。
理解聚合
Chronon 中的 GroupBy 本质上是按给定键聚合数据。通过扩展传统的 SQL group-by,Chronon 提供强大的聚合操作。
Windows — 你可以选择只聚合在一个窗口时间内的数据。这对于机器学习至关重要,因为未窗口化的聚合倾向于增长和改变数据的分布,降低模型性能。最近的事件比非常旧的事件更加重要。
Bucketing — 你也可以选择指定一个第二级的聚合,即在 Group-By 键之外的一个桶 。bucket 聚合的输出是一列映射类型,用于 bucket 的列作为键和聚合后的结果作为值。
Auto-unpack — 如果输入列包含嵌套在数组中的数据,Chronon 会自动解包。
基于时间的聚合 — 当在数据源中指定了时间戳时,像 first_k,last_k,first,last 等。
你可以灵活地组合所有这些选项来定义非常强大的聚合。Chronon 会在内部维护部分聚合结果,并将它们组合起来在不同的时间点生产特征值,所以可以用户处理非常大的时间窗口和回填长时间段的训练数据。
总结
作为用户,你只需要设定你的计算规则一次,Chronon 就会生成所有需要的基础设施,持续地将原始数据转化为训练和在线服务的特征值。爱彼迎的机器学习工程师不再需要花费数月的时间尝试手动实现复杂的管道和特征索引。他们通常花费不到一周的时间就能为他们的模型生成新的特征值集。
我们的核心目标是使特征工程尽可能地高效和可扩展。自从 Chronon 发布以来,用户已经开发了超过四万个特征值,为爱彼迎的机器学习模型提供强大支持。
查看 https://chronon.ai 或 https://github.com/airbnb/chronon 了解更多关于 Chronon 的开源信息。若有开源相关的问题,您可以通过电子邮件与相关成员取得联系:pengyu.hou@airbnb.com
作者:Nikhil Simha Raprolu
译者:Keyao Yang
校对:Pengyu Hou
如果你想了解关于爱彼迎技术的更多进展,欢迎关注我们的 Github 账号(https://github.com/airbnb/) 以及微信公众号(爱彼迎技术团队)