社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  机器学习算法

特征时序化建模:基于特征缓慢变化维度历史追踪的机器学习模型性能优化方法

数据派THU • 9 月前 • 160 次点击  


来源:DeepHub IMBA
本文约3000字,建议阅读10分钟
本文将通过缓慢变化维度(Slowly Changing Dimensions)这一数据建模技术来解决上面的这个问题。


我们在工作中经常会遇到一个问题,数据基础设施的设计往往没有充分考虑数据科学的需求。数据仓库或数据湖仓中的大量表格(主要是事实表和维度表)缺乏构建高性能机器学习模型所需的关键字段或结构。其中最显著的局限性在于,大多数表格仅记录观测值的当前状态,而未保留历史记录。

本文将通过缓慢变化维度(Slowly Changing Dimensions)这一数据建模技术来解决上面的这个问题。通过本文的介绍,可以了解历史数据存储对模型性能的重要影响,以及如何在实际应用中实施这一技术方案。

数据科学领域的常见挑战

在数据科学或机器学习工程领域工作一段时间后,可能会遇到这样一个建模问题:需要对数据中每个实例在时间维度上发生某事件的概率进行建模:

这种建模方法,通常称为面板建模(Panel Modeling),在实际应用中极为普遍。任何涉及特征随时间变化的建模问题都可以且通常应该采用这种方法。典型应用场景包括:客户流失预测、贷款违约预测、疾病进展监测、欺诈检测、设备故障预测等。

从形式化角度,可以用以下数学符号描述该问题:

以贷款违约预测为例,其基本目标是利用借款人随时间变化的特征(X)来预测其在贷款发放后各时间段(t)的违约概率(Y)。对于特定借款人,模型的预测结果可能呈现如下形式:

在上述图示中,t = 0 表示贷款发放时间点,t = 100 表示贷款到期时间点。模型预测显示随着贷款接近完成,借款人的违约概率呈下降趋势。然而,这种趋势并非固定模式,实际情况会根据借款人的信用状况和其他相关特征而存在显著差异。

构建此类模型的特征时,通常需要依赖数据仓库中的多个事实表和维度表。例如借款人特征通常来源于记录借款人属性的 dim_borrower 维度表。在后期才引入机器学习的组织中,dim_borrower 表的典型结构如下:

在 dim_borrower 表中,每条记录通过 borrower_key 唯一标识一个借款人的属性信息。例如,借款人153443的当前记录显示:FICO评分为567,年收入为55,123美元,债务收入比(DTI)为0.25。created_datetime_utc 字段记录数据创建时间,updated_datetime_utc 字段记录最新更新时间。

这种维度表设计的主要缺陷在于缺乏历史记录追踪功能。以上述示例而言,我们无法获知借款人153443在 2024-04-19 记录创建时的FICO评分、收入状况和DTI比率。同样,我们也无法追溯记录的更新频次和具体更新字段。系统仅保留借款人的当前状态信息、记录创建时间和最后更新时间。

若使用借款人153443的数据构建面板训练集,其形式如下:

这种训练数据存在显著问题:除了 weeks_to_completion = 0 时点(即最新记录时间点)外,其他时间点的数据可能都不准确。实际的借款人历史数据应呈现如下形式:

这组数据展现了与仅使用最新记录完全不同的信息特征。数据显示该借款人的FICO评分在第20周到第11周期间出现显著下滑,DTI比率从0.018(几乎无负债)上升至0.25。这些变化表明借款人在此期间新增了大量外部债务,信用状况显著恶化。基于这种包含完整历史记录的数据集训练的模型,其性能将远优于使用仅包含当前状态数据集训练的模型。

在理解了不追踪历史记录的表结构所存在的问题后,我们将探讨解决这一问题的最佳实践之一 - 缓慢变化维度技术。

解决方案:缓慢变化维度技术

缓慢变化维度(Slowly Changing Dimensions,简称SCD)是追踪维度历史变更的一种优秀数据建模范式。顾名思义,SCD用于处理那些随时间缓慢发生变化的相对稳定的维度。虽然SCD包含四种类型,但其中Type II类型最为常用。

借款人维度是应用SCD的典型场景。在SCD范式下,传统维度表的结构:

将转变为:

在这种SCD结构中,每条记录代表借款人在特定时间区间(由 start_datetime_utc 和 end_datetime_utc 定义)内的属性状态。例如,2024-04-27至2024-06-09期间,借款人153443的属性状态为:FICO评分567,年收入55,123美元,DTI比率0.25。当前有效记录通过 is_current = 1 或 end_datetime_utc 为空值标识。因此,borrower_key 仅在 is_current = 1 时具有唯一性约束。

