跳转至

1样本不均衡#

在一般的建模问题中,经常会出现样本不均衡的情况。比如二分类问题顾客是否会消费1, 0. 实际样本中有消费的人:无消费的人,比例可能是1:10 或者1:100

针对样本不均衡类的解决方法主要有以下几种方式:

1. 抽样-过采样/欠采样#

即通过抽样的方式增加正样本的比例or随机删除负样本的比例

简单复制#

操作简单,但是当样本量较少的时候,容易导致过拟合

过采样 smote#

将少数样本做合成,工作方式是选择特征空间中靠近的样本在特征空间中的样本之间画一条线,然后在沿该线的点上绘制新样本。
简单说:差值

https://github.com/scikit-learn-contrib/imbalanced-learn
https://zhuanlan.zhihu.com/p/440648816

smote实现

from imblearn.over_sampling import RandomOverSampler
# 使用RandomOverSampler从少数类的样本中进行随机采样来增加新的样本使各个分类均衡
ros = RandomOverSampler(random_state=0)
X_resampled, y_resampled = ros.fit_sample(X, y)

# SMOTE: 对于少数类样本a, 随机选择一个最近邻的样本b, 然后从a与b的连线上随机选取一个点c作为新的少数类样本
from imblearn.over_sampling import SMOTE
X_resampled_smote, y_resampled_smote = SMOTE().fit_sample(X, y)


# RandomUnderSampler函数是一种快速并十分简单的方式来平衡各个类别的数据: 随机选取数据的子集.
from imblearn.under_sampling import RandomUnderSampler
rus = RandomUnderSampler(random_state=0)
X_resampled, y_resampled = rus.fit_sample(X, y)

2. 模型层面加权#

模型层面,也就是说在训练模型的时候,对损失函数做一定的加权处理。正常情况下,一个二分类问题,采用交叉熵公式:
Loss = -log(p), if y = 1
Loss = -log(1-p), if y = 0

加权#

所以一个直观的方式就是对不同类别加权

Loss = -alog(p), if y = 1
Loss = -(1-a)log(1-p), if y = 0
在算法层面,通过对正负样本设置权重来解决不平衡问题。比如xgboost中的class_weight参数

focal loss#

基于这个问题2017年何恺明大神在论文《Focal Loss for Dense Object Detection》中提出了非常火的Focal Loss。
核心的一点就是:不仅样本的比例会影响训练的损失,样本的难易区分程度也会影响损失函数。比如一个p=0.55的和一个p=0.95的肯定0.95的容易区分,0.55的不易区分。那不易区分的是不是损失可以设置的大一些。

所以有了如下的加权方式:
FL = -a(1-p)^{\eta}log(p) if y = 1; = -(1-a)p^{\eta}log(1-p) if y=0
作者在这里面建议参数\eta=2

GHM loss#

focal loss可能存在一个小问题,对于有离群点的数据可能会偏于离群点,降低了模型的效果

2019年论文《Gradient Harmonized Single-stage Detector》中提出了GHM(gradient harmonizing mechanism) Loss。
GHM Loss认为不仅仅要多关注容易区分的样本,这点和Focal Loss一致,同时还认为需要关注那些十分困难区分的样本,因为这部分样本可能是标注错误的离群点,过多的关注这部分样本不仅不会提升模型的效果,反而还会有一定的逆向效果。

todo https://www.zhihu.com/question/66408862/answer/1953978327#

3. 通过组合/集成的方法#

组合/集成方法指的是在每次生成训练集时使用所有分类中的小样本量,同时从分类中的大样本量中随机抽取数据来与小样本量合并构成训练集,这样反复多次会得到很多训练集和训练模型。最后在应用时,使用组合方法(例如投票、加权投票等)产生分类预测结果。

即在第一种采样的基础上进行集成组合。

2.实践#

xgboost自定义损失函数#

xgboost根据其迭代逻辑,只需传入损失函数的一阶导、二阶导。比如xgboost + focal loss

xgboost 更改损失函数

参考资料#

https://www.zhihu.com/question/66408862/answer/1953978327