第三章 数据探索与采集:打好评分卡的地基

说实话,做评分卡这么多年,我最大的体会就是——数据质量决定了模型的天花板。算法再牛,特征工程再花哨,数据本身是脏的,那一切都是白搭。这一章,咱们就聊聊数据探索和采集那些事儿。

3.1 内部数据与外部数据源

做申请评分卡,数据从哪来?无非两条路:内部和外部。

内部数据,说白了就是你自己系统里攒的那些家底。比如客户填的申请表信息、历史借贷记录、还款行为、甚至客服通话记录。我个人习惯,先把手头内部数据理清楚,再考虑外采。为什么?因为内部数据最可控,成本也最低。

我在项目中遇到过一家消金公司,他们内部数据其实挺全的,但没人系统整理过。客户近半年的还款逾期次数、最近一次申请时间、历史最大负债金额……这些字段散落在三个不同的库里。后来我们花了两周时间做数据血缘梳理,才把这些金子挖出来。

外部数据源,就是第三方提供的补充信息。常见的有:

  • 征信数据:央行征信、百行征信、朴道征信等
  • 黑名单库:法院失信被执行人、网贷黑名单
  • 多头借贷数据:同盾、百融等平台提供的多头查询记录
  • 设备指纹:手机IMEI、MAC地址、IP归属地等
  • 社交网络数据:通讯录关系、通话频次等(注意合规)

核心原则:外部数据是锦上添花,不是雪中送炭。别指望靠买几个外部变量就能把模型从0.6 AUC拉到0.8。先把内部数据吃透,再考虑外采。

你想想看,外部数据有成本,而且接口调用还有延迟。如果内部数据已经能区分出好坏客户了,何必多花那个钱?

3.2 数据字典与元数据管理

数据字典这东西,听起来很枯燥,但做评分卡的人要是没有它,就像厨师没有菜谱——全凭感觉炒菜。

什么是数据字典?就是一张表,记录了每个字段的名字、类型、含义、取值范围、来源、更新频率等信息。我见过最糟糕的情况:一个字段叫"flag_01",没人知道它代表什么。后来查了三个月前的邮件才知道,原来是"是否通过人脸识别"的标记。

嗯,这里要注意——元数据管理不只是写个文档就完事了。它需要持续维护。我建议用以下格式来管理:

字段名 数据类型 含义 取值范围 来源 更新频率 备注
cust_id string 客户唯一标识 UUID格式 核心系统 实时 主键
apply_date date 申请日期 2020-01-01至今 前端录入 实时 注意时区问题
loan_amount float 申请金额(元) 1000-500000 前端录入 实时 单位统一为元
overdue_days int 历史最大逾期天数 0-365 贷后系统 T+1 -1表示无历史记录

我曾经因为一个字段的取值含义没搞清楚,导致模型上线后效果暴跌。那个字段叫"education_level",取值是1、2、3、4。我以为1是小学,2是初中,3是高中,4是大学。结果后来发现——1是博士,2是硕士,3是本科,4是其他。你想想看,这要是搞反了,模型能不出问题吗?

小技巧:每次拿到新数据,先花半天时间做字段级的数据字典梳理。别急着跑模型。磨刀不误砍柴工。

3.3 数据质量初探:缺失值与异常值

数据质量,说白了就是数据干不干净。做评分卡最怕两件事:缺失太多、异常太多。

3.3.1 缺失值处理

缺失值,就是字段里空着的那部分。为什么会缺失?原因很多:

  • 客户没填(比如收入信息很多人不愿意填)
  • 系统没采集到(比如某个接口挂了)
  • 数据本身就不存在(比如未婚人士的配偶信息)

我个人习惯,先看缺失率。如果某个字段缺失率超过70%,我基本就不考虑了。为什么?因为缺失太多,你很难推断出真实分布,强行填充反而会引入噪声。

常见的缺失值处理方法:

  1. 删除:缺失率极高(>70%)或缺失模式完全随机
  2. 填充均值/中位数:适用于连续变量,且缺失率较低(<20%)
  3. 填充众数:适用于分类变量
  4. 模型预测填充:用其他字段预测缺失值,适合缺失率中等(20%-50%)
  5. 单独作为一类:把"缺失"本身当作一个取值,比如"收入未知"

避坑指南:我曾经在某个项目里,把所有缺失值都填充了0。结果模型训练出来,发现"收入=0"的客户反而违约率最低。后来一查,原来这些客户是系统没采集到数据,并不是真的收入为0。嗯,这个教训让我记住了——填充之前,先搞清楚缺失的原因。

3.3.2 异常值检测

异常值,就是那些明显不合理的数据。比如年龄填了200岁,月收入填了9999999元,或者申请金额是负数。

检测异常值,我常用的方法:

  • 业务规则:年龄0-120岁,收入0-100万(根据产品类型调整)
  • 统计方法:3σ原则、箱线图(IQR方法)
  • 聚类方法:DBSCAN等密度聚类,把离群点揪出来

你想想看,一个客户填的月收入是100万,但申请金额只有5000块。这合理吗?大概率是填错了。我建议的做法是:先标记异常值,然后根据业务逻辑判断是修正还是删除。

下面是一个简单的异常值检测代码示例:

import pandas as pd
import numpy as np

def detect_outliers_iqr(data, column):
    """
    使用IQR方法检测异常值
    """
    Q1 = data[column].quantile(0.25)
    Q3 = data[column].quantile(0.75)
    IQR = Q3 - Q1
    
    lower_bound = Q1 - 1.5 * IQR
    upper_bound = Q3 + 1.5 * IQR
    
    outliers = data[(data[column] < lower_bound) | (data[column] > upper_bound)]
    return outliers

# 示例使用
df = pd.read_csv('application_data.csv')
age_outliers = detect_outliers_iqr(df, 'age')
print(f"年龄字段异常值数量:{len(age_outliers)}")

提示:异常值不一定要删除。有时候异常值反而是重要的信号。比如某个人年龄填了18岁但收入填了50万,这可能是欺诈信号。我建议先标记,再分析,最后决定处理方式。

3.4 本章知识体系总览

说了这么多,咱们用一张图来总结一下本章的核心逻辑:

第三章:数据探索与采集知识体系 数据探索与采集 数据源 内部数据 外部数据 数据字典与元数据 字段定义 取值范围 数据质量 缺失值 异常值 数据质量决定模型上限

这张图把本章的核心内容串起来了。数据源是输入,数据字典是地图,数据质量是检查站。三者缺一不可。

最后说一句:数据探索这件事,没有捷径。你花的时间越多,后面建模就越顺。我见过太多人急着建模,结果数据问题没发现,模型上线后各种翻车。嗯,别急,慢慢来。


公众号:蓝海资料掘金营,微信deep3321