SCD数据结构对机器学习模型的影响十分显著。当模型的训练数据源均采用SCD或事实表时,我们就能构建出充分捕捉特征时间动态特性的最优模型,准确反映特征值变化对目标变量的影响。

SCD结构可以便捷地转换为模型所需的面板数据视图。回顾前文中借款人153443的示例:

从训练数据的视角观察,dti_ratio 特征的时间序列表现如下:

基于传统维度数据训练的模型无法感知DTI比率的历史变化趋势,因此也无法准确建模DTI比率变化对贷款违约概率的影响。相比之下基于SCD数据训练的模型能够完整掌握借款人DTI比率的历史变化情况,从而在预测时充分利用这些时序信息。

在生产环境中,这两种模型对同一借款人的预测结果可能存在显著差异:

在模型推理阶段,基于传统维度数据训练的模型仅能获取借款人的当前特征值。以借款人153443为例,该模型只能观察到贷款余额随时间递减或保持稳定的现象。除非借款人的特征值进入训练数据中识别的高违约风险区间,否则预测的违约概率将呈现稳定下降趋势。

而基于SCD数据训练的模型能够捕捉到借款人FICO评分下降和DTI比率上升的趋势。这使得模型能够准确反映借款人风险状况的恶化,预测的违约概率随时间相应上升。

SCD或完整历史记录追踪的应用场景远不止于此。接下来我们将就如何在组织中落地SCD技术提供一些具体建议。

实施建议

根据不同的职能角色,可以采取不同的策略来推动SCD或其他历史追踪表的应用,从而提升组织的机器学习模型质量。

数据工程师视角

作为数据工程师,在数据仓库/湖仓设计方面具有一定的决策权。对于是否需要追踪某个表的历史记录,建议采用"默认开启"的原则。尽管实现SCD需要更复杂的ETL流程,但考虑到其带来的价值,这种投入通常是值得的。

常见的反对意见来自存储成本方面的考虑。得益于现代数据平台普遍采用的列式存储格式,存储成本已不再构成主要障碍。

数据科学家/ML工程师视角

作为数据科学家或ML工程师,特别是在机器学习并非组织数据主要应用场景的情况下,在数据仓库/湖仓设计方面的影响力可能较为有限。应尽可能争取实现历史追踪功能。

如果无法影响上游数据表的设计,可以考虑在特征存储或模型训练数据集层面开始实施历史追踪。虽然可能需要一定时间才能积累足够的历史数据以供使用,但及早开始永远是明智之选。

产品经理视角

将历史追踪功能作为产品需求提出可能是最有效的推进方式。机器学习模型的质量直接取决于训练数据的质量,而缺乏历史数据的模型难以发挥其全部潜力。构建高质量的机器学习产品,必须建立在高质量数据的基础之上,而具备历史追踪能力的数据集是构建高性能模型的基础要素。

总结

特征历史追踪对于提升机器学习模型性能至关重要。通过在数据集中引入历史数据,我们能够有效捕获上下文信息和时间动态特性,从而提高预测准确性和模型稳定性。

实施历史数据追踪确实面临一些挑战,如存储需求增加和ETL流程复杂化。从模型性能提升和业务洞察增强的角度来看,这些投入是极具价值的。对于数据工程师、数据科学家和产品经理而言,将历史追踪作为基础设施建设的核心原则之一,将有助于全面提升组织的数据基础设施和机器学习能力。

建议采用渐进式的实施策略:

  1. 从关键数据表的改造入手
  2. 在特征存储中构建历史追踪机制
  3. 在新建数据管道中集成SCD设计模式

历史数据的价值会随时间积累而不断增长,越早开始实施,模型就能越早具备提供准确、具有上下文感知能力的预测结果。

特征历史追踪不仅是提升模型性能的技术手段,更是构建面向未来的数据生态系统的重要基石。通过系统性地实施这一技术,我们能够为组织的数据驱动决策提供更坚实的支持。

作者:Harrison Hoffman

编辑:黄继彦



关于我们

数据派THU作为数据科学类公众号,背靠清华大学大数据研究中心,分享前沿数据科学与大数据技术创新研究动态、持续传播数据科学知识,努力建设数据人才聚集平台、打造中国大数据最强集团军。



新浪微博:@数据派THU

微信视频号:数据派THU

今日头条:数据派THU

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/178397