从反欺诈和信用违约预测比赛中我学到了什么

前几天参加了一个国外的比赛AgentDS Benchmark,内容是寻常的金融风控主题,最后取得了第五名的好成绩哈哈,虽说参加的人数并不多。一开始两个任务都设置了阈值,但是后来因为其中一个比赛超过阈值的人数太少了(只有我,比阈值高一点),官方就把阈值限制取消了。不然只有我能拿奖金。今天就来聊一聊在这个比赛中我学到了什么。

首先,这两个场景各自有侧重点:反欺诈是一个数据高度不平衡的场景,欺诈事件极为罕见,导致模型难以学习有意义的模式。而信用违约预测在需要复杂的模型来提升预测性能的同时,监管机构又要求高度的可解释性——必须能解释为什么某位客户被判定为高风险。

其次,这个比赛鼓励与AI进行协作,我主要是用了传统的机器学习方法进行建模,同时使用了大模型提供了一些新特征生成建议和调参建议。

建模步骤包括:数据整合,特征工程,模型训练和集成优化。

欺诈检测的主要目标是克服极端的数据不平衡。我们通过以下方式实现:


第一,数据缩放:我们选择了 RobustScaler 而非 StandardScaler,因为欺诈数据中充满了异常值——例如,欺诈交易的金额往往极高。RobustScaler 对异常值具有鲁棒性,因此不会让这些极端值扭曲我们的训练过程,而 StandardScaler 对此非常敏感。


第二,SMOTE合成采样:SMOTE(Synthetic Minority Over-sampling Technique,合成少数类过采样技术)是处理不平衡数据的经典解决方案。它不是简单地复制少数类样本(这会导致过拟合),而是通过在邻近的少数类样本点之间进行插值来生成新的合成样本。例如,我们会取一个欺诈样本,找到它的k个最近邻,随机选择其中一个,并在它们之间的连线上创建一个新样本。我们也尝试过在模型中调整类别权重,但SMOTE的效果要好得多。


第三,堆叠集成(stacking model):我们采用了堆叠方法,以逻辑回归作为元模型(meta-model),并为其设置了平衡的类别权重。尽管我们的基模型使用了SMOTE,但元模型的输入(即基模型的输出)仍然是不平衡的。这一步确保了元模型不会偏向多数类(合法交易),从而在保持精确率的同时提高了对欺诈案例的召回率。

对于信用违约预测,可解释性是重中之重——监管机构需要理解我们是如何得出风险评分的。

因此,我们专注于设计透明的特征,每个特征都具有清晰的金融含义。这些特征捕捉了三个关键维度:稳定性、恶化趋势和风险信号——这些都是预测未来一周内违约的关键。让我们看一些例子:

  • balance_slope:我们对客户每周的账户余额随时间变化进行线性回归。如果斜率显著小于0,意味着其余额在稳步下降——这是一个强烈的未来违约信号。

  • balance_last_minus_mean:该指标衡量客户当前余额与其历史平均值的偏差程度。一个很大的负数表明其当前账户状况远差于平常水平。

  • Balance_to_amount:平均余额与平均交易金额的比率。如果该比率过低,意味着客户很可能透支。

  • Negative_balance_ratio:客户在过去几周内账户余额为负的比例。频繁透支是未来违约的明确警示信号。

所有这些特征都很容易向监管机构解释,并且仍然能让模型表现极为出色——这证明了可解释性不必以牺牲性能为代价。

模型选择方面采用了常见了逻辑回归,xgboost和catboost,对于树模型,使用gridsearchCV进行调参,调参还是有一些技巧的,下面以反欺诈为例进行说明:

catboost调参:

总体策略:分阶段调优 (Sequential Tuning)

  1. 第一阶段 (   param_test1 ): 首先调整对模型性能影响最大、且相互关联最紧密的两个核心参数:   iterations  (树的数量) 和    learning_rate  (学习率)。
  1. 第二阶段 (   param_test2 ): 在固定了第一阶段找到的最佳    iterations  和    learning_rate  后,调整控制单棵树复杂度的参数:   depth  (深度) 和    l2_leaf_reg  (L2正则化)。
  1. 第三阶段 (   param_test3 ): 在固定了前两阶段的最佳参数后,调整与随机性和 bagging 相关的参数:   random_strength  和    bagging_temperature 。
  1. 第四阶段 (   param_test4 ): 最后,微调一个影响计算精度和速度的参数:   border_count 。

