3. 特征工程基础:特征类型、质量评估与缺失值异常值处理
在催收模型中,原始数据无法直接喂给 LightGBM。特征工程是将原始数据转化为模型可理解、可学习的数值特征的过程。本章将系统讲解催收场景下的特征类型划分、质量评估方法以及缺失值与异常值的处理策略,为后续特征筛选打下坚实基础。
3.1 特征类型:数值型、类别型、时序型
催收数据中的特征可按其数学性质分为三大类,不同类型决定了后续编码与变换方式。
| 特征类型 | 定义 | 催收场景举例 | LightGBM 处理要点 |
|---|---|---|---|
| 数值型 | 连续或离散的数值,有大小和顺序意义 | 逾期天数、欠款金额、历史还款次数、年龄 | 可直接输入;建议做分箱或归一化以提升鲁棒性 |
| 类别型 | 有限个离散取值,无大小顺序(或顺序无意义) | 城市、职业、产品类型、催收员ID | 需转换为整数编码;高基数类别建议使用计数编码或目标编码 |
| 时序型 | 与时间顺序相关的特征,包含趋势、周期、间隔 | 最近联系时间、逾期起始日期、账单日 | 需提取时间差、星期几、月份、节假日标志等衍生特征 |
实战提示: 催收模型中,时序型特征往往比静态数值型特征更重要。例如“距离上次还款的天数”比“总欠款金额”更能预测短期还款意愿。建议将原始时间戳转化为相对时间差后再输入模型。
3.2 特征质量评估
特征质量直接影响模型上限。在催收场景中,我们通常从以下四个维度评估每个特征的质量:
- 覆盖率: 特征非空比例。覆盖率低于 60% 的特征需谨慎使用,除非缺失本身具有业务含义。
- 区分度: 特征在不同目标类别(如“已还款” vs “未还款”)上的分布差异。常用指标为 IV 值(信息量)或 KS 统计量。
- 稳定性: 特征分布随时间的变化程度。使用 PSI(群体稳定性指标)衡量,PSI > 0.25 的特征建议剔除。
- 相关性: 特征与目标变量之间的关联强度,以及特征之间的多重共线性。催收模型中,与“逾期天数”高度相关的特征需注意去冗余。
催收特征质量速查表:
✅ 覆盖率 > 80% → 优质
✅ IV > 0.1 → 有区分力
✅ PSI < 0.1 → 高度稳定
✅ 相关系数 |r| < 0.8 → 无严重共线性
✅ 覆盖率 > 80% → 优质
✅ IV > 0.1 → 有区分力
✅ PSI < 0.1 → 高度稳定
✅ 相关系数 |r| < 0.8 → 无严重共线性
3.3 缺失值处理
催收数据中缺失值普遍存在,原因包括:客户未填写、系统未采集、数据源合并丢失等。处理策略需结合业务含义与模型特性。
3.3.1 缺失值类型判断
- 完全随机缺失(MCAR): 缺失与任何变量无关。可直接删除或填充均值/中位数。
- 随机缺失(MAR): 缺失与其他观测变量相关。例如高逾期客户更可能缺失联系电话。建议使用模型预测填充。
- 非随机缺失(MNAR): 缺失与缺失值本身相关。例如“收入”字段,高收入者可能故意不填。此时缺失本身可作为重要特征。
3.3.2 催收场景推荐处理方案
| 特征类型 | 缺失率 < 5% | 缺失率 5%–30% | 缺失率 > 30% |
|---|---|---|---|
| 数值型 | 中位数填充 | 中位数填充 + 新增“是否缺失”标志 | 保留缺失标志,数值填充为 -999 或 0(需业务确认) |
| 类别型 | 众数填充 | 众数填充 + 新增“缺失”类别 | 将“缺失”作为独立类别编码 |
| 时序型 | 前向填充或线性插值 | 前向填充 + 缺失时长特征 | 仅保留缺失时长特征,原始值丢弃 |
避坑提醒: 不要对催收数据中的“逾期天数”做均值填充!逾期天数的缺失往往意味着该笔贷款尚未进入逾期阶段,此时应填充为 0 而非均值。务必先理解缺失的业务含义。
3.4 异常值处理
异常值在催收数据中常见于:欠款金额极端高、联系次数异常多、年龄超出合理范围等。异常值会拉偏 LightGBM 的分裂点,导致模型泛化能力下降。
3.4.1 异常值检测方法
- IQR 法: 超出 Q1 - 1.5×IQR 或 Q3 + 1.5×IQR 的值视为异常。适用于近似正态分布的特征。
- Z-Score 法: |Z| > 3 视为异常。适用于数据量较大且分布对称的场景。
- 业务规则法: 例如“年龄 < 18 或 > 70”、“欠款金额为负数”等直接定义为异常。
- 孤立森林: 无监督方法,适合高维特征空间中的异常检测。
3.4.2 异常值处理策略
| 策略 | 适用场景 | 催收案例 |
|---|---|---|
| 截断(Winsorize) | 特征分布长尾,异常值数量少 | 将“欠款金额”上限设为 99% 分位数 |
| 分箱 | 异常值有业务含义,但数值不稳定 | 将“联系次数”分为 0、1-3、4-10、>10 四档 |
| 单独编码 | 异常值代表特殊群体 | “年龄 > 65”单独标记为“高龄客群” |
| 删除 | 确认是录入错误且样本量充足 | “逾期天数 = -5”明显错误,直接删除该样本 |
催收实战建议: 对于“欠款金额”这类长尾分布特征,推荐使用 对数变换 + 截断 的组合方式。先取 log(1+x) 压缩尺度,再在 99.5% 分位数处截断,既能保留区分度,又能抑制极端值对 LightGBM 分裂的干扰。
3.5 特征类型与处理流程总览
下图总结了从原始特征到清洗后特征的完整处理流程,帮助你在实际项目中按步骤操作:
3.6 代码实战:缺失值与异常值处理示例
以下代码展示了在 Python 中对催收数据集进行缺失值填充与异常值截断的典型操作:
import pandas as pd
import numpy as np
# 示例数据:催收样本
df = pd.DataFrame({
'逾期天数': [15, 30, None, 60, 90, None, 45, 120, 180, 5],
'欠款金额': [2000, 5000, 3000, 15000, 80000, 4000, 6000, 200000, 3500, 2500],
'年龄': [28, 35, 42, None, 55, 31, 29, 48, 22, 38],
'城市': ['北京', '上海', None, '广州', '深圳', '北京', '上海', None, '广州', '深圳']
})
# 1. 缺失值处理
# 数值型:中位数填充 + 缺失标志
for col in ['逾期天数', '年龄']:
df[f'{col}_缺失标志'] = df[col].isna().astype(int)
df[col].fillna(df[col].median(), inplace=True)
# 类别型:众数填充 + 缺失类别
df['城市'].fillna('未知', inplace=True)
# 2. 异常值处理:IQR 截断
def winsorize_series(s, lower=0.01, upper=0.99):
q_low = s.quantile(lower)
q_high = s.quantile(upper)
return s.clip(lower=q_low, upper=q_high)
df['欠款金额_截断'] = winsorize_series(df['欠款金额'])
# 3. 时序特征衍生(假设有日期字段)
# df['逾期起始日'] = pd.to_datetime(df['逾期起始日'])
# df['逾期持续天数'] = (pd.Timestamp.today() - df['逾期起始日']).dt.days
print("处理完成,特征维度:", df.shape)
print(df.head())
代码要点:
• 对“逾期天数”使用中位数填充,避免均值被极端值拉偏。
• 对“欠款金额”做分位数截断,保留 99% 的正常样本分布。
• 类别型特征“城市”将缺失值作为独立类别“未知”处理,保留缺失信息。
• 建议在实际项目中为每个数值型特征都生成一个“缺失标志”特征,LightGBM 可以自动学习缺失模式。
• 对“逾期天数”使用中位数填充,避免均值被极端值拉偏。
• 对“欠款金额”做分位数截断,保留 99% 的正常样本分布。
• 类别型特征“城市”将缺失值作为独立类别“未知”处理,保留缺失信息。
• 建议在实际项目中为每个数值型特征都生成一个“缺失标志”特征,LightGBM 可以自动学习缺失模式。
3.7 本章小结
特征工程是催收模型成功的关键起点。通过本章学习,你应掌握:
- 区分数值型、类别型、时序型特征,并针对不同类型选择编码与变换方式。
- 从覆盖率、区分度、稳定性、相关性四个维度评估特征质量。
- 根据缺失率与业务含义,选择中位数填充、众数填充、缺失标志或独立类别等策略。
- 使用 IQR 截断、分箱或业务规则处理异常值,避免极端值干扰模型分裂。