第3章 数据采集与理解:常见数据源、数据质量检查
做信用评分,数据就是你的弹药库。弹药质量不行,模型再牛也白搭。这一章咱就聊聊数据从哪来,以及怎么保证这些数据靠谱。
我最早做评分卡项目时,客户给了整整10个G的CSV。当时以为数据全了,结果一跑分布,缺了40%的字段。那感觉,就像你准备了满汉全席,结果发现菜没洗。所以,数据源理解和质量检查,是特征工程的第一步,也是最重要的一步。
3.1 常见数据源
信用评分需要的数据,说白了就三类:内部自己的数据、外部拿到的数据、还有第三方加工过的数据。我按实战中出现的频率,给你排个序:
| 数据源类别 | 典型例子 | 特点 | 常见问题 |
|---|---|---|---|
| 内部数据 | 客户基本信息、交易流水、还款记录、存款行为 | 量大、独有、实时性好 | 字段老旧、数据孤岛、口径不统一 |
| 外部数据 | 人行征信、百行征信、社保、公积金 | 权威、覆盖面广 | 更新周期长、字段有限、有查询成本 |
| 第三方数据 | 电商消费、运营商、黑名单、多头借贷 | 维度丰富、能补充弱特征 | 质量参差不齐、合规风险 |
| 公开数据 | 法院失信、工商信息、行政处罚 | 验证性强 | 延迟大、结构化差 |
你看,内部数据最香,但往往最乱。我见过一个银行,同一个客户在“对私”和“信用卡”系统里有不同的身份证号……你说这是一个人吗?所以,采集之前,先画清楚数据地图。
我的习惯:拿到任何数据源,第一件事不是建模,而是画一张 数据字典。字段名、类型、取值范围、唯一性、缺失率,列一张表。这能帮你省掉后面一半的返工时间。
3.2 数据采集方式
数据怎么到我们手里?常见的方式有这些:
- 数据库直连:从生产库拉数据,速度快,但可能影响性能。我建议用只读副本。
- 文件导入:CSV、Excel、Parquet 最常见。嗯,这里要特别注意编码和分隔符。
- API 接口:调用外部征信或第三方数据,需要设计容错和重试。
- 手工录入:比如线下调查表,这个质量最难保证,我一般会做二次校验。
下面这张图,是我自己项目里常用的数据采集与质量检查流程。顺着方向看,每一步都在做什么。
3.3 数据质量检查
数据进来了,不代表就能用。我给自己定了个规矩:质量检查没通过,模型绝不动笔。从四个维度下手:
- 完整性:有没有空值?关键字段缺多少?
我一般设个阈值:缺失超过70%的字段,直接丢弃;50%~70%的考虑派生或填充;低于50%的做插补。 - 准确性:值是否合理?比如年龄200岁,身份证长度不对。
我曾经遇到过某个字段“月收入”居然有负数,查了半天是数据导入时符号位搞反了。 - 一致性:同一份数据跨系统对不上吗?比如内部标签和征信报告上的逾期天数。
- 时效性:数据更新是否及时?建模集和验证集的时间窗口跨度别太大。
避坑指南:我曾经用一个外部多头借贷数据做特征,结果跑出来的评分模型特别“准”,上线后坏账率飙升。后来才发现,那个数据源更新滞后了3个月,相当于用历史信息预测未来,时间穿越了。所以,别忘了给每条数据打上时间戳。
质量检查的实操,我一般写个简单的脚本。下面是一个伪代码例子,你可以直接改:
def check_data_quality(df):
report = {}
for col in df.columns:
report[col] = {
'missing_pct': df[col].isnull().mean(),
'unique_count': df[col].nunique(),
'min': df[col].min() if df[col].dtype in ['int','float'] else None,
'max': df[col].max() if df[col].dtype in ['int','float'] else None,
'logical_check': check_logic(col, df) # 自定义规则
}
return report
注意:质量检查是迭代的。不是跑一次就完事,每次接入新数据源、每次模型迭代,都重新检查一遍。数据源变了,你的特征逻辑可能也跟着变。