这种顺序是合理的,因为前两个参数(迭代次数和学习率)奠定了模型的基础性能,而后续参数更多是在此基础上进行微调和正则化。


各阶段参数组合选择原因详解

阶段 1:    param_test1  - 调整基础学习动力
param_test1 = {

'iterations': [100, 200, 300],

'learning_rate': [0.03, 0.1, 0.2]

}
  • 核心目标: 找到模型学习的“节奏”和“步长”的最佳平衡点。
  •    iterations     [100, 200, 300] :
  •    100 : 作为保守的起点,训练速度快,用于快速评估模型基线。
  •    200 : 一个常用的中间值,平衡了性能和计算成本。
  •    300 : 测试更高复杂度的模型是否能带来显著收益,但也增加了过拟合和计算时间的风险。
  •    learning_rate     [0.03, 0.1, 0.2] :
  •    0.03 : 小学习率,需要更多    iterations  来收敛,但通常能得到更鲁棒、泛化能力更强的模型。
  •    0.1 : 经典默认值,学习速度适中。
  •    0.2 : 较大的学习率,学习速度快,但可能不稳定或错过最优解,容易过拟合。
  • 组合逻辑: 这个网格旨在探索从“慢而稳”(低学习率+高迭代)到“快而糙”(高学习率+低迭代)的各种组合,以找到最适合该数据集的基础配置。
阶段 2:    param_test2  - 调整模型复杂度与正则化
param_test2 = {

'depth': [4, 6, 8, 10],

'l2_leaf_reg': [1, 3, 5, 7, 9]

}
  • 核心目标: 在已确定的学习节奏下,控制单棵树的复杂度并施加正则化以防止过拟合。
  •    depth     [4, 6, 8, 10] :
  • 这是一个从浅到深的范围。CatBoost 通常在    depth  为 3-10 时表现良好。
  •    4 : 浅树,强正则化,抗过拟合能力强。
  •    6/8 : 中等深度,允许模型捕捉更复杂的特征交互,是实践中最常见的选择。
  •    10 : 深树,模型容量大,但极易过拟合,尤其是在数据量不大或噪声多的情况下。
  •    l2_leaf_reg     [1, 3, 5, 7, 9] :
  • 这是应用于叶子节点值的 L2 正则化系数。它通过惩罚过大的叶子值来平滑模型预测,是防止过拟合的关键手段。
  •    1 : 弱正则化,允许模型更自由地拟合数据。
  •    3/5 : 中等强度的正则化,通常是很好的起点。
  •    7/9 : 强正则化,会显著约束模型,可能导致欠拟合,但在数据噪声很大时很有用。
  • 组合逻辑: 深度越深,模型越复杂,就越需要更强的正则化(更高的    l2_leaf_reg )来平衡。这个网格系统地测试了不同复杂度与不同正则化强度的组合。
阶段 3:    param_test3  - 调整随机性
param_test3 = {

'random_strength': [0.5, 1, 2, 3],

'bagging_temperature': [0.8, 1.0, 1.2, 1.5]

}

  • 核心目标: 通过引入受控的随机性来进一步提升模型的泛化能力和鲁棒性,减少过拟合。
  •    random_strength     [0.5, 1, 2, 3] :
  • 这个参数在分数计算时添加随机噪声。值越大,随机性越强。
  •    0.5/1 : 轻微的随机性,主要用于打破特征选择中的平局。
  •    2/3 : 更强的随机性,可以作为一种正则化形式,使模型对训练数据的微小变化不那么敏感,从而提升泛化能力。
  •    bagging_temperature     [0.8, 1.0, 1.2, 1.5] :
  • 这个参数控制在 Bagging(自助采样)过程中选择观测值的概率分布的形状。
  •    1.0 : 标准的 Bagging 行为。
  •    <1.0 (0.8) : 使采样更均匀,每个样本被选中的概率更接近。
  •    >1.0 (1.2, 1.5) : 使采样更偏向于某些样本,增加了多样性。
  • 组合逻辑: 这两个参数都是为了增加模型的随机性和多样性。它们的作用相对微妙,通常在核心参数调优后进行微调,以榨取最后一点性能提升。
