过采样和欠采样(数据不均衡处理)

使用过采样和欠采样的原因

大模型的默认的阈值是输出值的中位数, 比如限制取值范围为[-1,1]的时候,如果大于0的时候就会划分为正例。过采样和欠采样等采样方法主要解决的是原数据类别不均衡从而影响模型正常输出。如果数据类别不平衡的时候,如果采用默认的分类阈值,可能会导致输出全部都为某一类别,产生虚假的高准确度,降低分类的实际的作用。
一般的处理操作都为将数据调整至最低的类别的一半,致使为数据比例呈现3:7亦或是1:1的比例。这样会使模型达到更好的效果。
过采样(over sampling)和欠采样(under sampling)的目的是调整数据的不均衡。但可能改变原始数据的分布。

常见过采样方法

SMOTE方法

相对随机采样的方法,使用Synthetic Minority Overingsampling Technique(SMOTE)。
SMOTE算法原理为对于少数样本a,随机选取一个最近邻的样本b,然后从a,b之间连线随机选取一个点c作为新的少数类样本。
具体的步骤如下所示。

  • 运用欧氏距离计算距离少量样本点a的所有少量样本的数据的距离,获得k近邻(k个距离样本点最近的数据)。
  • 根据样本不平衡的比例设置一个采样比例确定计算采样倍率N,对于每个少量类样本x,从k近邻中随机选取若干样本,结社获取的样本为x,获取的最近邻为 x n x_{n} xn n ∈ [ 1 , K ] n \in[1, K] n[1,K]),
  • 对于每个随机选取的近邻 x n x_{n} xn,按照下列公式构建新的样本。

x new  = x + rand ⁡ ( 0 , 1 ) ∗ ∣ x − x n ∣ \mathrm{x}_{\text {new }}=\mathrm{x}+\operatorname{rand}(0,1) *|\mathrm{x}-\mathrm{x_{n}}| xnew =x+rand(0,1)xxn

具体实现代码

from imblearn.over_sampling import SMOTE, ADASYN
from sklearn.datasets import make_classification
from collections import Counter
# 创建一个三个类别,聚类的样本数量为5000,X的数据有2列,而且类别的数据比例为0.1,0.05,0.95
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)
# 过采样生成的样本,生成的比例为具体为如下
X_resampled_smote, y_resampled_smote = SMOTE().fit_resample(X, y)

print(sorted(Counter(y_resampled_smote).items()))
# [(0, 4674), (1, 4674), (2, 4674)]

ADASYN方法

Adaptive Synthetic(ADASYN)算法关注的是基于K-means的分类器被错误分类的原始样本附近,生成的新的少量数量样本。

ADASYN例子(二分类问题为例子)

  1. 训练数据为Data有m个样本 { x i , y i } , i = 1 … , m \{x_{i}, y_{i}\},i=1\dots,m { xi,yi}i=1,m ,而且 y i ∈ Y = { 0 , 1 } y_i \in Y=\{0,1\} yiY={ 0,1} m s m_{s} ms为少类别样本点数量, m l m_{l} ml为多类别样本点数量。
  2. 计算类别的不平衡度
    d = m s / m l d=m_s / m_l d=ms/ml
  3. 若d小于预设的最大类别不平衡度 d t h d_{th} dth,则进行下列操作。
  1. 计算需要合成的少量数据样本的数量G。
    G = ( m l − m s ) × β G=\left(m_l-m_s\right) \times \beta G=(mlms)×β
    β \beta β为需要控制的期望平衡水平,若 β \beta β等于1则创建一个完全平衡的数据集合。)
  2. 随后计算比率 r r r,且 r i r_i ri求和为 r r r,具体为 Δ i \Delta_i Δi x i x_{i} xi(为少类样本)的K个最近邻(Euclidiaean distance)中属于多类样本的数量。公式如下。
    r i = Δ i / K , i = 1 , … , m s r_i=\Delta_i / K, \quad i=1, \ldots, m_s ri=Δi/K,i=1,,ms
  3. 将r进行归一化处理。公式如下
    r i ^ = r i / ∑ i = 1 m s r i \hat{r_i}=r_i / \sum_{i=1}^{m_s} r_i ri^=ri/i=1msri
  4. 计算对于 x i x_i xi所需要生成的样本数量。
    g i = r i ^ × G g_i=\hat{r_i} \times G gi=ri^×G
  5. 循环下列操作。从 x i x_i xi的k个最近邻中随机选取一个少量样本 x z i x_{zi} xzi,合成样本数据。
    s i = x i + ( x z i − x i ) × λ s_i = x_i + (x_{zi} - x_i) \times \lambda si=xi+(xzixi)×λ,而且 λ \lambda λ为[0,1]的随机数。

具体代码实现

from imblearn.over_sampling import SMOTE, ADASYN
from sklearn.datasets import make_classification
from collections import Counter
# 创建一个三个类别,聚类的样本数量为5000,X的数据有2列,而且类别的数据比例为0.1,0.05,0.95
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)
X_resampled_adasyn, y_resampled_adasyn = ADASYN().fit_sample(X, y)
print(sorted(Counter(y_resampled_adasyn).items()))

欠采样

给定的数据集S,原型选择算法是属于欠采样的一种方法。而且圆形选择是直接从原始数据集中进行抽取,抽取的方法大概可以分为两类。下列因为时间有限,只介绍controlled under-sampling technique

  • controlled under-sampling technique
  • cleaning under-sampling technique

RandomUnderSampler

下列介绍一个RandomUnderSampler是一种快速而且简单的方式用于平衡各个类别的数据。具体操作为删除随机删除多样本数据。使得少样本数据和多样本数据比例基本持平或者达到一定比例。
具体代码如下所示。默认采取的是不重复采样方式。

from imblearn.over_sampling import 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)
cc = ClusterCentroids(random_state=0)
X_resampled, y_resampled = cc.fit_resample(X, y)
print(sorted(Counter(y_resampled).items()))
# [(0, 64), (1, 64), (2, 64)]

NearMiss

NearMiss undersampling是一种基于近邻的欠采样技术,其目标是通过删除多数类别样本来平衡数据集。该方法的基本原理是根据近邻关系选择少数类别样本,目的是保留那些被多数类别样本紧密包围的少数类别样本。代码实现如下所示。

from imblearn.over_sampling import SMOTE, ADASYN
from sklearn.datasets import make_classification
from collections import Counter
from imblearn.under_sampling import NearMiss
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)
nm1 = NearMiss(version=3) # 这里的version的可选为1,2,3,代表下列三种不同方式。
X_resampled_nm1, y_resampled = nm1.fit_resample(X, y)
print(sorted(Counter(y_resampled).items()))
# [(0, 64), (1, 64), (2, 64)]
  • version=1 : 选择离N个近邻的负样本的平均距离最小的正样本;
  • version=2: 选择离N个负样本最远的平均距离最小的正样本;
  • version=3: 是一个两段式的算法. 首先, 对于每一个负样本, 保留它们的M个近邻样本; 接着, 那些到N个近邻样本平均距离最大的正样本将被选择.

参考

欠采样(undersampling)和过采样(oversampling)会对模型带来怎样的影响?
Python sklearn 实现过采样和欠采样
SMOTE算法(人工合成数据)
ADASYN: Adaptive Synthetic–不平衡数据采样方法

猜你喜欢

转载自blog.csdn.net/xiaziqiqi/article/details/132271091
今日推荐