第3章 数据采集与理解:常见数据源、数据质量检查

做信用评分,数据就是你的弹药库。弹药质量不行,模型再牛也白搭。这一章咱就聊聊数据从哪来,以及怎么保证这些数据靠谱。

我最早做评分卡项目时,客户给了整整10个G的CSV。当时以为数据全了,结果一跑分布,缺了40%的字段。那感觉,就像你准备了满汉全席,结果发现菜没洗。所以,数据源理解和质量检查,是特征工程的第一步,也是最重要的一步。

3.1 常见数据源

信用评分需要的数据,说白了就三类:内部自己的数据、外部拿到的数据、还有第三方加工过的数据。我按实战中出现的频率,给你排个序:

数据源类别典型例子特点常见问题
内部数据客户基本信息、交易流水、还款记录、存款行为量大、独有、实时性好字段老旧、数据孤岛、口径不统一
外部数据人行征信、百行征信、社保、公积金权威、覆盖面广更新周期长、字段有限、有查询成本
第三方数据电商消费、运营商、黑名单、多头借贷维度丰富、能补充弱特征质量参差不齐、合规风险
公开数据法院失信、工商信息、行政处罚验证性强延迟大、结构化差

你看,内部数据最香,但往往最乱。我见过一个银行,同一个客户在“对私”和“信用卡”系统里有不同的身份证号……你说这是一个人吗?所以,采集之前,先画清楚数据地图。

我的习惯:拿到任何数据源,第一件事不是建模,而是画一张 数据字典。字段名、类型、取值范围、唯一性、缺失率,列一张表。这能帮你省掉后面一半的返工时间。

3.2 数据采集方式

数据怎么到我们手里?常见的方式有这些:

  • 数据库直连:从生产库拉数据,速度快,但可能影响性能。我建议用只读副本。
  • 文件导入:CSV、Excel、Parquet 最常见。嗯,这里要特别注意编码和分隔符。
  • API 接口:调用外部征信或第三方数据,需要设计容错和重试。
  • 手工录入:比如线下调查表,这个质量最难保证,我一般会做二次校验。

下面这张图,是我自己项目里常用的数据采集与质量检查流程。顺着方向看,每一步都在做什么。

数据采集与质量检查流程图 内部系统 外部数据源 第三方数据 数据采集层 API / 直连 / 文件 增量 / 全量 数据仓库 ODS / 数据湖 存储原始数据 质量检查 完整性 / 准确性 一致性 / 时效性 建议:在采集层就完成字段映射、类型转换和去重 质量检查通过后,再进入特征工程阶段

3.3 数据质量检查

数据进来了,不代表就能用。我给自己定了个规矩:质量检查没通过,模型绝不动笔。从四个维度下手:

  1. 完整性:有没有空值?关键字段缺多少?
    我一般设个阈值:缺失超过70%的字段,直接丢弃;50%~70%的考虑派生或填充;低于50%的做插补。
  2. 准确性:值是否合理?比如年龄200岁,身份证长度不对。
    我曾经遇到过某个字段“月收入”居然有负数,查了半天是数据导入时符号位搞反了。
  3. 一致性:同一份数据跨系统对不上吗?比如内部标签和征信报告上的逾期天数。
  4. 时效性:数据更新是否及时?建模集和验证集的时间窗口跨度别太大。

避坑指南:我曾经用一个外部多头借贷数据做特征,结果跑出来的评分模型特别“准”,上线后坏账率飙升。后来才发现,那个数据源更新滞后了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

注意:质量检查是迭代的。不是跑一次就完事,每次接入新数据源、每次模型迭代,都重新检查一遍。数据源变了,你的特征逻辑可能也跟着变。