【风控模型】特征工程之类别不平衡问题

在风控场景中, 由于正样本获取的成本较高, 往往样本比例是失衡的, 样本的不平衡很容易导致模型偏向比例较高的一方

imbalanced-learn

imbalanced-learn 是一个MIT许可开源的源代码库, 依赖于 scikit-learn 库, 为处理不均衡的分类问题提供工具.

conda install -c conda-forge imbalanced-learn

注: 利用 jupyter notebook 使用时, 需要重新打开 jupyter notebook 才能正常生效, 否则会报异常.

利用 make_classification 生成仿真样本.

from sklearn.datasets import make_classification
X, y = make_classification(
    n_samples = 5000, n_features = 2, n_informative = 2,
    n_redundant = 0, n_repeated = 0, n_classes = 3,
    n_clusters_per_class = 1,
    weights=[0.01, 0.09, 0.9],
    class_sep = 0.8, random_state = 0
)
from collections import Counter
Counter(y)
# Counter({2: 4477, 1: 459, 0: 64})

过采样

对于风控场景中, 常常遇到的就是正样本(如网贷逾期)过少等, 需要针对正样本进行过采样.

随机过采样

随机过采样: 针对少数类样本提供精确精确副本, 由于精确副本的重复采样, 可能会导致严重的过拟合.

from imblearn.over_sampling import RandomOverSampler
X_resampled, y_resampled = RandomOverSampler(random_state=0).fit_resample(X, y)
Counter(y_resampled)
# Counter({2: 4477, 1: 4477, 0: 4477})

SMOTE

SMOTE(synthetic minority oversampling technique) 的思想概括起来就是在少数类样本之间进行插值来产生额外的样本.

对于一个少数类样本 \(x_i\) 使用 K 近邻法, 求出离 \(x_i\) 距离最近的 \(k\) 个少数类样本,其中距离定义为样本之间 \(n\)维特征空间的欧氏距离.然后从 \(k\) 个近邻点中随机选取一个,使用下列公式生成新样本:

\[ x_{new} = x_i + (\hat{x}_i - x_i) \times \delta \]

其中 \(\hat{x}_i\) 为选出的 \(k\) 近邻点, \(\delta \; in \; \lbrack 0, 1 \rbrack\) 是一个随机数.

下图来自于机器学习之类别不平衡问题 (3) —— 采样方法, 是一个SMOTE生成样本的例子,使用的是3-近邻,可以看出SMOTE生成的样本一般就在 \(x_i\)\(x_{zi}\) 相连的直线上:

SMOTE生成新样本

缺陷:

  • 如果选取的少数类样本周围也都是少数类样本,则新合成的样本不会提供太多有用信息.
  • 如果选取的少数类样本周围全是多数类样本,这类的样本可能是噪音,则新合成的样本会与周围的多数类样本产生大部分重叠,致使分类困难.
from imblearn.over_sampling import SMOTE
X_resampled, y_resampled = SMOTE(random_state=0).fit_resample(X, y)
Counter(y_resampled)
# Counter({2: 4477, 1: 4477, 0: 4477})

ADASYN

ADASYN (adaptive synthetic sampling): 采用某种机制自动决定每个少数类样本需要产生多少合成样本,而不是像SMOTE那样对每个少数类样本合成同数量的样本.

  1. 首先计算需要合成的样本总量:

    \[ G = (S_{maj} - s_{min}) \times \beta \]

    其中:

    • \(S_{maj}\): 多数类样本数量
    • \(s_{min}\): 少数类样本数量
    • \(\beta\): 系数
    • \(G\): 总共想要合成的少数类样本数量

    如果 \(\beta = 1\) 则是合成后各类别数目相等. ​

  2. 对于每个少类别样本\(x_i\),找出其 K 近邻个点

    \[ \Gamma_i = \frac{\Delta_i / K}{Z} \]

    其中:

    • \(\Delta_i\): K 近邻个点中多数类样本的数量
    • \(Z\): 规范化因子以确保 \(\Delta_i\) 构成一个分布.

    若一个少数类样本 \(x_i\) 的周围多数类样本越多,则其 \(\Gamma_i\) 也就越高. ​

  3. 最后对每个少类别样本 \(x_i\) 计算需要合成的样本数量 \(g_i\) ,再用 SMOTE 算法合成新样本:

    \[ g_i = \Gamma_i \times G \]

    缺点: 易受离群点的影响,如果一个少数类样本的K近邻都是多数类样本,则其权重会变得相当大,进而会在其周围生成较多的样本.

    from imblearn.over_sampling import ADASYN
    X_resampled, y_resampled = ADASYN(random_state=0).fit_resample(X, y)
    Counter(y_resampled)
    # Counter({2: 4477, 1: 4477, 0: 4477})

