3. 信用评分数据模型设计:用户画像、交易流水、外部征信数据的数据结构设计;评分卡模型输入特征定义
信用评分模型的核心在于数据。原始数据的质量、结构以及特征工程的合理性,直接决定了评分卡模型的区分能力和稳定性。本章将详细定义三类核心数据源的数据结构,并明确评分卡模型的输入特征规范,为后续Kafka实时特征计算与模型推理奠定数据基础。
3.1 三类核心数据源的数据结构设计
信用评分场景下,数据源通常分为内部用户画像、交易流水以及外部征信数据。每一类数据在Kafka消息中的序列化结构必须统一、完备且易于扩展。以下采用Avro作为序列化格式示例,因其支持Schema演化,适合流式数据管道。
3.1.1 用户画像数据(User Profile)
用户画像数据是静态或准静态的客户基础信息与行为标签,通常来自CRM系统、注册信息或历史行为汇总。该数据在Kafka中作为“慢变维度”存在,通常以用户ID为主键,每日或每小时更新一次。
| 字段名 | 类型 | 说明 | 示例值 |
|---|---|---|---|
| user_id | string | 用户唯一标识 | U10002345 |
| age | int | 年龄 | 32 |
| gender | string | 性别(M/F) | M |
| education_level | string | 教育程度编码 | 本科 |
| marital_status | string | 婚姻状况 | 已婚 |
| occupation | string | 职业类别 | IT工程师 |
| city | string | 居住城市 | 北京 |
| registration_days | int | 注册天数 | 365 |
| profile_version | long | 数据版本时间戳 | 1700000000000 |
3.1.2 交易流水数据(Transaction Log)
交易流水是高频、实时产生的行为数据,是信用评分模型中“行为评分”的核心输入。每条交易记录代表一次独立的金融行为,必须包含时间戳、金额、交易对手、渠道等关键信息。
| 字段名 | 类型 | 说明 | 示例值 |
|---|---|---|---|
| transaction_id | string | 交易唯一ID | TXN20250301001 |
| user_id | string | 用户标识 | U10002345 |
| trans_time | long | 交易发生时间戳(毫秒) | 1700000000000 |
| trans_amount | double | 交易金额(元) | 1500.00 |
| trans_type | string | 交易类型编码 | 消费 |
| trans_channel | string | 交易渠道 | 线上支付 |
| counterparty | string | 交易对手标识 | 商户A |
| balance_after | double | 交易后余额 | 8500.00 |
| trans_status | string | 交易状态(成功/失败) | 成功 |
3.1.3 外部征信数据(External Credit Data)
外部征信数据来自央行征信中心、百行征信、同盾等第三方机构。这类数据通常以查询接口或批量文件方式获取,在Kafka中作为“补充特征”与用户画像进行关联。数据结构需包含征信报告的核心指标。
| 字段名 | 类型 | 说明 | 示例值 |
|---|---|---|---|
| user_id | string | 用户标识 | U10002345 |
| credit_query_date | long | 征信查询日期 | 1700000000000 |
| credit_score_external | int | 外部信用分(如芝麻分) | 680 |
| overdue_days_max | int | 历史最大逾期天数 | 30 |
| overdue_count_12m | int | 近12个月逾期次数 | 2 |
| credit_card_count | int | 信用卡持有数量 | 3 |
| loan_count_active | int | 当前未结清贷款笔数 | 1 |
| total_debt | double | 总负债金额(元) | 50000.00 |
| data_source | string | 数据来源机构编码 | 百行征信 |
3.2 评分卡模型输入特征定义
评分卡模型通常采用逻辑回归或XGBoost等算法,其输入特征必须经过严格的特征工程,包括缺失值处理、异常值截断、WOE编码或分箱等步骤。以下定义评分卡模型的标准输入特征集,这些特征将作为Kafka Streams实时特征计算的输出目标。
3.2.1 特征分类与定义
特征分为三大类:基础属性特征、行为特征、征信特征。每类特征在模型中的权重和业务含义不同。
| 特征类别 | 特征名称 | 数据类型 | 特征来源 | 业务含义 |
|---|---|---|---|---|
| 基础属性 | age_group | int | 用户画像 | 年龄分箱编码(1-5) |
| 基础属性 | education_woe | double | 用户画像 | 教育程度WOE值 |
| 基础属性 | city_risk_level | int | 用户画像 | 城市风险等级(1-3) |
| 行为特征 | trans_avg_amount_30d | double | 交易流水 | 近30天平均交易金额 |
| 行为特征 | trans_count_7d | int | 交易流水 | 近7天交易笔数 |
| 行为特征 | balance_ratio_30d | double | 交易流水 | 近30天余额波动比率 |
| 行为特征 | night_trans_ratio | double | 交易流水 | 夜间交易占比 |
| 征信特征 | external_score_bin | int | 外部征信 | 外部信用分分箱 |
| 征信特征 | overdue_flag_12m | int | 外部征信 | 近12个月是否逾期(0/1) |
| 征信特征 | debt_income_ratio | double | 外部征信 | 负债收入比 |
3.2.2 特征计算与Kafka Streams映射
在Kafka Streams中,特征计算通过时间窗口聚合和状态存储实现。以下是一个典型的特征计算拓扑示例:
// Kafka Streams DSL 示例:计算近30天平均交易金额
KStream<String, TransactionLog> transactions = builder.stream("transaction-topic");
KTable<String, Double> avgAmount30d = transactions
.groupByKey()
.windowedBy(TimeWindows.of(Duration.ofDays(30)).grace(Duration.ofHours(1)))
.aggregate(
() -> 0.0,
(key, value, aggregate) -> aggregate + value.getTransAmount(),
Materialized.with(Serdes.String(), Serdes.Double())
)
.toStream()
.map((windowedKey, value) -> KeyValue.pair(windowedKey.key(), value / countPerWindow));
3.3 数据模型与特征工程的整体架构
下图展示了从原始数据源到评分卡模型输入特征的完整数据流架构,涵盖Kafka主题、Streams计算节点以及特征存储。
- 三类数据源通过独立的Kafka主题接入,保证数据隔离和并行处理能力。
- Kafka Streams负责所有特征计算逻辑,包括时间窗口聚合、多流关联、特征编码等,计算结果输出到特征主题。
- 特征主题支持多版本共存,模型推理时通过配置中心动态选择特征版本,实现模型迭代的无缝切换。
3.4 特征数据质量监控
数据质量是评分卡模型的生命线。在Kafka链路中,必须对特征数据实施实时质量监控,避免因数据异常导致模型评分偏差。以下列出关键监控指标:
| 监控维度 | 监控指标 | 告警阈值 | 处理策略 |
|---|---|---|---|
| 完整性 | 特征缺失率 | > 5% | 触发补数任务或使用默认值填充 |
| 时效性 | 特征计算延迟 | > 60秒 | 检查Kafka消费者Lag和Streams任务状态 |
| 一致性 | 特征分布偏移(PSI) | > 0.1 | 触发模型重训练或特征版本回滚 |
| 准确性 | 特征值范围异常 | 超出业务定义边界 | 记录异常日志并隔离该条特征向量 |
通过以上数据结构设计和特征定义,我们为信用评分模型构建了清晰、可扩展的数据基础。下一阶段将基于这些特征,在Kafka Streams中实现实时的特征计算管道,并最终驱动评分卡模型的在线推理。