📜  重采样方法介绍

📅  最后修改于: 2022-05-13 01:58:07.591000             🧑  作者: Mango

重采样方法介绍

在阅读机器学习和数据科学时,我们经常遇到一个术语,称为不平衡类分布,通常发生在其中一个类中的观察值远高于或低于任何其他类时。
由于机器学习算法倾向于通过减少错误来提高准确性,因此它们不考虑类分布。这个问题在欺诈检测、异常检测、面部识别等示例中很普遍。

两种常见的重采样方法是 -

  1. 交叉验证
  2. 引导

交叉验证——

交叉验证用于估计与模型相关的测试误差以评估其性能。

验证集方法:
这是最基本的方法。它只是将数据集随机分为两部分:首先是训练集,其次是验证集或保留集。该模型拟合训练集,拟合模型用于对验证集进行预测。
验证集方法

留一法交叉验证:
LOOCV 是比验证集方法更好的选择。不是将整个数据集分成两半,只使用一个观察值进行验证,其余的用于拟合模型。
LOOCV



k折交叉验证——
这种方法涉及将观察集随机分成大小几乎相等的 k 折。第一个折叠被视为验证集,模型适合剩余的折叠。然后将该过程重复 k 次,其中每次将不同的组视为验证集。
K折

引导——

Bootstrap 是一种强大的统计工具,用于量化给定模型的不确定性。然而,bootstrap 的真正力量在于它可以应用于各种模型,在这些模型中,难以获得或不能自动输出可变性。

挑战:
当处理不平衡的数据集时,机器学习中的算法往往会产生不令人满意的分类器。
例如,电影评论数据集

Total Observations : 100
Positive Dataset : 90
Negative Dataset : 10
Event rate : 2%

这里的主要问题是如何获得平衡的数据集。

标准机器学习算法的挑战:
决策树和逻辑回归等标准 ML 技术偏向于多数类,并且倾向于忽略少数类。他们倾向于只预测多数类,因此,与多数类相比,少数类存在重大错误分类。

分类算法的评价是通过混淆矩阵来衡量的。
混淆矩阵

评估结果的一种方法是通过混淆矩阵,它显示每个类的正确和错误预测。在第一行中,第一列表示有多少类“真”被正确预测,第二列表示有多少类“真”被预测为“假”。在第二行,我们注意到所有“False”类条目都被预测为“True”类。
因此,混淆矩阵的对角线值越高,正确预测就越好。