欠采样

Prototype generation

ClusterCentroids 使用 K-means 来减少样本数量. 因此,每个类将用 K-means 方法的质心而不是原始样本合成.

from imblearn.under_sampling import ClusterCentroids
X_resampled, y_resampled = ClusterCentroids(random_state=0).fit_resample(X, y)
Counter(y_resampled)
# Counter({0: 64, 1: 64, 2: 64})

随机欠采样

from imblearn.under_sampling import RandomUnderSampler
X_resampled, y_resampled = RandomUnderSampler(random_state=0).fit_resample(X, y)
Counter(y_resampled)
# Counter({0: 64, 1: 64, 2: 64})

组合采样

SMOTE 可能会产生造成样本, 在组合采样中可通过清除过度采样产生的空间来解决.组合采样即为 SMOTE+数据清洗方法

SMOTEENN 倾向于清除比 SMOTETomek 更多的噪声样本.

数据清洗技术最大的缺点: 无法控制欠采样的数量.

  • 由于都在某种程度上采用 K 近邻法,而事实上大部分多数类样本周围也都是多数类,因而能剔除的多数类样本比较有限

SMOTETomek

Tomek Link: Tomek Link表示不同类别之间距离最近的一对样本,即这两个样本互为最近邻且分属不同类别.这样如果两个样本形成了一个Tomek Link,则要么其中一个是噪音,要么两个样本都在边界附近.这样通过移除Tomek Link就能"清洗掉"类间重叠样本,使得互为最近邻的样本皆属于同一类别,从而能更好地进行分类.

下图来自于机器学习之类别不平衡问题 (3) —— 采样方法, 左上为原始数据,右上为SMOTE后的数据,左下虚线标识出Tomek Link,右下为移除Tomek Link后的数据集,可以看到不同类别之间样本重叠减少了很多.

from imblearn.combine import SMOTETomek
X_resampled, y_resampled = SMOTETomek(random_state=0).fit_resample(X, y)
Counter(y_resampled)
# Counter({1: 4396, 0: 4324, 2: 4283})

SMOTEENN

Edited Nearest Neighbours(ENN): 对于属于多数类的一个样本,如果其 K 个近邻点有超过一半都不属于多数类,则这个样本会被剔除.这个方法的另一个变种是所有的 K 个近邻点都不属于多数类,则这个样本会被剔除.

from imblearn.combine import SMOTEENN
X_resampled, y_resampled = SMOTEENN(random_state=0).fit_resample(X, y)
Counter(y_resampled)
# Counter({1: 4217, 0: 3895, 2: 3529})

代价敏感

代价敏感学习是在原始标准代价损失函数的基础上,增加了一些约束和权重条件,使得最终代价的数值计算朝向一个特定的方向偏置(bias),而这个偏置就是具体业务场景更关注的部分.

其具体实现即针对 loss 的两种分类错误赋予不同的权重从而"拉伸"损失函数的函数形式,进而影响模型的最优决策面.对 accrecall 的不同权重因子,最终影响了 roc 曲线中向 accrecall 方向的偏离程度.

\[ Loss = Loss(FP)+ Loss(FN)\rightarrow Loss = Loss(FP)\ast C1 + Loss(FN)\ast C2 \]

实现方法:

  1. Train set sample rescaling: 针对训练集样本利用权重进行配比
  2. Class membership probability: 针对损失函数利用权重进行加权

参考资料


【风控模型】特征工程之类别不平衡问题
https://www.windism.cn/1015665139.html
作者
windism
发布于
2021年3月20日
许可协议