阶段 4:    param_test4  - 调整计算精度
param_test4 = {

'border_count': [32, 64, 128]

}

  • 核心目标: 微调数值特征的分桶数量,这会影响模型的精度和训练速度。
  •    border_count     [32, 64, 128] :
  • CatBoost 会对连续特征进行分桶(离散化),   border_count  决定了桶的数量。
  •    32 : 默认值,提供了良好的速度和精度平衡。
  •    64/128 : 更多的桶意味着对连续特征的划分更精细,理论上可以捕捉到更细微的模式,从而可能略微提升精度。但代价是训练时间会增加,并且在数据量不足时可能导致过拟合。
  • 组合逻辑: 这是一个典型的精度与速度的权衡。在其他所有重要参数都已优化后,可以尝试增加    border_count  看是否能获得微小的性能增益。

总结

这种分阶段的调参方法 (   param_test1  ->    param_test4 ) 是一种高度结构化和高效的策略:

  1. 由主到次: 先优化对性能影响最大的参数(学习率、迭代次数),再逐步处理影响较小的参数(随机性、计算精度)。
  1. 利用已有信息: 每个新阶段都固定了前一阶段找到的最佳参数,大大缩小了搜索空间。
  1. 逻辑清晰: 每个阶段都有明确的目标(如控制复杂度、增加随机性),使得调参过程更有目的性,而非盲目搜索。

通过这种方式,可以在有限的计算资源下,系统地逼近全局最优或接近最优的超参数组合。

xgboost调参:

总体策略:分阶段调优 (Sequential Tuning)

  1. 第一阶段 (   param_test1 ): 调整最核心的学习率 (   learning_rate ) 和树的数量 (   n_estimators )。
  1. 第二阶段 (   param_test2 ): 在固定了学习率和树的数量后,调整控制单棵树结构和复杂度的参数:最大深度 (   max_depth ) 和子节点最小样本权重和 (   min_child_weight )。
  1. 第三阶段 (   param_test3 ): 调整用于控制叶子节点分裂的正则化参数:伽马 (   gamma )。
  1. 第四阶段 (   param_test4 ): 调整L1和L2正则化参数 (   reg_alpha ,    reg_lambda ) 以进一步防止过拟合。
  1. 第五阶段 (   param_test5 ): 最后,调整随机采样比例参数 (   subsample ,    colsample_bytree ) 以增加模型的随机性和鲁棒性。

这种顺序遵循了XGBoost调参的经典最佳实践,从宏观到微观,从基础到细节。


各阶段参数组合选择原因详解

阶段 1:    param_test1  - 确定基础学习框架
param_test1 = {

'n_estimators': [100, 200, 300],

'learning_rate': [0.05, 0.1, 0.2]

}
  • 核心目标: 找到模型学习的“步长”和“步数”的最佳平衡。
  •    n_estimators     [100, 200, 300] : 测试从小型(100棵树)到中等规模(300棵树)的集成模型,以评估模型容量对性能的影响。
  •    learning_rate     [0.05, 0.1, 0.2] :
  •    0.05 : 小学习率,通常需要更多树,但能产生更稳健的模型。
  •    0.1 : 经典默认值,是很好的起点。
  •    0.2 : 较大学习率,收敛快,但可能不稳定。
  • 逻辑: 这两个参数高度耦合。此阶段旨在为整个调优过程奠定一个坚实的基础。
