【风控模型】特征工程之类别不平衡问题
在风控场景中, 由于正样本获取的成本较高, 往往样本比例是失衡的, 样本的不平衡很容易导致模型偏向比例较高的一方
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}\) 相连的直线上:

缺陷:
- 如果选取的少数类样本周围也都是少数类样本,则新合成的样本不会提供太多有用信息.
- 如果选取的少数类样本周围全是多数类样本,这类的样本可能是噪音,则新合成的样本会与周围的多数类样本产生大部分重叠,致使分类困难.
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那样对每个少数类样本合成同数量的样本.
首先计算需要合成的样本总量:
\[ G = (S_{maj} - s_{min}) \times \beta \]
其中:
- \(S_{maj}\): 多数类样本数量
- \(s_{min}\): 少数类样本数量
- \(\beta\): 系数
- \(G\): 总共想要合成的少数类样本数量
如果 \(\beta = 1\) 则是合成后各类别数目相等.
对于每个少类别样本\(x_i\),找出其
K
近邻个点\[ \Gamma_i = \frac{\Delta_i / K}{Z} \]
其中:
- \(\Delta_i\):
K
近邻个点中多数类样本的数量 - \(Z\): 规范化因子以确保 \(\Delta_i\) 构成一个分布.
若一个少数类样本 \(x_i\) 的周围多数类样本越多,则其 \(\Gamma_i\) 也就越高.
- \(\Delta_i\):
最后对每个少类别样本 \(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
的两种分类错误赋予不同的权重从而"拉伸"损失函数的函数形式,进而影响模型的最优决策面.对
acc
和 recall
的不同权重因子,最终影响了
roc
曲线中向 acc
和 recall
方向的偏离程度.
\[ Loss = Loss(FP)+ Loss(FN)\rightarrow Loss = Loss(FP)\ast C1 + Loss(FN)\ast C2 \]
实现方法:
Train set sample rescaling
: 针对训练集样本利用权重进行配比Class membership probability
: 针对损失函数利用权重进行加权