第1章:数据准备与探索

做风控模型这么多年,我最大的体会就是:数据质量决定了模型的天花板。算法再牛,给一堆脏数据也白搭。今天咱们就聊聊数据准备和探索这第一步,说白了就是「把食材洗干净再下锅」。

1.1 数据源介绍

信用评分卡的数据来源,我习惯分成三大类。你想想看,银行要判断一个人还不还钱,总得从不同角度去了解他吧?

征信数据

这是最核心的数据源。央行征信报告里,有贷款记录、信用卡还款情况、担保信息等。我记得刚入行时,有个项目就因为没处理好征信报告里的「连三累六」规则,模型上线后坏账率直接飙升。嗯,从那以后我对征信数据就格外小心。

  • 信贷历史:贷款笔数、逾期次数、当前负债
  • 查询记录:硬查询次数(贷款审批、信用卡审批)
  • 公共记录:法院执行、税务欠款等

行为数据

这是用户在你平台上的「活数据」。比如消费习惯、登录频率、还款方式等。我个人习惯把行为数据看作「征信数据的补充」,它能捕捉到征信报告里看不到的细节。

  • 交易行为:消费金额、消费时间、消费类型
  • 还款行为:是否提前还款、还款渠道、逾期天数
  • 活跃度:APP登录频率、页面停留时间

第三方数据

现在市面上有很多第三方数据服务商,比如百融、同盾、前海征信等。它们提供反欺诈评分、多头借贷检测、设备指纹等。我在项目中遇到过,有些第三方数据质量参差不齐,一定要做交叉验证。

  • 反欺诈数据:黑名单、团伙欺诈识别
  • 多头借贷:同时在多少家平台借款
  • 社交网络:通讯录关系、通话记录

1.2 数据质量检查

数据拿到手,第一件事不是建模,而是检查质量。我见过太多人上来就跑模型,结果跑出来一堆垃圾。为什么会这样?因为数据质量不过关。

数据质量检查清单

  • 完整性:有没有大量缺失值?
  • 准确性:数值是否在合理范围内?比如年龄200岁,明显有问题
  • 一致性:同一字段在不同表中是否一致?
  • 时效性:数据是否是最新的?
  • 唯一性:有没有重复记录?

举个实际例子。有一次我检查一个数据集,发现「收入」字段有30%的缺失,还有5%的值是负数。你想想看,收入为负?这明显是数据录入错误。后来一查,是系统把退款金额也记进去了。

1.3 缺失值处理

缺失值处理,说白了就是「缺了怎么办」。我个人习惯先看缺失比例,再决定处理方式。

缺失比例 处理方式 适用场景
<5% 直接删除 样本量足够大时
5%-20% 均值/中位数填充 数值型变量
20%-50% 模型预测填充 有相关变量时
>50% 单独作为一类 分类变量

小技巧:对于信用评分卡,我建议把「缺失」本身作为一个特征。因为有时候「不填信息」本身就是一种风险信号。比如收入不填的人,可能收入不稳定。

# 缺失值处理示例
import pandas as pd
import numpy as np

# 查看缺失比例
def missing_ratio(df):
    return df.isnull().sum() / len(df)

# 数值型:中位数填充
df['income'].fillna(df['income'].median(), inplace=True)

# 分类型:单独一类
df['education'].fillna('未知', inplace=True)

1.4 异常值处理

异常值,就是那些「离谱」的数据。比如年龄200岁,月收入1000万。我曾经在一个项目中,发现有个用户的「月消费金额」是平均值的100倍,一查发现是系统把企业转账也记进去了。

怎么识别异常值?我常用两种方法:

  • 3σ原则:超出均值±3倍标准差的数据
  • 箱线图法:超出1.5倍IQR的数据

注意:不要一刀切删除异常值。有些异常值其实是「高价值客户」或者「欺诈用户」,需要结合业务判断。我建议先标记,再单独分析。

# 异常值检测示例
def detect_outliers_iqr(data, column):
    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
    return data[(data[column] < lower_bound) | (data[column] > upper_bound)]

1.5 数据探索性分析(EDA)

EDA,说白了就是「先看看数据长什么样」。我习惯从三个维度入手:

单变量分析

看每个变量自己的分布。比如年龄分布是否合理?收入是否呈长尾分布?

  • 连续变量:直方图、箱线图、描述性统计
  • 分类变量:频数统计、柱状图

双变量分析

看变量和目标变量(是否违约)的关系。比如年龄越大违约率越低?收入越高违约率越低?

  • 连续变量 vs 目标:分箱后看违约率
  • 分类变量 vs 目标:交叉表、卡方检验

多变量分析

看变量之间的相关性。避免多重共线性,比如「贷款金额」和「月还款额」高度相关,建模时只能选一个。

# EDA示例
import matplotlib.pyplot as plt
import seaborn as sns

# 单变量:年龄分布
plt.figure(figsize=(10, 6))
sns.histplot(df['age'], bins=30)
plt.title('年龄分布')
plt.show()

# 双变量:年龄与违约率
df['age_bin'] = pd.cut(df['age'], bins=[18, 25, 35, 45, 55, 65])
age_default = df.groupby('age_bin')['default'].mean()
print(age_default)

# 相关性矩阵
corr_matrix = df.corr()
sns.heatmap(corr_matrix, annot=True, cmap='coolwarm')

核心要点:EDA不是走过场,而是帮你发现数据中的「故事」。比如某个年龄段的违约率特别高,那可能就是风险集中区。我建议每次EDA都输出一份报告,记录关键发现。

数据准备与探索核心流程 数据源 征信数据 行为数据 第三方数据 数据质量检查 完整性 准确性 一致性/时效性 数据预处理 缺失值处理 异常值处理 EDA探索性分析 单变量 双变量 多变量 高质量建模数据 数据准备是建模的基础,质量决定上限

好了,数据准备和探索这部分就聊到这儿。记住一句话:花80%的时间在数据上,模型自然就水到渠成。下一章咱们聊聊特征工程,那才是真正考验功力的地方。

专注资料整理