zoukankan      html  css  js  c++  java
  • 【火炉炼AI】机器学习015-如何处理样本数偏差较大的数据集

    【火炉炼AI】机器学习015-如何处理样本数偏差较大的数据集

    (本文所使用的Python库和版本号: Python 3.5, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 )

    我们得到的数据集在绝大多数情况下,都不是理想的数据集,都需要经过各种各样的处理,其中的一个处理方式就是,如何处理样本数偏差较大的数据集。比如对于某种疾病的发生概率是1%,即获得的自然状态下的数据集中大约99%的样本都是正常的,那么此时,通过模型进行训练,得到的模型在对新样本进行预测时,也往往偏向于样本数较大的类别,此时或极大的降低小样本类别的召回率。


    1. 查看数据集的特征

    此处所使用的是书本《Python机器学习经典实例》第三章的非平衡数据集,此处我用pandas读取到内存中,通过info()来查看该数据集的基本情况,代码如下:

    # 准备数据集
    data_path='E:PyProjectsDataSetFireAI/data_multivar_imbalance.txt'
    df=pd.read_csv(data_path,header=None)
    # print(df.head()) # 没有问题
    print(df.info()) # 查看数据信息,确保没有错误
    dataset_X,dataset_y=df.iloc[:,:-1],df.iloc[:,-1]
    # print(dataset_X.head())
    # print(dataset_X.info())
    # print(dataset_y.head()) # 检查没问题
    dataset_X=dataset_X.values
    dataset_y=dataset_y.values
    

    -------------------------------------输---------出--------------------------------

    <class 'pandas.core.frame.DataFrame'>
    RangeIndex: 1200 entries, 0 to 1199
    Data columns (total 3 columns):
    0 1200 non-null float64
    1 1200 non-null float64
    2 1200 non-null int64
    dtypes: float64(2), int64(1)
    memory usage: 28.2 KB
    None

    --------------------------------------------完-------------------------------------

    可以看出,该数据集只有两个features,一个label,且整个数据集有1200个样本。可以通过查看数据集的2D分布来初步的了解该数据集的样本偏差。如下图所示:

    本数据集在不同类别上样本数偏差比较大

    ########################小**********结###############################

    1. 数据集中不同类别之间样本数偏差比较大,此时需要做进一步处理。

    2. 数据集的加载和显示等,在前面的文章中已经讲烂了,此处无需赘言。

    #################################################################


    2. 用线性SVM分类器构建分类模型

    从上面的数据集分布图中可以大致看出,这个模型不是简单的线性模型,当然,为了对比效果,此处我仍然使用线性SVM分类器来构建分类模型,看一下效果。

    代码如下:

    # 将整个数据集划分为train set和test set
    from sklearn.model_selection import train_test_split
    train_X, test_X, train_y, test_y=train_test_split(
        dataset_X,dataset_y,test_size=0.25,random_state=42)
    
    # 如果用线性SVM分类器来进行分类,看看是什么结果
    # 使用线性核函数初始化一个SVM对象。
    from sklearn.svm import SVC
    classifier=SVC(kernel='linear') # 构建线性分类器
    classifier.fit(train_X,train_y)
    

    然后在通过plot_classifier()函数将这个模型的分类效果画出来。

    # 模型在训练集上的性能报告:
    from sklearn.metrics import classification_report
    plot_classifier(classifier,train_X,train_y)  # 分类器在训练集上的分类效果
    target_names = ['Class-0', 'Class-1']
    y_pred=classifier.predict(train_X)
    print(classification_report(train_y, y_pred, target_names=target_names))
    

    线性SVM分类器对本数据集的分类效果

    -------------------------------------输---------出--------------------------------

    precision recall f1-score support

    Class-0 0.00 0.00 0.00 151
    Class-1 0.83 1.00 0.91 749

    avg / total 0.69 0.83 0.76 900

    --------------------------------------------完-------------------------------------

    可以看出,线性SVM分类器完全没有将class_0区分出来,得到的各种指标都是0,从分类效果图中也可以看到,根本就没有线性平面。

    ########################小**********结###############################

    1. 由于本数据集存在样本数量偏差,故而使用线性SVM分类器没有任何效果。

    #################################################################


    3. 解决样本数量偏差的方法

    从上面可以看出,由于样本数量偏差的存在,使用线性SVM分类器没有任何效果,那么我们该怎么处理这种数据集了?

    SVM内部存在一个class_weight参数,我们可以设置该参数为"balanced",来调节各种类别样本数量的权重,使其达到平衡。如下代码:

    # 看来直接使用简单的线性SVM分类器难以将class_0区分出来,故而我们要调整数据集中样本的数量权重
    classifier2=SVC(kernel='linear',class_weight='balanced') # 比上面的分类器增加了 class_weight=‘balanced'参数
    classifier2.fit(train_X,train_y)
    
    # 模型在训练集上的性能报告:
    plot_classifier(classifier2,train_X,train_y)  # 分类器在训练集上的分类效果
    target_names = ['Class-0', 'Class-1']
    y_pred2=classifier2.predict(train_X)
    print(classification_report(train_y, y_pred2, target_names=target_names))
    

    设置class_weight参数为balanced后分类效果图

    -------------------------------------输---------出--------------------------------

    precision recall f1-score support

    Class-0 0.35 0.86 0.50 151
    Class-1 0.96 0.68 0.79 749

    avg / total 0.86 0.71 0.74 900

    --------------------------------------------完-------------------------------------

    从分类效果图中可以看出,此时可以使用线性SVM来对数据集进行训练,并能得到效果还不错的分类模型,从分类结果报告中可以看出,各种指标也还不错,但也存在较大的提升空间。

    ########################小**********结###############################

    1. 在定义SVM分类器时,只需要设置class_weight=balanced即可消除数据集中样本数量偏差的问题。

    2. 如果分类器的效果不理想,那么需要考虑是否是数据集存在明显的样本数量偏差问题。

    #################################################################


    注:本部分代码已经全部上传到(我的github)上,欢迎下载。

    参考资料:

    1, Python机器学习经典实例,Prateek Joshi著,陶俊杰,陈小莉译

  • 相关阅读:
    Andrew Ng机器学习公开课笔记–Principal Components Analysis (PCA)
    Python For Data Analysis -- Pandas
    Python For Data Analysis -- NumPy
    Python For Data Analysis -- IPython
    Andrew Ng机器学习公开课笔记 – Factor Analysis
    Andrew Ng机器学习公开课笔记 -- Mixtures of Gaussians and the EM algorithm
    Andrew Ng机器学习公开课笔记 -- Online Learning
    Machine Learning in Action -- Support Vector Machines
    HDU-1090-A+B for Input-Output Practice (II)(骗訪问量的)
    五种内部类形式将线程隐藏于类中
  • 原文地址:https://www.cnblogs.com/RayDean/p/9764820.html
Copyright © 2011-2022 走看看