共计 1508 个字符,预计需要花费 4 分钟才能阅读完成。
背景痛点
金融风控场景常面临三类典型挑战:
- 高维稀疏数据:用户行为日志、设备指纹等特征维度可达上万,但有效信息密度低。例如 IP 地址字段的基数超过百万,传统 One-Hot 编码会导致维度爆炸。
- 类别不平衡:欺诈样本占比通常不足 1%,直接训练会使模型偏向多数类。实测显示原始数据训练时 Recall 仅 0.03。
- 特征共线性:用户画像中年龄与工作年限等特征皮尔逊相关系数达 0.82,导致传统逻辑回归系数不稳定。
技术选型对比
通过同一数据集对比三种算法效果:
| 模型 | AUC | 训练时间(s) | 内存峰值(GB) |
|---|---|---|---|
| 逻辑回归 | 0.712 | 8.2 | 1.1 |
| 随机森林 | 0.783 | 63.5 | 4.7 |
| XGBoost | 0.821 | 29.8 | 2.3 |
XGBoost 在 AUC 指标上优势明显,因其具备:
1. 显式处理缺失值机制
2. 二阶导数优化目标函数
3. 内置正则化项 $\Omega(\theta)=\gamma T + \frac{1}{2}\lambda||w||^2$
核心实现
特征工程
采用分层 Target Encoding 处理分类变量:
def target_encode(df: pd.DataFrame, col: str, target: str, alpha: float=5) -> pd.Series:
global_mean = df[target].mean()
agg = df.groupby(col)[target].agg(['count', 'mean'])
return (agg['count'] * agg['mean'] + alpha * global_mean) / (agg['count'] + alpha)
样本平衡
使用 SMOTE 生成合成样本时需注意:
- 仅对训练集应用 SMOTE
- 设置 k_neighbors 参数不超过少数类样本量
- 搭配 Tomek Links 清除边界噪声
贝叶斯优化
基于 hyperopt 的调参示例:
from hyperopt import fmin, tpe, hp
space = {'max_depth': hp.quniform('max_depth', 3, 8, 1),
'eta': hp.loguniform('eta', -5, 0),
'subsample': hp.uniform('subsample', 0.6, 1)
}
def objective(params):
params['max_depth'] = int(params['max_depth'])
cv = xgb.cv(params, dtrain, num_boost_round=100, nfold=5,
early_stopping_rounds=10, metrics='auc')
return -cv['test-auc-mean'].max()
best = fmin(objective, space, algo=tpe.suggest, max_evals=50)
性能验证
通过 5 折交叉验证得到 ROC 曲线对比:

关键指标提升:
- F1-score 从 0.21→0.45
- AUC 提升 0.17
- 误杀率降低 34%
避坑指南
特征泄露预防
- 时间戳特征必须严格滞后于标签产生时间
- 目标编码需按时间划分训练 / 验证集
- 使用
sklearn.pipeline.Pipeline封装预处理步骤
模型漂移监控
建议部署以下检测机制:
- 周级 PSI(Population Stability Index)计算
- 特征分布 KL 散度检测
- 决策边界样本抽样复核
代码规范
所有 Python 代码需通过以下检查:
- mypy 静态类型检查
- flake8 格式验证
- 函数文档字符串包含 Google Style 格式的 Args/Returns 说明
思考题
当 SHAP 值显示某个特征的重要性突然下降时,可能由哪些原因导致?应如何排查?
(提示:考虑数据管道变化、业务规则调整、特征共线性等因素)
正文完
发表至: 未分类
近两天内
