最近在帮师兄处理一个二分类问题,其中的类别不平衡问题很严重.然后不管用什么模型,roc_auc_score得到的结果都不好. 然后网上找资料想办法解决数据倾斜问题.看到了SMOTE过采样算法.
SMOTE过采样算法
JAIR'2002的文章《SMOTE: Synthetic Minority Over-sampling Technique》提出了一种过采样算法SMOTE。概括来说,本算法基于“插值”来为少数类合成新的样本。下面介绍如何合成新的样本。
设训练集的一个少数类的样本数为 TT ,那么SMOTE算法将为这个少数类合成 NTNT 个新样本。这里要求 NN 必须是正整数,如果给定的 N<1N<1 那么算法将“认为”少数类的样本数 T=NTT=NT ,并将强制 N=1N=1 。
考虑该少数类的一个样本 ii ,其特征向量为 xi,i∈{1,...,T}xi,i∈{1,...,T} :
1. 首先从该少数类的全部 TT 个样本中找到样本 xixi 的 kk 个近邻(例如用欧氏距离),记为 xi(near),near∈{1,...,k}xi(near),near∈{1,...,k} ;
2. 然后从这 kk 个近邻中随机选择一个样本 xi(nn)xi(nn) ,再生成一个 00 到 11 之间的随机数 ζ1ζ1 ,从而合成一个新样本 x
xi1 :
xi1=xi+ζ1⋅(xi(nn)−xi)
3. 将步骤2重复进行 NN 次,从而可以合成 NN 个新样本:xinew,new∈1,...,Nxinew,new∈1,...,N。
那么,对全部的 TT 个少数类样本进行上述操作,便可为该少数类合成 NTNT 个新样本。
如果样本的特征维数是 22 维,那么每个样本都可以用二维平面上的一个点来表示。SMOTE算法所合成出的一个新样本 xi1xi1 相当于是表示样本 xixi 的点和表示样本 xi(nn)xi(nn) 的点之间所连线段上的一个点。所以说该算法是基于“插值”来合成新样本
实现代码:
from collections import Counter
from sklearn.datasets import make_classification
from imblearn.over_sampling import SMOTE # doctest: +NORMALIZE_WHITESPACE
X, y = make_classification(n_classes=2, class_sep=2,
weights=[0.1, 0.9], n_informative=3, n_redundant=1, flip_y=0,
n_features=20, n_clusters_per_class=1, n_samples=1000, random_state=10)
print('Original dataset shape %s' % Counter(y))
sm = SMOTE(random_state=42)
X_res, y_res = sm.fit_resample(X, y)
print('Resampled dataset shape %s' % Counter(y_res))
SMOTE过采样算法实现 有一个专门实现的库,imblearn.over_sampling.SMOTE这里合成了若干数量少的类别,最终两种类别的数量是一样的.
输出结果:
Original dataset shape Counter({1: 900, 0: 100})
Resampled dataset shape Counter({0: 900, 1: 900})
参考链接:
https://imbalanced-learn.readthedocs.io/en/stable/generated/imblearn.over_sampling.SMOTE.html
https://www.cnblogs.com/Determined22/p/5772538.html