4、用户画像与特征工程:基础属性特征、行为特征、关系网络特征、特征存储与实时计算
在流式决策链路中,用户画像与特征工程是连接原始数据与额度定价模型的桥梁。特征的质量直接决定了模型对风险与收益的刻画能力。本章从基础属性、行为轨迹、关系网络三个维度拆解特征体系,并深入探讨特征存储架构与实时计算方案。
4.1 特征体系三维度
信贷场景下的用户特征可归纳为三大类:基础属性特征(静态或低频变化)、行为特征(动态时序)、关系网络特征(社交与资金关联)。三者共同构成完整的用户画像。
| 特征维度 | 数据来源 | 更新频率 | 典型特征示例 |
|---|---|---|---|
| 基础属性 | 身份证、征信报告、运营商 | 月/季度 | 年龄、性别、学历、婚姻状况、居住稳定性、职业类别 |
| 行为特征 | APP埋点、交易流水、还款记录 | 秒/分钟/天 | 登录频次、浏览时长、消费金额、还款逾期天数、额度使用率 |
| 关系网络 | 通讯录、转账记录、担保关系 | 天/周 | 联系人数量、二度关联逾期率、资金流入流出比、团伙标识 |
实战要点:基础属性特征在首次授信时权重最高,但随着用户行为数据积累,行为特征的预测能力会逐步超越基础属性。关系网络特征在反欺诈和团伙识别中不可替代,但在额度定价中需谨慎使用,避免群体歧视。
4.2 基础属性特征工程
基础属性特征通常来自用户授权数据或第三方数据源,处理重点在于缺失值填充、异常值清洗和分箱编码。
- 缺失值处理:对于学历、职业等分类特征,使用“未知”作为独立类别;对于收入等连续特征,使用中位数或分位数填充。
- 异常值截断:年龄超过100岁、收入为负值等明显错误数据,按业务逻辑截断或剔除。
- 分箱与WOE编码:将连续特征(如年龄)按业务经验或卡方分箱离散化,再计算每个分箱的WOE(Weight of Evidence)值,用于逻辑回归等线性模型。
# 年龄分箱与WOE编码示例(Python伪代码)
import pandas as pd
import numpy as np
def age_woe_encoding(df, target_col='is_default'):
# 按业务经验分箱
bins = [0, 25, 35, 45, 55, 100]
labels = ['18-25', '26-35', '36-45', '46-55', '56+']
df['age_bin'] = pd.cut(df['age'], bins=bins, labels=labels)
# 计算每个分箱的坏账率与WOE
total_good = df[target_col].sum()
total_bad = len(df) - total_good
woe_dict = {}
for bin_label in labels:
bin_df = df[df['age_bin'] == bin_label]
good = bin_df[target_col].sum()
bad = len(bin_df) - good
woe = np.log((bad / total_bad) / (good / total_good))
woe_dict[bin_label] = woe
return woe_dict
4.3 行为特征工程
行为特征是流式决策中最具时效性的信号。核心处理思路包括统计聚合、时序特征和比率特征。
- 滑动窗口统计:过去7天/30天的登录次数、消费金额均值、最大单笔金额等。
- 趋势特征:近3个月额度使用率的斜率、还款金额的环比变化。
- 行为序列特征:用户从注册到首次借款的天数、浏览产品页面的路径长度。
实时计算提示:行为特征在流式场景中通常使用Flink或Spark Streaming进行滑动窗口聚合。窗口大小建议与决策频率匹配——额度调整场景常用7天和30天双窗口,既能捕捉短期波动,又能保留长期趋势。
4.4 关系网络特征工程
关系网络特征通过图算法提取用户的社会关系和资金往来模式。常用方法包括度中心性、PageRank和社区检测。
| 特征类型 | 计算方法 | 业务含义 |
|---|---|---|
| 入度/出度 | 统计用户被转账/向他人转账的次数 | 资金活跃度与依赖关系 |
| 二度关联逾期率 | 用户好友中逾期用户占比 | 风险传染可能性 |
| PageRank值 | 迭代计算节点在图中的重要性 | 识别关键人物或资金枢纽 |
| 社区标签 | Louvain/标签传播算法 | 团伙欺诈识别 |
合规红线:关系网络特征涉及用户通讯录和社交数据,必须获得用户明确授权。在额度定价模型中,不得直接使用“联系人数量”等敏感特征作为拒绝依据,建议仅用于辅助欺诈评分。
4.5 特征存储架构
特征存储需要同时满足在线低延迟读取和离线批量训练的需求。业界主流方案采用分层存储架构。
4.6 实时特征计算方案
流式决策要求特征在用户请求到达时立即可用。实时计算方案通常基于事件驱动架构,核心组件包括消息队列、流计算引擎和特征存储。
- 事件采集:用户行为(点击、借款、还款)通过SDK上报至Kafka,每条事件携带用户ID、事件类型、时间戳。
- 流计算:Flink消费Kafka消息,按用户ID进行keyBy分组,在滑动窗口内计算聚合特征(如近7天借款次数)。
- 特征更新:计算结果写入Redis,设置TTL(如7天),同时异步写入HBase作为近线备份。
- 在线读取:决策引擎在收到额度请求时,通过Feature Store的API从Redis读取实时特征,若缺失则降级到HBase。
-- Flink SQL 实时特征计算示例
CREATE TABLE user_behavior (
user_id STRING,
event_type STRING,
amount DOUBLE,
event_time TIMESTAMP(3),
WATERMARK FOR event_time AS event_time - INTERVAL '5' SECOND
) WITH (
'connector' = 'kafka',
'topic' = 'user_events',
'properties.bootstrap.servers' = 'localhost:9092',
'format' = 'json'
);
CREATE TABLE redis_sink (
user_id STRING,
loan_count_7d BIGINT,
total_amount_7d DOUBLE,
PRIMARY KEY (user_id) NOT ENFORCED
) WITH (
'connector' = 'redis',
'redis.mode' = 'single',
'host' = 'localhost',
'port' = '6379'
);
INSERT INTO redis_sink
SELECT
user_id,
COUNT(*) AS loan_count_7d,
SUM(amount) AS total_amount_7d
FROM user_behavior
WHERE event_type = 'loan'
GROUP BY
user_id,
HOP(event_time, INTERVAL '1' MINUTE, INTERVAL '7' DAY);
性能优化建议:实时特征计算应避免大状态(如存储全量用户行为序列)。建议将窗口大小控制在30天以内,并使用RocksDB状态后端。对于需要长期趋势的特征(如6个月还款趋势),在离线层计算后同步到近线层,实时层仅做增量修正。
4.7 特征质量监控
特征工程上线后必须建立持续监控机制,防止数据漂移或特征失效导致模型退化。
| 监控维度 | 指标 | 告警阈值 | 处理措施 |
|---|---|---|---|
| 缺失率 | 特征缺失值占比 | > 5% | 检查上游数据源是否异常 |
| 分布漂移 | PSI(群体稳定性指标) | > 0.1 | 重新分箱或模型重训 |
| 实时延迟 | 特征写入到可读取的延迟 | > 500ms | 扩容Flink算子或优化Redis连接池 |
| 特征一致性 | 在线特征与离线特征差异 | > 1% | 检查特征计算逻辑是否一致 |
最佳实践:建议在特征存储层为每个特征打上版本标签(如 v1.2.3),并在模型推理时记录特征版本号。当特征逻辑变更时,可以快速回溯历史决策,定位模型效果变化的原因。