2. 风控特征基础
在风控系统中,模型和规则只是“决策大脑”,真正决定判断质量的是喂给大脑的“信息原料”——特征。理解特征的定义、分类、生命周期以及承载它们的平台架构,是后续排查特征缺失异常、治理新鲜度问题的前提。本节从工程视角把“特征”讲清楚,为实战打好地基。
一、核心原理:什么是风控特征
风控特征(Feature)是指在风控决策时刻,能够被系统读取、用于刻画当前事件风险的一组结构化数值或标签。它通常由原始事件、历史行为、外部数据经过加工计算得到,具备三个关键属性:
- 时效性:特征值必须对应某个明确的时间窗口,如“近1小时登录次数”“近30天逾期笔数”。
- 可计算性:特征必须能由确定的加工逻辑产出,可复现、可回溯、可监控。
- 决策相关性:特征需与风险目标有统计或业务上的关联,否则只是噪声。
一个常被忽视的点是:特征不是“数据库字段”,而是“在决策时刻可用的、带时间语义的派生量”。例如用户表里的“注册时间”是原始字段,而“注册距今天数”才是特征;“近7天同设备登录账号数”则是跨事件聚合特征。
二、特征的分类:从多个维度切分
分类不是为了贴标签,而是为了在设计监控、存储和回填策略时能对症下药。常见切分维度如下:
| 分类维度 | 类型 | 典型示例 | 工程关注点 |
|---|---|---|---|
| 数据来源 | 实时事件 / 离线数仓 / 外部三方 | 本次请求IP、近90天消费、征信分 | 依赖稳定性、回填能力 |
| 时间语义 | 实时特征 / 近线特征 / 离线特征 | 近5分钟频次、近1天设备数、近1年标签 | 新鲜度、窗口对齐 |
| 计算方式 | 统计聚合 / 序列 / 图关系 / 模型分 | 计数、滑动窗口、团伙关系、风险评分 | 计算成本、一致性 |
| 取值形态 | 数值 / 类别 / 布尔 / 向量 | 金额、渠道编码、是否黑名单、Embedding | 缺失填充、编码方式 |
其中“时间语义”维度与后续新鲜度治理关系最密切。实时特征要求秒级更新,近线特征通常分钟到小时级,离线特征按天或按周更新。不同时间语义的特征混用,是新鲜度异常的常见根源。
三、特征生命周期:从定义到退役
特征不是一次性产物,它有一条完整的生命周期。理解这条链路,才能在异常发生时快速定位是哪个环节出了问题。
- 需求与定义:业务提出风险假设,数据团队将其转化为可计算的特征口径,明确实体、窗口、聚合函数。
- 开发与注册:在特征平台注册元数据,包括名称、类型、负责人、更新频率、依赖上游。
- 生产与写入:由批处理或流计算任务产出,写入在线存储(如Redis、HBase)供实时读取。
- 在线服务:决策引擎在请求时刻按实体Key拉取特征,组装成特征向量。
- 监控与回填:持续监控覆盖率、延迟、分布漂移;异常时触发回填或降级。
- 退役:当特征失效或冗余时,下线并清理存储与依赖,避免“僵尸特征”污染。
四、常见特征平台架构
工业界特征平台通常采用“离线 + 在线”双链路架构,核心目标是保证离线与在线特征的一致性(即训练-服务一致性)。典型分层如下:
- 数据源层:埋点日志、业务库、三方接口。
- 计算层:离线用Spark/Hive做批聚合,实时用Flink/Kafka做流聚合。
- 存储层:离线特征存Hive/ClickHouse,在线特征存Redis/HBase,向量特征存专用向量库。
- 服务层:特征网关统一接收请求,按Key并行拉取多路特征,做超时与降级控制。
- 治理层:元数据中心、血缘追踪、质量监控、回填调度。
下面是一段特征网关拉取在线特征的伪代码,展示了超时与缺失兜底的基本处理逻辑:
def fetch_features(entity_key, feature_names, timeout_ms=50):
result = {}
for name in feature_names:
try:
value = redis_client.get(f"{name}:{entity_key}", timeout=timeout_ms)
if value is None:
result[name] = DEFAULT_VALUE # 缺失兜底
metrics.incr(f"feature_missing.{name}")
else:
result[name] = value
except TimeoutError:
result[name] = DEFAULT_VALUE
metrics.incr(f"feature_timeout.{name}")
return result
这段代码里,DEFAULT_VALUE 和监控埋点是关键。缺失兜底保证决策不中断,监控埋点则为后续缺失异常分析提供数据。若没有这两者,特征缺失会直接表现为线上决策报错或静默错误。
五、案例与误区复盘
某信贷风控团队曾遇到一次典型的特征缺失事故:模型A依赖“近7天申请次数”这一实时特征,某日凌晨Flink任务因上游Kafka分区倾斜导致消费延迟,在线Redis中该特征大面积未更新。由于网关没有配置缺失监控,决策引擎读取到的是旧值,导致一批高风险申请被误判为低风险。
复盘后发现三个问题:
- 误区一:认为“特征存在即有效”,忽略了新鲜度监控。旧值不等于缺失,但风险等价。
- 误区二:缺失兜底策略过于简单,统一填0,掩盖了异常信号。
- 误区三:离线与在线特征口径不一致,回填时无法对齐,延长了恢复时间。