Python借助smote实现不均衡样本数据的上采样和下采样,并可视化展示样本分布

    smote是一个很有用的用于样本生成的方法,在Python中已经有了现成的实现可以直接调用,对于安装可以直接使用命令:

pip install imblearn

    由于imblearn包比较大40多MB,需要耐心等一会才可以,安装成功就可以使用了

    今天主要是借助于样本生成的方法,来对原始不均衡样本数据集的扩充,使得其“尽力平衡”

    下面是简单的实验:

def create_dataset(n_samples=1000, weights=(0.01, 0.01, 0.98), n_classes=3,class_sep=0.8, n_clusters=1):
    '''
    创建虚拟数据集
    '''
    return make_classification(n_samples=n_samples, n_features=2,n_informative=2, n_redundant=0, n_repeated=0,
                               n_classes=n_classes,n_clusters_per_class=n_clusters,weights=list(weights),class_sep=class_sep, random_state=0)




def dataset_show(savepath='dataset_show.png'):
    '''
    数据及样本可视化
    原始样本数据经过采样后会形成将近1:1的数据集
    '''
    X, y=create_dataset(n_samples=3000, weights=(0.6, 0.4),n_classes=2)
    print('Original dataset shape {}'.format(Counter(y)))
    startnum=221
    pca=PCA(n_components=2)
    #将数据矩阵转化为二维矩阵
    X_vis=pca.fit_transform(X)
    #应用SMOTE
    sm=SMOTE()
    X_resampled, y_resampled_SMOTE=sm.fit_sample(X, y)
    print('SMOTE dataset shape {}'.format(Counter(y_resampled_SMOTE)))
    X_res_vis_SMOTE=pca.transform(X_resampled)
    #应用SMOTE + ENN
    sm=SMOTEENN()
    X_resampled, y_resampled_SMOTEENN=sm.fit_sample(X, y)
    print('SMOTEENN dataset shape {}'.format(Counter(y_resampled_SMOTEENN)))
    X_res_vis_SMOTEENN=pca.transform(X_resampled)
    #应用SMOTE + Tomek
    smt=SMOTETomek()
    X_resampled, y_resampled_SMOTETomek=smt.fit_sample(X, y)
    print('SMOTETomek dataset shape {}'.format(Counter(y_resampled_SMOTETomek)))
    X_res_vis_SMOTETomek=pca.transform(X_resampled)
    plot_data_list=[[X_vis,y],[X_res_vis_SMOTE,y_resampled_SMOTE],[X_res_vis_SMOTEENN,y_resampled_SMOTEENN],[X_res_vis_SMOTETomek,y_resampled_SMOTETomek]]
    plot_subplot(plot_data_list,savepath=savepath)

   我们使用sklearn库提供的make_classification方法来随机生成符合要求的样本数据集,dataset_show主要实现对数据集的可视化展示,由于我们的样本数据都是多维的,为了展示方便,这里我们都是使用PCA方法将其降到2维来处理,我们分别对比了三种不同的采样方法得到的样本数据分布和原始的样本数据分布情况,结果如下:

   实验一:两类样本数据,比例为:3:2

    数据统计结果为:

    

Original dataset shape Counter({0: 1792, 1: 1208})
SMOTE dataset shape Counter({0: 1792, 1: 1792})
SMOTEENN dataset shape Counter({1: 1528, 0: 1431})
SMOTETomek dataset shape Counter({0: 1719, 1: 1719})

    数据集可视化展示为:


    

    实验二:两类样本数据,数据比例为:9:1

    数据统计结果为:

    

Original dataset shape Counter({0: 2686, 1: 314})
SMOTE dataset shape Counter({0: 2686, 1: 2686})
SMOTEENN dataset shape Counter({1: 2380, 0: 2232})
SMOTETomek dataset shape Counter({0: 2584, 1: 2584})

    数据集可视化展示为:

    

    从上面可以简单发现:

    当数据比例不是很不平衡的时候,在使用采样方法得到的数据集分布以及样本局部密度不会改变很大

    当数据样本比例失衡加大的时候,在使用采样方法会明显的改变样本的局部分布密度,在整体分布轮廓上会很接近原始数据集

SMOTE算法是一种用于解决数据不平衡问题的算法,它通过对少数类样本进行合成来增加数据集的平衡性。下面是SMOTE算法的Python实现: ```python import numpy as np from sklearn.neighbors import NearestNeighbors def SMOTE(T, N, k): """ T: 少数类样本集 N: 需要生成的新样本数目 k: 选取的最近邻个数 """ n_samples, n_features = T.shape if N < 100: print("Error: N must be larger than 100!") return None if (N % 100) != 0: print("Error: N must be a multiple of 100!") return None N = N // 100 # Step 1: 对少数类样本集进行k近邻搜索 neigh = NearestNeighbors(n_neighbors=k) neigh.fit(T) # Step 2: 对每个少数类样本进行N/k次合成 new_index = [] for i in range(n_samples): nn_array = neigh.kneighbors(T[i].reshape(1, -1), return_distance=False)[0] for j in range(N // k): nn = np.random.choice(nn_array) diff = T[nn] - T[i] gap = np.random.rand() new_sample = T[i] + gap * diff new_index.append(new_sample) new_samples = np.array(new_index) return new_samples ``` 使用示例: ```python from collections import Counter from sklearn.datasets import make_classification from matplotlib import pyplot as plt # 生成样本数据 X, y = make_classification(n_classes=3, class_sep=2, weights=[0.05, 0.25, 0.7], 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:", Counter(y)) # 进行SMOTE采样 X_smote = SMOTE(X[y == 1], N=500, k=5) X_resampled = np.vstack((X[y == 0], X[y == 1], X_smote, X[y == 2])) y_resampled = np.hstack((y[y == 0], y[y == 1], np.ones(500, dtype=int) * 1, y[y == 2])) # 查看过采样后的样本分布 print("Resampled dataset shape:", Counter(y_resampled)) # 可视化样本分布 plt.figure(figsize=(10, 8)) plt.scatter(X_resampled[:, 0], X_resampled[:, 1], c=y_resampled) plt.show() ``` 在上面的示例中,我们生成了一个三分类不平衡的样本数据集,然后使用SMOTE算法进行过采样,并可视化样本分布
评论 37
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Together_CZ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值