第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都输出一份报告,记录关键发现。
好了,数据准备和探索这部分就聊到这儿。记住一句话:花80%的时间在数据上,模型自然就水到渠成。下一章咱们聊聊特征工程,那才是真正考验功力的地方。