简介
本文深入探讨了 MLOps 的世界,并探索了特征存储:不同类型、可能需要特征存储的原因以及主要组件。在此基础上,我们介绍了如何使用 ClickHouse 来驱动特征存储,从而驱动模型生命周期,提供性能和灵活性。
此博客主要对主题进行入门介绍,旨在作为后续使用驻留在 ClickHouse 中的特征训练机器学习模型示例的先驱。作为此处潜力的证明,我们确实展示了我们最近与 Featureform 的集成 - 一个开源的“虚拟”特征存储,我们将在未来的示例中使用它。
什么是特征?
在讨论特征存储是什么之前,澄清特征是什么可能会有所帮助。
简单来说,特征是实体的某些属性,对机器学习 (ML) 模型具有预测能力。从这个意义上说,实体是特征的集合以及表示现实世界概念的类别或标签。如果特征质量足够高,并且存在这种关系,则这些特征应该有助于预测实体的类别。例如,银行交易可以被视为一个实体。这可能包含诸如交易金额和购买/卖家等特征,其中类别描述交易是否欺诈。
开发特征通常需要一些先期的数据工程步骤和数据转换逻辑,然后才能使用这些特征。然后,它们可以在训练模型或从中推断结果(进行预测)时使用。在前一种情况下,许多特征(和实体)将被组合并作为训练数据(通常规模很大)公开,并用于训练模型。在后一种推理情况下,模型将使用仅在预测时可用的数据作为特征,例如欺诈预测情况下的交易详细信息。其他特征可能来自与训练数据相同的来源,但包含最新值,例如用户的账户余额。
以上假设特征始终可以在推理时根据需要构建,并使用与训练时类似的转换。由于延迟要求,这有时是不可能的,因此通常需要在“在线”存储中缓存和预处理某些特征的最新版本。
训练一个能够以任何 准确率 进行预测的模型几乎总是(有时除了深度学习之外)需要数据科学家仔细选择与要预测的类别相关的特征。
什么是特征存储?
最简单的形式,特征存储是用于存储和管理特征数据并充当真相来源的集中式存储库。
通过提供允许存储、版本控制和检索特征的 API,特征存储旨在为从开发到生产环境的训练和推理提供特征的一致视图。无论是在内部构建的自定义解决方案还是现成的产品,特征存储提供的实际产品级功能都会有所不同,有些功能提供了一个完整的数据平台,能够将数据聚合成特征,甚至提供用于模型训练的计算引擎 - 请参阅下面的 特征存储类型。其他功能提供了一个更轻量级的抽象,管理元数据和版本控制,但将训练和数据/特征存储推迟到它们集成的其他平台和数据库。
无论特征存储本身具有多少功能,所有特征存储都为数据科学家和工程师熟悉的基础数据提供了抽象。除了将数据作为版本化的实体、特征和类别交付之外,大多数特征存储还公开了特征组、训练集、批处理、流处理和时间点查询的概念(例如,能够识别特定时间点的特征值,例如最新值)。
为什么你可能需要使用它?
理论上,特征存储将不同的系统和功能结合在一起,形成一个完整机器学习数据层,既可以作为训练数据的真相来源,也可以在进行预测时提供上下文。
虽然它们提供的具体功能各不相同,但目标保持不变
- 改进数据科学家和数据工程师之间的协作和可重用性,方法是集中特征及其转换逻辑
- 减少模型迭代时间,方法是在训练和推理时允许在实验和部署期间重复使用特征
- 治理和合规性,通过规则和版本控制,可以限制模型访问敏感数据(和特征)
- 提高模型性能和可靠性,方法是将数据工程的复杂性从数据科学家那里抽象出来,并确保他们仅使用通过 API 提供的质量一致的特征。
虽然这些代表了对特征存储解决的一些问题的非常高级别的概述,但这里的主要好处是能够跨团队共享特征,并利用相同的数据进行训练和推理。
特征存储还解决了 MLOps 中的其他一些挑战,例如如何回填特征数据、如何处理源数据的增量更新(以更新特征)或监控新数据是否存在漂移。最近,它们还集成了向量数据库,以充当 RAG 管道的编排层,或帮助使用嵌入查找类似特征 - 这在某些模型训练期间很有用。
那么,你真的需要一个吗?
在决定是使用现成的特征存储还是构建自己的特征存储时,该决定可能取决于几个因素(在我们看来)
-
现有工具 - 如果你使用了一个完整的机器学习平台,那么你可能不需要特征存储。这些功能中的大部分都是此类平台的子集。但是,这些平台通常灵活性最低,并且采用成本最高、最复杂。相反,如果你正在使用一组不同的系统和工具来实现机器学习训练和推理过程的不同部分,那么它可能是有意义的。
-
复杂度和规模 - 虽然机器学习模型训练不一定是您业务的基础,但您可能需要相当数量的数据集、模型和数据科学家来证明额外的复杂性是合理的。虽然对于较小的用例,可能可以通过临时的方式来处理,但将更大、更关键的任务模型迁移到生产环境中,则需要更强的治理和更强大的管道。
-
抽象的好处 - 特征存储提供的抽象对某些团队的好处大于其他团队。如果您拥有角色非常不同的数据科学家和数据工程师,那么特征存储可能带来的关注点分离可能很有吸引力。在这种情况下,工程师可以通过简单的 API(使用他们理解的术语)将特征交付给数据科学家,而数据科学家则无需了解特征准备过程。
相反,如果您的数据科学家熟悉特征工程,那么提供的抽象可能带来的好处较少。例如,假设您的数据驻留在与 SQL 兼容的数据库或数据湖中(可以通过查询引擎访问),则可以通过 dbt 等工具管理转换。这将要求您的数据科学家直接在 SQL 中查询表,但这可能就足够了,dbt 提供了转换的版本控制和文档。但是,这确实意味着您需要使用特定的点解决方案来解决机器学习运维的许多其他挑战。
特征存储的组件
在我们探讨 ClickHouse 如何融入特征存储之前,了解常见组件有助于理解上下文。通常,特征存储将包含最多 4 个主要组件
- 数据源 - 虽然这可以像 CSV 文件一样简单,但它通常是数据库或数据湖,其中包含 Iceberg 等格式的文件,并且可以通过查询引擎访问。
- 转换引擎(可选) - 原始数据需要转换为特征。在简单的情况下,特征可以与列的值相关联。更有可能的是,它是转换过程的结果,该过程涉及连接、聚合和表达式,从而改变列值的结构和/或类型。一些特征存储(请参阅特征存储类型)可能会提供内置功能来实现此目的;其他存储可能会将工作卸载到本地 Python 函数,或者对于较大的数据集,通过物化或 Spark 等处理引擎卸载到数据库(甚至可能在幕后使用 dbt)。使用 ClickHouse,这可以通过物化视图实现。持续更新的特征通常需要某种形式的流式管道,通常使用 Flink 或 Spark Streaming 等工具实现。通常,如果这些转换是链接的并且需要跟踪依赖关系,则需要某种形式的有向无环图 (DAG)。
- 离线(训练)存储 - 离线存储保存先前转换管道产生的特征。这些特征通常被分组为实体并与标签(目标预测)相关联。通常,模型需要选择性地使用这些特征,无论是迭代地还是通过聚合,都可能多次且以随机顺序进行。模型通常需要多个特征,这需要将特征组合到“特征组”中 - 通常通过实体 ID 和时间维度。这要求离线存储能够为特定时间点提供特征和标签的正确版本。“时间点正确性”通常对模型至关重要,因为模型需要增量训练。
- 在线(推理)存储 - 模型训练完成后,可以部署并用于进行预测。此推理过程需要的信息仅在预测时可用,例如交易的用户 ID。但是,它也可能需要用于预测的特征,这些特征可能是预先计算的,例如表示历史购买的特征。即使对于 ClickHouse 来说,这些特征在推理时计算成本也往往过高。这些特征需要在延迟敏感的情况下提供服务,基于数据的最新版本,尤其是在需要实时进行预测的场景中,例如欺诈检测。可以将特征从离线存储物化到在线存储以供服务。
以上省略了一些组件,虽然这些组件不一定是特征存储的一部分,但它们与任何机器学习管道都密切相关并且是必需的
- 训练引擎和模型托管 - 任何管道都需要一个计算框架和引擎,用于使用离线存储中的特征训练模型。然后,此模型需要进行版本控制和托管,以便可以调用它来进行推理。一个模型注册表可以成为此过程中的重要组成部分,提供模型血缘、版本控制、标记和注释。
- 向量数据库 - 我们在之前的博文中探讨了向量搜索及其在RAG 工作流中的应用。虽然传统上不是特征存储的组件,但它们与在线存储有相似之处。通常,向量嵌入将与存储中存在的实体相关联。然后,数据库可以在经典的 RAG 工作流中部署,或用于识别类似的特征 - 这在训练和推理时都很有用。
所有这些都需要某种形式的状态管理,例如跟踪特征版本。这通常是存储的本地状态,并且通常相对于源数据和特征本身来说很小。
特征存储类型
并非所有特征存储都直接提供上述组件,它们在提供的灵活性和功能方面有所不同。例如,有些存储可能具有现有的转换引擎,并部署 Postgres 等数据库作为离线存储或 Redis 作为在线组件。因此,需要一定程度的架构灵活性和开放性才能将 ClickHouse 集成到特征存储中。
我们将在下面探讨这些差异以及它们如何与 ClickHouse 共存。有关虚拟特征存储与替代方案(文字存储和物理存储)之间差异的更详细说明,我们推荐 Featureform 的优秀博文。
物理存储
物理存储提供了一种更集成的解决方案,用于计算和存储特征。这种类型的存储在 Tecton 等专有供应商中很常见,通常包含一个转换引擎,以及集成的在线和离线存储,以及一些流式功能。通常,它们与外部数据存储集成,并且可以将一些工作推送到这些存储,例如用于数据子集选择。在这种情况下,用户正在投资一个完整的解决方案,而灵活性有限。这种缺乏灵活性在历史上可以通过更高的性能来弥补。与文字存储相比,用户也需要学习的技术少得多,但代价可能是潜在的供应商锁定。
Tecton 架构 - 版权所有:https://www.tecton.ai/
在此架构中,ClickHouse 充当训练数据的源存储库,集成机会很少。
文字存储
在文字存储中,特征是在存储外部处理的,存储仅充当集中式存储库。特征通常发送到离线存储,并将这些特征物化到在线存储的过程留给用户。然后,这些特征被用于推理,并提供通常如上所述公开的时间点正确性功能。从这个意义上说,特征存储是一个实际的数据存储,其范围仅限于存储和服务特征,同时位于实际的真实数据存储之上。此架构的经典实现是Feast。这种方法提供了最大的灵活性,但同时也给采用者带来了最大的负担,他们需要构建从源生成特征的转换管道。在这里,用户必须学习和连接各种技术才能构建强大的 MLOps 管道。
Feast 架构 - 原文:https://feast.dev/
虽然 ClickHouse 可以用作文字存储的存储引擎,但这种类型的特征存储无法充分利用 ClickHouse 的功能。ClickHouse 不仅可以用于存储和服务特征。虽然文字存储用户可以潜在地使用 ClickHouse 进行存储外部的转换,但它没有提供集成的体验。
虚拟存储
Featureform 是一个开源项目,它将自己描述为“虚拟特征存储”。Featureform 提出了虚拟存储的概念,作为上述架构之间的平衡。在这种情况下,用户可以在其基础设施中使用任何他们选择的存储、转换和流式引擎。特征存储负责管理转换以及特征的持久性和版本控制,但仅充当协调器。这种插件架构让采用者可以为每个组件选择他们首选的技术,从而让他们获得类似物理存储的集成体验的优势,同时保持与文字存储相关的灵活性。从这个意义上说,虚拟存储可以被认为是一个工作流管理和协调层,确保为每个角色使用最佳技术,同时使用数据科学家和工程师习惯的相同抽象。
Featureform 架构 - 版权所有:https://www.featureform.com/
使用 ClickHouse 的虚拟存储
此架构的传统实现可能会牺牲一部分物理存储的性能,以提供同等水平的协调和管理,同时保留文字存储的相同灵活性。这种灵活性还会带来一些部署成本,异构架构本质上具有更大的 DevOps 开销。但是,通过使用 ClickHouse 为架构的重要组件提供支持,用户可以实现优于更异构架构的性能并降低管理开销。特征缩放和相关矩阵计算等昂贵的操作可以在 PB 级数据集上以秒为单位完成。灵活性也仍然保留 - 如果用户希望替换 ClickHouse,他们可以自由地这样做,同时仍然保留一致的版本控制方案和特征定义的集中式跟踪。
特征存储和 ClickHouse
作为实时数据仓库,ClickHouse 可以承担许多组件的角色 - 这可能大大简化特征存储架构。
具体来说,ClickHouse 可以充当
-
数据源 - ClickHouse 能够查询或摄取超过 70 种不同的文件格式,包括 Iceberg 和 Delta Lake 等数据湖格式,这使得它成为存储或查询数据的理想长期存储。通过使用对象存储分离存储和计算,ClickHouse Cloud 还允许无限期地保存数据 - 将计算缩减或完全闲置以最大程度地降低成本。灵活的编解码器,加上面向列的存储和磁盘上的数据排序,最大限度地提高了压缩率,从而最大限度地减少了所需的存储空间。用户可以轻松地将 ClickHouse 与数据湖结合使用,并使用内置函数在对象存储中查询数据。
-
转换引擎 - SQL 提供了一种声明数据转换的自然方式。当与 ClickHouse 的分析和统计函数扩展时,这些转换变得简洁且优化。除了应用于 ClickHouse 表之外,在将 ClickHouse 用作数据存储的情况下,表函数允许针对以 Parquet、磁盘或对象存储等格式存储的数据编写 SQL 查询,甚至针对其他数据存储(如 Postgres 和 MySQL)编写 SQL 查询。一个完全并行的查询执行引擎,结合面向列的存储格式,允许 ClickHouse 在几秒钟内对 PB 级数据执行聚合 - 与内存中数据帧上的转换不同,用户不受内存限制。此外,物化视图允许在插入时转换数据,从而将计算负载从查询时间转移到数据加载时间。这些视图可以利用相同的分析和统计函数范围,非常适合数据分析和汇总。如果 ClickHouse 的任何现有分析函数不足或需要集成自定义库,用户还可以利用用户定义函数 (UDF)。
虽然用户可以直接在 ClickHouse 中或使用 SQL 查询在插入之前转换数据,但 ClickHouse 也可以在 Python 等编程环境中使用,例如通过 chDB 的 Python。这允许将嵌入式 ClickHouse 作为 Python 模块公开,并用于在笔记本中转换和操作大型数据帧。这允许数据工程师在客户端执行转换工作,结果可能以集中式 ClickHouse 实例中的特征表的形式物化。
-
离线存储 - 凭借上述从多个来源读取数据并通过 SQL 应用转换的功能,这些查询的结果也可以通过
INSERT INTO SELECT
语句持久化到 ClickHouse 中。由于转换通常按实体 ID 分组并返回多个列作为结果,因此 ClickHouse 的模式推断可以自动检测这些结果所需的类型并生成相应的表模式以存储它们。用于生成随机数和统计抽样的函数允许高效地迭代和扩展数据,每秒可达数百万行,以供模型训练管道使用。通常,特征以表格形式表示,其中包含一个时间戳,指示特定时间点实体和特征的值。如前所述,训练管道通常需要特定时间点和组中特征的状态。ClickHouse 的稀疏索引允许快速过滤数据以满足时间点查询和特征选择过滤器。虽然 Spark、Redshift 和 BigQuery 等其他技术依赖于缓慢的有状态窗口化方法来识别特定时间点特征的状态,但 ClickHouse 支持 ASOF(截至此时)LEFT JOIN 查询和 argMax 函数。除了简化语法之外,这种方法通过使用排序和合并算法在大型数据集上具有很高的性能。这允许快速构建特征组,减少训练前的准备时间。
所有这些工作都可以下推到 ClickHouse,并行化并在集群中执行。这使得离线存储可以扩展到 PB 级,而特征存储本身仍然是一个轻量级的协调层。
-
在线存储 - 作为实时分析数据库,ClickHouse 可以以低延迟服务高并发查询工作负载。虽然这需要数据通常非规范化,但这与在训练和推理时使用的特征组的存储相一致。重要的是,ClickHouse 能够在承受高写入工作负载的同时提供此查询性能,这要归功于其日志结构合并树。在线存储需要这些属性来保持特征的最新状态。由于特征已存在于离线存储中,因此它们可以轻松地物化到同一 ClickHouse 集群或不同实例中的新表中,例如通过现有功能 e.g. remoteSecure。
通过精确一次的 Kafka Connect产品或通过ClickHouse Cloud 中的 ClickPipes,与 Kafka 的集成也使得从流式源消费流式数据变得简单可靠。
对于需要非常高请求并发性(例如每秒数千次)和非常低延迟的用例,我们建议用户仍然考虑使用专用的数据存储(例如 Redis),这些数据存储专为这些工作负载而设计。
- 向量数据库 - ClickHouse 通过浮点数组内置支持向量嵌入。可以通过距离函数搜索和比较这些向量,从而允许 ClickHouse 用作向量数据库。这种线性比较可以轻松地扩展和并行化以处理更大的数据集。此外,ClickHouse 对近似最近邻 (ANN)索引以及使用纯 SQL 的超平面索引提供了日益成熟的支持,这是处理更大向量数据集所必需的。
通过满足上述每个角色,ClickHouse 可以极大地简化特征存储架构。除了简化操作外,此架构还允许更快地构建和部署特征。ClickHouse 的单个实例可以垂直扩展以处理 PB 级数据,并可以简单地添加其他实例以实现高可用性。这最大限度地减少了数据存储之间的数据移动,最大限度地减少了典型的网络瓶颈。ClickHouse Cloud 通过仅在对象存储中存储数据的单个副本并允许节点根据需要动态垂直或水平扩展以响应负载,进一步扩展了这一点。
上述架构仍然需要 ClickHouse 未满足的一些关键组件:例如 Kafka + Flink 等流式引擎和用于提供模型训练计算的框架。还需要一种托管模型的方法。为简单起见,我们假设使用云托管解决方案来解决这些问题,例如 Confluent 和 Amazon SageMaker。
ClickHouse Featureform 集成
为了实现我们由 ClickHouse 加速的虚拟特征存储的愿景,我们确定 Featureform 是理想的集成解决方案。Featureform 除了是开源的(因此我们可以轻松地做出贡献)之外,还为离线存储、在线存储和向量数据库提供了成熟的(设计好的)集成点。
对于我们的初始集成,我们已将 ClickHouse 添加为离线存储。这代表了最大的工作量,并允许 ClickHouse 用作数据源和特征和训练集的主要存储。用户还可以利用 ClickHouse 在创建特征组和从其他来源插入数据时为转换提供支持。
这代表了我们首次尝试与 Featureform 集成。期待很快能够将 ClickHouse 用作在线存储和向量数据库!
结论
在这篇博文中,我们介绍了特征存储的概念及其在 MLOps 工作流中的使用。我们探讨了为什么要使用特征存储、主要类型的特征存储及其核心架构组件。在此基础上,我们介绍了如何将 ClickHouse 作为高性能实时数据仓库用于为“虚拟”特征存储的多个组件提供支持,并宣布了最近与 Featureform 的集成作为一个示例。
在本系列的下一篇博文中,我们将探讨使用 Featureform 和 AWS Sagemaker 训练模型,以及将数据和特征保存在 ClickHouse 中!