4. 特征工程基础:特征分类、时效性与存储选型
在催收触达场景中,特征的质量直接决定模型分流的准确性。本章从特征分类、时效性分级和存储选型三个维度,建立催收特征工程的基础框架。
4.1 特征分类:静态 / 动态 / 聚合
催收特征按数据来源和更新频率可分为三类,每类在建模中承担不同角色:
| 特征类型 | 定义 | 催收典型示例 | 更新频率 | 存储特点 |
|---|---|---|---|---|
| 静态特征 | 用户基础属性,长期不变或极少变化 | 年龄、性别、户籍地、学历、注册渠道 | 月 / 季度 | MySQL 宽表,全量快照 |
| 动态特征 | 用户近期行为,随时间快速变化 | 近 7 天还款次数、近 3 天通话时长、当日 APP 登录次数 | 天 / 小时 | Redis 缓存 + 实时流 |
| 聚合特征 | 基于历史窗口的统计汇总,反映趋势 | 过去 30 天逾期天数均值、历史最大逾期天数、近 6 个月还款率 | 天 / 周 | HBase 列族 + 离线批处理 |
实战建议:静态特征用于冷启动和分层;动态特征驱动实时触达策略切换;聚合特征为模型提供长期信用画像。三者缺一不可。
4.2 特征时效性:从秒级到月级的分级管理
不同特征对时效性的要求差异巨大,催收系统必须按时效等级设计更新策略:
- T+0 实时(秒级):用户当前是否在线、当日是否已触达、当前催收员状态。依赖消息队列 + Redis 写入。
- 近实时(分钟级):最近 1 小时还款行为、最近 1 小时通话结果。依赖 Flink 或 Spark Streaming 微批处理。
- 天级:昨日逾期天数、昨日联系率。依赖离线调度(如 Airflow)每日凌晨产出。
- 周 / 月级:历史最大逾期天数、近 6 个月还款率。依赖离线数仓(Hive / Spark)周期性计算。
常见陷阱:将天级特征用于实时分流,会导致模型响应滞后;将实时特征用于离线训练,会造成训练 / 推理不一致。必须严格对齐特征时间戳。
4.3 特征存储选型:Redis / MySQL / HBase
不同特征类型和时效性决定了存储引擎的选择。以下是催收场景下的推荐选型矩阵:
| 存储引擎 | 适用特征 | 读写模式 | 延迟 | 容量 | 催收典型用途 |
|---|---|---|---|---|---|
| Redis | 动态特征、实时特征 | 高并发读 / 写,Key-Value | < 1ms | GB 级(内存) | 用户实时状态、当日触达次数、催收员在线状态 |
| MySQL | 静态特征、天级聚合特征 | 低频写入,批量读取 | 10~50ms | TB 级(磁盘) | 用户基础信息宽表、催收策略配置表 |
| HBase | 聚合特征、历史序列特征 | 列族存储,范围扫描 | 10~100ms | PB 级(分布式) | 用户 6 个月逾期序列、历史通话记录聚合 |
选型原则:在线分流服务优先使用 Redis 缓存热特征;离线训练从 HBase 或 MySQL 批量拉取;避免将 MySQL 用于高并发实时查询,避免将 Redis 用于全量历史数据存储。
4.4 特征存储选型对比清单
在实际架构选型中,建议按以下清单逐项评估:
- 数据量级:单表超过 1 亿行且需要范围扫描 → 选 HBase;单表千万级且关联查询多 → 选 MySQL。
- 读写比例:写多读少且要求低延迟 → 选 Redis(如实时行为计数);读多写少且要求事务 → 选 MySQL。
- 数据生命周期:需要 TTL 自动过期 → 选 Redis(如当日触达次数);需要永久存储 → 选 MySQL 或 HBase。
- 一致性要求:强一致性(如策略配置)→ 选 MySQL;最终一致性(如聚合统计)→ 选 HBase。
- 运维成本:Redis 集群需要内存规划;HBase 需要 HDFS 和 Zookeeper 维护;MySQL 主从成熟但扩展性有限。
实战案例:某头部消金催收系统将“用户近 7 天还款次数”存储在 Redis(Key:
repay_cnt_7d:{userId},TTL=7 天),将“历史最大逾期天数”存储在 HBase(RowKey: userId_reverse),将“用户注册渠道”存储在 MySQL 用户宽表。分流服务在 10ms 内完成特征拼接。
4.5 特征工程避坑指南
- 特征穿越:使用未来信息构造特征(如用当天的还款结果预测当天的催收策略),导致模型过拟合。解决:严格按时间窗口回溯。
- 特征空值:新用户或低频用户大量特征为空。解决:设置默认值(如 0 或 -1),或使用静态特征兜底。
- 特征膨胀:聚合窗口过多(7 天 / 14 天 / 30 天 / 60 天)导致特征维度爆炸。解决:通过特征选择或 PCA 降维。
- 存储不一致:同一特征在 Redis 和 MySQL 中值不同。解决:统一写入入口,Redis 作为缓存,MySQL 作为权威源。