处理方法:



  • 随机过采样:
    它旨在通过复制它们随机增加少数类示例来平衡类分布。

    例如 -

    Total Observations : 100
    Positive Dataset : 90
    Negative Dataset : 10
    Event Rate : 2%

    我们复制负数据集 15 次

    Positive Datset: 90
    Negative Datset after Replicating: 150
    Total Observations: 190
    Event Rate : 150/240= 63%

    SMOTE(Synthetic Minority Oversampling Technique)在现有少数实例之间合成新的少数实例。它随机选取少数类并计算该特定点的 K 最近邻。最后,将合成点添加到相邻点和所选点之间。

  • 随机欠采样:
    它旨在通过随机消除多数类示例来平衡类分布。

    例如 -

    Total Observations : 100
    Positive Dataset : 90
    Negative Dataset : 10
    Event rate : 2%
    
    We take 10% samples of Positive Dataset and combine it with Negative Dataset.
    
    Positive Dataset after Random Under-Sampling : 10% of 90 = 9 
    
    Total observation after combining it with Negative Dataset: 10+9=19
    
    Event Rate after Under-Sampling : 10/19 = 53%

    当两个不同类的实例彼此非常接近时,我们删除多数类的实例以增加两个类之间的空间。这有助于分类过程。

  • 基于集群的过采样:
    K 表示聚类算法独立应用于两个类实例,例如识别数据集中的聚类。所有集群都被过采样,使得同一类的集群具有相同的大小。

    例如 -

    Total Observations : 100
    Positive Dataset : 90
    Negative Dataset : 10
    Event Rate : 2%

    多数类集群:
    集群 1:20 次观察
    集群 2:30 次观察
    集群 3:12 次观察
    集群 4:18 次观察
    第 5 组:10 次观察

    少数族群:
    集群 1:8 次观察
    集群 2:12 次观察

    过采样后,同一类的所有集群都有相同数量的观察。



    多数类集群:
    集群 1:20 次观察
    集群 2:20 次观察
    第 3 组:20 次观察
    集群 4:20 次观察
    第 5 组:20 次观察

    少数族群:
    集群 1:15 次观察
    集群 2:15 次观察

    下面是一些重采样技术的实现:

    您可以从下面给定的链接下载数据集:数据集下载

    # importing libraries
    import pandas as pd
    import numpy as np
    import seaborn as sns
    from sklearn.preprocessing import StandardScaler
    from imblearn.under_sampling import RandomUnderSampler, TomekLinks
    from imblearn.over_sampling import RandomOverSampler, SMOTE
    
    dataset = pd.read_csv(r'C:\Users\Abhishek\Desktop\creditcard.csv')
       
       
       
    print("The Number of Samples in the dataset: ", len(dataset))
    print('Class 0        :', round(dataset['Class'].value_counts()[0]
                          /len(dataset) * 100, 2), '% of the dataset')
       
    print('Class 1(Fraud) :', round(dataset['Class'].value_counts()[1]
                          /len(dataset) * 100, 2), '% of the dataset')
    

    X_data = dataset.iloc[:, :-1]
    Y_data = dataset.iloc[:, -1:]
       
    rus = RandomUnderSampler(random_state = 42)
    X_res, y_res = rus.fit_resample(X_data, Y_data)
       
    X_res = pd.DataFrame(X_res)
    Y_res = pd.DataFrame(y_res)
       
       
    print("After Under Sampling Of Major Class Total Samples are :", len(Y_res))
    print('Class 0        :', round(Y_res[0].value_counts()[0]
                    /len(Y_res) * 100, 2), '% of the dataset')
       
    print('Class 1(Fraud) :', round(Y_res[0].value_counts()[1]
                    /len(Y_res) * 100, 2), '% of the dataset')
    

    tl = TomekLinks()
       
    X_res, y_res = tl.fit_resample(X_data, Y_data)
       
    X_res = pd.DataFrame(X_res)
    Y_res = pd.DataFrame(y_res)
       
       
    print("After TomekLinks Under Sampling Of Major Class Total Samples are :", len(Y_res))
    print('Class 0        :', round(Y_res[0].value_counts()[0]
                    /len(Y_res) * 100, 2), '% of the dataset')
       
    print('Class 1(Fraud) :', round(Y_res[0].value_counts()[1]
                    /len(Y_res) * 100, 2), '% of the dataset')
    

    ros = RandomOverSampler(random_state = 42)
      
    X_res, y_res = ros.fit_resample(X_data, Y_data)
       
    X_res = pd.DataFrame(X_res)
    Y_res = pd.DataFrame(y_res)
       
       
    print("After Over Sampling Of Minor Class Total Samples are :", len(Y_res))
    print('Class 0        :', round(Y_res[0].value_counts()[0]
                    /len(Y_res) * 100, 2), '% of the dataset')
       
    print('Class 1(Fraud) :', round(Y_res[0].value_counts()[1]
                    /len(Y_res) * 100, 2), '% of the dataset')
    

    sm = SMOTE(random_state = 42)
       
    X_res, y_res = sm.fit_resample(X_data, Y_data)
       
    X_res = pd.DataFrame(X_res)
    Y_res = pd.DataFrame(y_res)
       
       
    print("After SMOTE Over Sampling Of Minor Class Total Samples are :", len(Y_res))
    print('Class 0        :', round(Y_res[0].value_counts()[0]
                     /len(Y_res) * 100, 2), '% of the dataset')
       
    print('Class 1(Fraud) :', round(Y_res[0].value_counts()[1]
                     /len(Y_res) * 100, 2), '% of the dataset')