阶段 2:    param_test2  - 控制树的复杂度
param_test2 = {

'max_depth': range(3, 10, 2), # [3,5,7,9]

'min_child_weight': range(1, 6, 2) # [1,3,5]

}
  • 核心目标: 在已确定的学习框架下,控制单棵树的复杂度以管理偏差-方差权衡。
  •    max_depth     [3, 5, 7, 9] :
  •    3 : 非常浅的树,强正则化,抗过拟合。
  •    5/7 : 中等深度,XGBoost的常用范围,能捕捉复杂的特征交互。
  •    9 : 深树,模型容量大,但极易过拟合。
  •    min_child_weight     [1, 3, 5] :
  • 定义了叶子节点所需包含的最小样本权重和。它作为预剪枝(pre-pruning)机制,防止模型学习过于具体的模式(即过拟合)。
  • 值越大,算法越保守,生成的树越简单。
  • 逻辑: 更深的树(高   max_depth )通常需要更高的   min_child_weight 来平衡其复杂性,防止过拟合。
阶段 3:    param_test3  - 调整分裂正则化
param_test3 = {

'gamma': [i/10.0 for i in range(0, 5)] # [0, 0.1, 0.2, 0.3, 0.4]

}
  • 核心目标: 微调叶子节点分裂的门槛。
  •    gamma     [0, 0.1, ..., 0.4] :
  •    gamma  是一个后剪枝(post-pruning)参数。它指定了一个分裂必须带来的最小损失减少量,否则该分裂将被阻止。
  •    0 : 不施加任何额外的分裂惩罚。
  •    >0 : 值越大,算法越保守,生成的树越简单、越不容易过拟合。
  • 逻辑: 在树的结构(   max_depth )和基本复杂度(   min_child_weight )确定后,   gamma  提供了一种更精细的方式来控制模型的最终复杂度。
阶段 4:    param_test4  - 应用L1/L2正则化
param_test4 = {

'reg_alpha': [0, 0.001, 0.01, 0.1, 1],

'reg_lambda': [0, 0.001, 0.01, 0.1, 1]

}
  • 核心目标: 对叶子权重直接施加L1(Lasso)和L2(Ridge)正则化,这是防止过拟合的最后防线。
  •    reg_alpha  &    reg_lambda :
  • 这些参数直接在目标函数中添加惩罚项。
  • 测试从    0 (无正则化)到    1 (强正则化)的对数尺度值,以全面探索正则化强度的影响。
  • L1 (   reg_alpha ) 可以促使部分叶子权重变为0,起到特征选择的作用;L2 (   reg_lambda ) 则倾向于让所有权重都变小。
  • 逻辑: 在树的结构和分裂规则都已优化后,通过直接约束叶子权重的大小来进行最终的平滑和泛化能力提升。
阶段 5:    param_test5  - 引入随机性 (Subsampling)
param_test5 = {

'subsample': [0.6, 0.7, 0.8, 0.9, 1.0],

'colsample_bytree': [0.6, 0.7, 0.8, 0.9, 1.0]

}
  • 核心目标: 通过随机采样增加模型的多样性,降低方差,提高鲁棒性。
  •    subsample : 控制每次构建树时使用的样本比例。小于1.0可以有效防止过拟合(类似Bagging)。
  •    colsample_bytree : 控制每次构建树时使用的特征比例。这不仅能加速训练,还能通过引入随机性来提升模型性能,并减少对少数强特征的依赖。
  • 逻辑: 这是调优的最后一步。在模型的所有确定性部分都已优化后,通过引入受控的随机性来进一步提升其在未知数据上的表现。

总结

这种五阶段的调参方法 (   param_test1  ->    param_test5 ) 是XGBoost调优的黄金标准

  1. 逻辑清晰: 遵循从基础学习参数 -> 树结构 -> 分裂规则 -> 权重正则化 -> 随机采样的清晰路径。
  1. 高效经济: 每个阶段只关注少数几个相关参数,大大减少了总的计算量。
  1. 效果显著: 通过系统地优化模型的各个层面,能够有效地逼近最优性能,同时很好地控制过拟合风险。

虽说参加这个比赛拿到了名次,还是觉得自己水水的,可能是因为现在AI越来越智能了,很多基础的内容AI都能替我做,所以感觉基本功不扎实。这确实是一个需要好好锻炼的地方,希望读到这里的你也一起加油吧!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值