项目

一般

简介

行为

CR-011-特征矩阵Parquet存储形态由长表变更为宽表

字段 内容
CR ID CR-004
标题 特征矩阵落盘形态由长表(EAV)变更为宽表(38列并排)
发起人 Henry Lin (PM)
日期 2026-04-17
状态 ✅ Approved
影响范围 规约 4.1 节特征目录、S3-04 产出物 Schema、docs/data_contract.md、下游 Step 5 数据加载逻辑

1. 变更描述

原规约约束

上述 38 维特征在 features.parquet 中必须为长表形态(Schema: fund_id, net_value_date, feature_name, feature_value)。严禁 Pivot 成宽表。

变更为

features_YYYY.parquet 必须为宽表形态。Schema 固定为:fund_id(String), net_value_date(Date), segment_id(UInt32), 以及 38 个特征列(如 price_vs_ma_ratio_12w Float64, ..., calmar_ratio_52w Float64)。严禁在落盘阶段使用 unpivot 转换为长表。

2. 变更原因(根因追溯)

在 M3a 架构评审中发现,原“长表落盘”红线与高性能计算架构存在严重冲突:

  1. 计算层冲突:截面 Z-Score 标准化与共线性剔除(IC 计算)的纯函数,在 Polars 中必须基于“行=样本,列=特征”的宽表矩阵才能进行高效向量化运算。若坚持长表,需在每次计算前后频繁执行 pivot/unpivot,带来巨额的 CPU 与内存开销。
  2. 训练层冲突:LightGBM 等树模型原生要求宽表输入,长表形态迫使 Step 5 必须额外维护一套高频 Pivot 读取逻辑。
  3. 列式存储劣势:对于 Parquet 这种列式格式,在特征维度固定(38维)且有限的情况下,宽表能完美利用“按列裁剪”优势;而长表(EAV)的 feature_name 字符串列会破坏列式压缩率,且按特征筛选时产生大量冗余 IO。
  4. 维度确定性:本系统特征已通过《特征字典基线文档》刚性冻结为 38 维,不存在“频繁增删特征导致宽表 Schema 失控”的 EAV 适用前提。

3. 影响分析

受影响模块 影响说明 应对措施
feature_engineering.py 取消落盘前的 unpivot() 逻辑 内存中全程维持宽表,计算完毕后直接调用 PyArrow write_parquet()
data_contract.md 存储形态红线描述变更 更新《特征矩阵接口契约单》,明确宽表 Schema 及 38 列的严格类型映射
trainer.py (Step 5) 简化数据加载逻辑 直接读取宽表,废弃原有的 GroupBy+Pivot 还原逻辑
元数据校验 Hash 与审计逻辑适配 features_hash.json 基于宽表文件计算,无需变更工具函数

Huarui Lin 更新于 大约 5 小时 之前 · 2 修订