维护可复现性并支持安全迭代是管理生产机器学习系统的重要方面。在特征存储中,它作为特征定义和值的中心,建立清晰的版本控制策略对达成这些目标很重要。如果没有版本控制,诊断模型性能衰退、确保合规性或回滚有害更改将变得非常困难。本节详细介绍了对特征存储体系中不同组件进行版本控制的实用策略。
为何版本控制在特征存储中很重要
版本控制提供了诸多益处:
- 可复现性: 它让您能够重新生成用于特定模型版本的精确特征数据,这对于调试、审计和再训练是必要的。
- 回滚: 如果新的特征定义或计算逻辑引入错误或对模型性能产生负面影响,版本控制能快速回退到之前的稳定状态。
- 实验与迭代: 数据科学家和工程师可以创建新的特征版本,以尝试新的特征逻辑,而不影响生产流程。
- 审计与合规: 版本历史提供了特征如何随时间定义、计算和使用的清晰审计路径,支持管理和合规要求。
- 协作: 清晰的版本控制可在多个团队或个人处理相关特征时避免冲突。
需要版本控制的项
有效的特征存储版本控制需要考虑多个相关产物:
- 特征定义: 这包括描述特征的元数据:其名称、数据类型、描述、所有者、源数据引用,以及可能的标签或文档链接。这里的更改可能涉及修改描述或更改源表。
- 转换逻辑/代码: 这是用于从源数据计算特征值的实际代码(例如,SQL查询、Python函数、Spark作业)。对逻辑的更改,即使是微小的更改,也应触发新版本。
- 特征数据(逻辑或物理): 尽管特征存储主要管理定义并促进计算,但理解所用数据的版本很重要。这可能意味着引用特定数据快照、时间旅行查询,或离线存储中对应特征定义版本的分区。在线存储通常包含最新值,但与生成数据所用的版本化定义之间的关联很重要。
- 特征组/特征视图模式: 一起定义的特征集合(通常称为特征组或特征视图)也有一个可能演变的模式。在组内添加、删除或修改特征构成模式更改,通常需要对组定义本身进行版本控制。
常见版本控制策略
选择合适的版本控制策略取决于您的团队工作流、所用特征存储技术以及您的操作要求。以下是常见方法:
1. 定义和代码的语义化版本控制
与软件版本控制类似,您可以将语义化版本控制(例如 MAJOR.MINOR.PATCH)应用于特征定义及其相关的转换代码。
- MAJOR(主版本): 对于不兼容的更改(例如,更改特征的基本含义或数据类型,从组中删除特征)递增。使用此特征的模型可能需要重新训练或修改。
- MINOR(次版本): 以向后兼容的方式添加功能(例如,向组添加新特征,引入新的可选转换参数)时递增。现有模型可能仍能运行,但可能从重新训练中获益。
- PATCH(补丁版本): 对于转换逻辑中不改变预期特征定义的向后兼容的错误修复(例如,修复窗口函数中的“差一”错误,优化计算)时递增。使用先前补丁版本的模型理想情况下应产生非常相似的结果。
这种方法要求在版本号应用上严谨的规范,并就更改的性质进行清晰的沟通。与Git集成以进行转换代码管理,可以实现将特征定义版本与特定代码提交关联起来。
2. 不可变特征版本
在此策略中,对定义或转换逻辑的任何更改都会导致创建全新的、唯一标识的特征版本(例如,使用UUID或内容哈希)。旧版本保持不变并可用。
- 优点: 提供可复现性最强保障。简化了对依赖关系的理解,因为特定版本ID总是指完全相同的定义和逻辑。
- 缺点: 可能导致版本激增,可能增加元数据管理复杂性。需要垃圾回收或归档旧的、未使用版本以管理成本并减少杂乱的机制。本身不指示更改的类型(错误修复与重大更改),除非有额外元数据。
此方法通常在高度管制的场景或绝对可复现性是首要任务的环境中优先选用。
3. 基于时间的版本控制和时间点正确性
此策略侧重于获取特征值在特定时间点上的状态,这与版本控制本身紧密关联。它很大程度上依赖于离线存储的能力。
- 实现: Apache Hudi、Delta Lake或Apache Iceberg等离线存储支持时间旅行查询。特征定义可以与它们活跃的时间范围相关联。当为在时间 T 之前的数据上训练的模型生成训练数据时,特征存储会使用在时间 T(或稍早,考虑数据延迟)有效的定义和逻辑,查询离线存储“截至”时间 T 的数据。
- 版本控制关联: 对特征定义或逻辑的更改会记录时间戳。对时间 T 的特征请求将解析为在该时间点活跃的定义/逻辑版本。
- 优点: 直接解决时间点正确训练数据的需求。与数据仓库实践契合良好。
- 缺点: 依赖底层存储技术高效支持时间旅行。管理将定义版本与时间范围关联的元数据需要在特征存储注册库中仔细实现。
4. 策略组合
通常,混合方法最实用。例如:
- 对定义和转换代码使用语义化版本控制或不可变ID。
- 依靠离线存储的时间旅行能力,获取与训练集生成所需特定时间戳对应的数据版本。
- 明确将特定模型版本链接到训练时所用特征定义/代码的版本ID。
流程图展示了特征定义和代码如何进行版本控制(可能通过注册库中引用的Git提交),如何计算、存储(离线存储具备时间旅行能力)和使用,用于时间点训练和低延迟服务,并将特定模型版本与特征定义版本关联起来。
将版本控制集成到MLOps工作流中
特征版本控制不应孤立存在。它必须集成到更广泛的MLOps实践中:
- 特征的CI/CD: 特征定义和代码更改应通过自动化CI/CD管道。这些管道应进行代码检查、测试(转换单元测试、数据验证测试),并在成功合并到主分支后自动分配或递增版本。部署可能涉及在特征注册库中注册新版本,并可能触发初始计算或回填。
- 模型训练: 训练管道必须记录所用所有特征(或特征组/视图)的精确版本。这种关联是重要的元数据,与训练好的模型产物一起存储在模型注册库中。
- 模型部署: 部署系统应验证所需的特征版本在生产环境(根据需要包括在线和离线存储)中是否可用,然后再部署依赖于它们的模型版本。
- 监控: 监控系统应了解特征版本,以便将特征分布或模型性能的变化与特定特征更新关联起来。
挑战与考量
- 依赖管理: 特征通常源自其他特征。管理这些有向无环图(DAGs)中的版本依赖关系可能很复杂。上游特征的更改可能需要创建所有下游特征的新版本。
- 版本激增: 特别是对于不可变策略,版本数量可能迅速增加。需要有效的工具、命名约定和生命周期管理(归档/删除策略)。
- 一致性: 确保离线训练所用版本与在线服务可用版本匹配,需要仔细协调和验证,尤其是在将新版本推广到生产环境时。
- 工具支持: 实现这些策略的难易程度很大程度上取决于您所选的特征存储框架或平台的能力。评估不同工具如何处理元数据注册、版本链接以及与存储层的集成。
总而言之,实施深思熟虑的特征版本控制策略是构建可靠且可维护的机器学习系统不可或缺的方面。通过对定义、代码以及可能的数据引用进行版本控制,并将此过程集成到MLOps工作流中,您为特征的可复现性、安全迭代和有效管理构建了支撑。策略的选择取决于平衡保证、复杂性和操作开销,通常导致根据特定组织需求量身定制的混合方法。