风控不平衡数据建模之Focal Loss
文章目录
一、风控中样本不平衡的挑战
在风控模型建设中,面临的一个核心问题是如何从海量的正常交易或行为中,准确地识别出少量的风险或异常事件。这种问题的根本困难在于,大量的负样本(正常事件)与极少数的正样本(风险事件)形成了极端的不平衡比例,导致模型在训练过程中容易偏向于多数类,而忽视少数但更重要的正样本。这种偏向不仅降低了模型对风险事件的敏感性,也大大限制了其在实际风控场景中的应用价值。
为了解决上述问题,Focal Loss被提出并广泛应用于处理不平衡数据集的场景。其核心优势在于能够通过调整损失函数,使模型在训练过程中更加关注难以分类的少数类样本,从而提升对风险事件的预测准确性。
二、Focal Loss的计算原理
Focal Loss是在传统的交叉熵损失函数基础上进行改进的,它是一个动态缩放的交叉熵损失,通过引入两个关键的调整参数——权重因子(α )和聚焦参数(γ),来动态降低训练过程中易区分样本的权重,从而将重心快速聚焦在那些难区分的样本上,具体的表达式如下:
其中, 是模型对当前类别预测的概率, 是用于调节正负样本贡献度的权重系数, 则是聚焦参数,用以减少易分类样本对损失的贡献,增加难分类样本的影响力。
三、Focal Loss参数取值范围
1.权重因子
作用:用于调节不同类别之间的重要性,常用于解决类别不平衡的问题。较高的 值(小于1)可以增加少数类的重要性,当 =1时,Focal Loss退化为标准的交叉熵损失。
取值范围:通常取值在 [0, 1] )之间。在某些情况下, 也可以根据类别的频率动态调整。
2.聚焦参数
作用:调节难易分类样本的影响,当 较大时,模型更加关注那些难以正确分类的样本(即 较小的样本),当 =0时,Focal Loss退化为标准的交叉熵损失函数。
取值范围:通常 的取值在 [0, 5] 范围内。根据原始论文的实验, = 2 是一个常用的选择。
四、Focal Loss对风控模型的影响
- 提升少数类样本的识别能力:通过减少多数类样本对损失的贡献,Focal Loss使模型更加专注于那些难以识别的少数类样本,从而提高了风险事件的检测率。
- 平衡样本权重:通过调节参数α,Focal Loss进一步平衡了正负样本在损失计算中的权重,有效缓解了因样本不平衡导致的模型偏差问题。
- 增强模型鲁棒性:通过聚焦于难分类的样本,Focal Loss促进模型学习到更加复杂和微妙的数据特征,从而提高模型对未见样本的泛化能力,增强了模型在实际应用中的鲁棒性。
五、Focal Loss实现代码
PyTorch版本
import torch
import torch.nn as nn
import torch.nn.functional as F
def focal_loss(gamma=2.0, alpha=0.25):
"""
创建一个二分类的 Focal Loss 函数。
:param gamma: 调节因子,用于减少易分样本的权重
:param alpha: 平衡因子,用于调节正负样本的权重
"""
def binary_focal_loss(y_true, y_pred):
"""
Focal Loss 的 PyTorch 实现。
:param y_true: 真实的标签,形状与 y_pred 相同
:param y_pred: 预测的概率,通常来自网络的 sigmoid 输出
"""
# 为避免计算log时出现NaN,添加一个小的epsilon值
epsilon = 1e-6
y_pred = torch.clamp(y_pred, min=epsilon, max=1-epsilon)
# 计算focal loss的组件
cross_entropy_loss = -y_true * torch.log(y_pred) - (1 - y_true) * torch.log(1 - y_pred)
loss = alpha * torch.pow(1 - y_pred, gamma) * cross_entropy_loss
return torch.mean(loss)
return binary_focal_loss
TensorFlow版本
import tensorflow as tf
# y_true:代表真实的标签,通常是一个二元向量,其中包含了样本的实际类别
# y_pred:代表模型预测的类别概率,通常是一个在 0 到 1 之间的值,表示样本属于正类的概率
# 对应二分类问题
def focal_loss(gamma=2.0, alpha=0.25):
def binary_focal_loss(y_true, y_pred):
# 为避免计算log时出现NaN,添加一个小的epsilon值
y_pred = tf.clip_by_value(y_pred, tf.keras.backend.epsilon(), 1 - tf.keras.backend.epsilon())
# 计算focal loss的组件
y_true_float = tf.cast(y_true, tf.float32)
cross_entropy_loss = -y_true_float * tf.math.log(y_pred) - (1.0 - y_true_float) * tf.math.log(1 - y_pred)
loss = alpha * tf.pow(1 - y_pred, gamma) * cross_entropy_loss
return tf.reduce_mean(loss)
return binary_focal_loss