不平衡样本处理策略

本文详细介绍了处理不平衡样本的策略,包括前期准备、过采样(如SMOTE、Borderline-SMOTE)、欠采样(如Tomek's Links、NearMiss)和综合采样方法(如SMOTETomek)。过采样中的Borderline-SMOTE可减少噪声,欠采样中的NearMiss-3较不受噪声影响。同时,文章探讨了EasyEnsemble和BalanceCascade两种样本的集成学习方法,用于实现数据平衡。
摘要由CSDN通过智能技术生成

不平衡样本处理策略

前期准备工作

不平衡数据的生成

采用sklearn.datasets的make_classification来生成试验的不平衡数据集。

from sklearn.datasets import make_classification
from collections import Counter

'''
make_classification的参数说明:
n_samples=5000:生成5000个样本
n_features=2:特征数为2
n_informative=2:有用特征数为2
n_redundant=0:冗余特征数为0,冗余特征是有用特征的随机线性组合
n_repeated=0:重复特征数为0,重复特征是有用特征和冗余特征的随机线性组合
n_classes=3:样本类别数为3
n_clusters_per_class=1:每个类别只有1个簇类
weights=[0.01, 0.05, 0.94]:第0,1,2类样本数量比例采用0.01:0.05:0.94,默认为平衡
class_sep=1.5:控制簇类之间距离的参数因子为1.5,越大簇类之间离得越远
random_state=34:随机种子设为34
'''
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=1.5,
                           random_state=34)

# Counter统计各类别样本出现的次数
Counter(y)

结果

Counter({
   0: 65, 2: 4668, 1: 267})

make_classification生成的数据各类别的数量比例接近0.01 : 0.05 : 0.94。

也可以用计数图来可视化展示。

import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline

# 画出y的计数图
sns.countplot(y)

在这里插入图片描述

logistic回归结果可视化

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.linear_model import LogisticRegression

# 把坐标图网格划分
h = .02  # 设置网状间隔为0.2
# 规定数据X两个特征方向的最大最小值
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
# 用meshgrid产生网格数据
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
                     np.arange(y_min, y_max, h))

# ravel()能将多维数组转换为一维数组,它跟flatten()的区别在于:
# ravel()返回的是原数据,flatten()返回的是原数据的拷贝
# np.c_的作用是按列拼接xx.ravel()和yy.ravel()
data_mesh = np.c_[xx.ravel(), yy.ravel()]

# 用逻辑回归做多分类,并画出结果,写成函数方便后续调用
def lr_result_plot(X, y):
    # 调用LogisticRegression函数,规定相应的参数
    lr = LogisticRegression(solver='sag',
                             max_iter=100,
                             random_state=19,
                             multi_class='multinomial').fit(X, y)
    
    # 输出训练的评价指标结果
    print("training score : %.3f ('multinomial')" % lr.score(X, y))
    
    # 将网格数据输入逻辑回归做预测
    Z = lr.predict(data_mesh)
    # 预测结果变换成与网格数据同样的维度
    Z = Z.reshape(xx.shape)
    
    plt.figure()
    # contour和contourf都可以画三维等高线图
    # 不同点在于contour()是绘制轮廓线,contourf()会填充轮廓
    plt.contourf(xx, yy, Z, cmap=plt.cm.Set2)
    plt.title("Decision surface of LogisticRegression ('multinomial')")
    plt.axis('tight')
    
    # 画样本的散点图,用不同颜色区分不同类的样本
    colors = "rby"
    for i,color in zip(lr.classes_, colors):
        # 查找类别i的所有样本的所在行数
        idx = np.where(y == i)
        # 画出样本的坐标图
        plt.scatter(X[idx, 0], X[idx, 1], c=color, cmap=plt.cm.hot,
                    edgecolor='black', s=20)
        
lr_result_plot(X, y)

分类结果如下图

在这里插入图片描述

红蓝黄3种颜色代表不同类别的样本,不同颜色的背景表示Logistic回归的分类结果。

后面只介绍不平衡数据处理方法中的数据处理方法。

在这里插入图片描述

过采样

简单过采样方法

在这里插入图片描述
简单过采样,即从少数类的样本中随机采样来增加新的样本,api使用RandomOverSampler。

from imblearn.over_sampling import RandomOverSampler

ros = RandomOverSampler(random_state=0)
X_over_resampled, y_over_resampled = ros.fit_sample(X, y)

Counter(y_over_resampled)

结果如下

Counter({
   0: 4668, 2: 4668, 1: 4668})

简单过采样出来的结果,各类别的数量占比是1:1:1。

# 画出逻辑回归结果
lr_result_plot(X_over_resampled, y_over_resampled)

在这里插入图片描述
可以看到Logistic分类平面明显向类3样本(黄色)方向推进了。

因为简单过采样是重复采样,出来的样本在图中都是重叠的,所以少数类看起来数量没有变化,其实3类数据是一样多的。

简单过采样方法容易导致过拟合(因为少数类样本重复了很多次,训练时相当于重复学习了很多次那一小撮少数类样本的特征),为避免简单重复过采样,于是有了SMOTE算法。

SMOTE

SMOTE(Synthetic Minority Oversampling Tenchnique)是一种不重复的过采样算法,它的算法步骤如下:

  1. 算法只接收少数类样本;

    在这里插入图片描述

  2. 每个少数类样本搜索K个最近的样本;

    在这里插入图片描述

  3. 根据所需要的采样倍数,从K个最近邻中随机抽取M个样本;

    在这里插入图片描述

  4. 合成的样本随机地生成在少数类样本与其M个近邻点之间的连线上。

    在这里插入图片描述
    api采用imblearn.over_sampling的SMOTE,具体使用如下:

from imblearn.over_sampling import SMOTE

smt = SMOTE()
X_smote, y_smote = smt.fit_sample(X,y)

Counter(y_smote)

结果

Counter({
   0: 4668, 2: 4668, 1: 4668})

SMOTE算法生成的数据是平衡的。

# 画出逻辑回归结果
lr_result_plot(X_smote, y_smote)

在这里插入图片描述
因为SMOTE不是简单重复采样,所以从图可以很明显看出,类0样本(红色)和类1样本(蓝色)的数量有所增多。但是,图中比之前出现了更多的噪声(合成的样本跑到其他类别堆里),这是因为如果存在异常点,异常点与其近邻合成的样本很可能会变成噪声。

在这里插入图片描述
这是SMOTE算法非常致命的缺点,它加大了后续模型对样本的分类难度。

SMOTE算法的另一个问题是,远离两类数据边界的点合成的样本对模型分类几乎没有贡献,这是因为很多分类模型(如SVM、决策树等)都依赖于边界附近的样本做判断。

在这里插入图片描述

Borderline-SMOTE

为克服SMOTE算法的缺点,于是有论文提出了一种改进算法Borderline-SMOTE。

Borderline-SMOTE的思路是每个少数类样本搜索 m \text{m} m个最近邻,依据K个最近邻中多数类样本的个数 m ′ \text{m}'

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值