有关不平衡学习与SMOTE算法
Posted Jullii
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了有关不平衡学习与SMOTE算法相关的知识,希望对你有一定的参考价值。
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
因为最近的任务中运用到了Smote算法,但是我找了网上好多帖子都没有解决问题,因此去阅读了imblearn库的User guide。然后在这边写下所得到的知识以及掌握了的算法,可以供大家学习与参考。还有感觉在网上查到的帖子很多SMOTE算法都只是用于二分类任务的,但是尝试之后发现是可以用于多分类任务的,但是所带的特征要对应。
一、有关上采样和Smote算法?
**
1、上采样
**
按照我的理解来讲就是,因为在我的不平衡数据集中,有一类样本比较少,有一类样本多,就想办法把少类的样本增多就可。最简单的做法就是通过随机抽样和替换当前可用样本来生成新样本。
from sklearn.datasets import make_classification
from collections import Counter
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.05, 0.94],
class_sep=0.8, random_state=0)
from imblearn.over_sampling import RandomOverSampler
ros = RandomOverSampler(random_state=0)
print("采样之前的样本个数为:")
print(sorted(Counter(y).items()))
X_resampled, y_resampled = ros.fit_resample(X, y)
print("采样之后的样本个数为:")
print(sorted(Counter(y_resampled).items()))
采样之前的样本个数为:
[(0, 64), (1, 262), (2, 4674)]
采样之后的样本个数为:
[(0, 4674), (1, 4674), (2, 4674)]
这是从官网截取下来的代码,这里可以看到,总共是需要一个X,一个y。这时候我们就会在想X,和y到底是什么。然后我就试着输出了一下。
X就是一个二维列表,应该是样本的特征,而y就是样本具体的值了,这个生成的数据集中共有三类,包括2、1、0。但是可以看出2是多数类,0比较少。而上采样的做法就是生成了很多0类和1类使之与多数的2类样本个数一样。
此外,值得一提的是,在imblearn库所提供的RandomOverSampling也支持对于异构数据进行采样(例如,包含一些字符串)
import numpy as np
X_hetero = np.array([['xxx', 1, 1.0], ['yyy', 2, 2.0], ['zzz', 3, 3.0]],
dtype=object)
y_hetero = np.array([0, 0, 1])
X_resampled, y_resampled = ros.fit_resample(X_hetero, y_hetero)
print(X_resampled)
print(y_resampled)
输出的结果为:
[['xxx' 1 1.0]
['yyy' 2 2.0]
['zzz' 3 3.0]
['zzz' 3 3.0]]
[0 0 1 1]
这给我们的启示就是,在使用RandomOverSampling的时候其实X是不必进行编码的,可以是异构数据。y与之对应的就是我们数据集中类型id,可以依据类型id所做复制。这给我们带来了很大的方便啊啊啊!!因为我之前所输入的X想了好久还进行了编码处理。
2、SMOTE算法
SMOTE算法是现在非常流行的一种上采样的方法。使用RandomOverSampling方法是复制,而SMOTE 和 ADASYN 通过插值生成新样本。因为现在暂时只是在使用SMOTE算法,所以就先不介绍ADASYN算法惹,之后用到再进行补充。下面用的也是生成的数据,然后生成的是三类,控制了样本比例。值得注意的是,如果是多分类任务,想要得到的目标样本数量要使用字典,要不然就会报错。
from sklearn.datasets import make_classification
from collections import Counter
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.05, 0.94],
class_sep=0.8, random_state=0)
print("采样之前的样本数为:")
print(Counter(y))
from imblearn.over_sampling import SMOTE
sampling_strategy=0:3000,1:3000,2:4674
oversampler=SMOTE(sampling_strategy=sampling_strategy,random_state=0,k_neighbors=2,n_jobs=1)
X_resampled, y_resampled = oversampler.fit_resample(X, y)
print("采样后的样本数为:")
print(Counter(y_resampled))
采样之前的样本数为:
Counter(2: 4674, 1: 262, 0: 64)
采样后的样本数为:
Counter(2: 4674, 1: 3000, 0: 3000)
其中 sampling_strategy可以选择以下几种,这是我在其他帖子中看到的:
‘majority’:resample only the majority class; 仅仅重新采样多数类
‘not minority’:resample all classes but the minority class; 重采样所有类别除了少数类
‘not majority’:resample all classes but the majority class; 重采样所有类别除了多数类
‘all’:resample all classes; 重采样所有类别
‘auto’:equivalent to ‘not minority’。 等价于not minority
二、如果是使用真实的数据集(类似文本分类任务?)
我尝试了一下,就是如果是特征值是字符串的话,只有RandomOverSampling可以,SMOTE算法要报错。具体的错误如下。所以我浅浅地认为好像是不行的,但是我如果把SMOTE换成ROS就是可以的。所以我们在处理文本数据的时候应该是要做预处理的。
预处理我用的是from sklearn.preprocessing import LabelEncoder,来进行标签的编码,应该只是很简单的处理。
for col in ["ID"]:
le = LabelEncoder()
le.fit(df[col])
row = le.transform(df[col])
df[col] = row + index
index = max(row) + 1
总结
以上就是今天要讲的内容,本文仅仅简单介绍了RandomOverSampling和SMOTE算法的使用,我也正在探索当中,所以如果哪里有错误,欢迎大家批评指正!!!我们一起交流一起进步!!!之后如果学到更多的,我会继续跟进的!!
参考
https://www.jianshu.com/p/3eac447b7261
以上是关于有关不平衡学习与SMOTE算法的主要内容,如果未能解决你的问题,请参考以下文章