• Scikit-Learn快速生成分类数据集


    假如你学习了新的分类算法并想进一步探索研究、尝试不同的超参数评估模型性能,但问题是你找不到好的数据集用于实验。幸运的是Scikit-Learn 提供的 make_classification() 方法可以创建不同类型的数据集,它可以生成不同类型的数据集:二分类、多分类、平衡或不平衡数据集、难以分类的数据集等。本文通过示例详细说明,并结合随机森林分类算法进行验证。

    make_classification函数

    首先我们介绍该函数参数,以及常用参数及默认值:

    • n_samples: 生成多少条样本数据,缺省100条.
    • n_features: 有几个数值类型特征,缺省为20.
    • n_informative: 有用特征的个数,仅这些特征承载对分类信号.,缺省为2.
    • n_classes: 分类标签的数量,缺省为2.

    该函数返回包含函数Numpy 数组的tuple,分别为特征X,以及标签y。其他参数用到时再作说明。

    生成二分类数据集

    下面生成二分类数据集,即标签仅有两个可能的值:0 、1.

    因此需要设置n_classes参数为2。我们需要生成1000条样本,包括5个特征,其中三个为有用特征,另外两个为冗余特征。

    from sklearn.datasets import make_classification
    
    X, y = make_classification(
        n_samples=1000, # 1000 observations 
        n_features=5, # 5 total features
        n_informative=3, # 3 'useful' features
        n_classes=2, # binary target/label 
        random_state=999 # if you want the same results as mine
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    下面需转换 make_classification 函数返回值为 padas 数据框。padas 数据框比Numpy数组更易分析。

    import pandas as pd
    
    # Create DataFrame with features as columns
    dataset = pd.DataFrame(X)
    # give custom names to the features
    dataset.columns = ['X1', 'X2', 'X3', 'X4', 'X5']
    # Now add the label as a column
    dataset['y'] = y
    
    dataset.info()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    输出结果:

    
    RangeIndex: 1000 entries, 0 to 999
    Data columns (total 6 columns):
     #   Column  Non-Null Count  Dtype  
    ---  ------  --------------  -----  
     0   X1      1000 non-null   float64
     1   X2      1000 non-null   float64
     2   X3      1000 non-null   float64
     3   X4      1000 non-null   float64
     4   X5      1000 non-null   float64
     5   y       1000 non-null   int64  
    dtypes: float64(5), int64(1)
    memory usage: 47.0 KB
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    和我们期望一致,该数据集包括1000个样本,包括5个特征,以及对应的响应目标标签。我们设置**n_informative** 为3,因此,仅 (X1, X2, X3)是重要的,另外两个 X4X5, 是多余的。

    现状我们检查标签y的基数和总数:

    dataset['y'].value_counts()
    
    1    502
    0    498
    Name: y, dtype: int64
    
    • 1
    • 2
    • 3
    • 4
    • 5

    标签仅包括两个可能的值,因此属于二分类数据集。而且两者数量大致相当,因此标签分类相对平衡。下面查看前5条样本值:

    dataset.head()
    
    • 1
    X1X2X3X4X5y
    02.501284-0.1591550.6724383.4699910.9492680
    12.203247-0.3312710.7943193.2599630.8324510
    2-1.524573-0.8707371.004304-1.028624-0.7173831
    31.8014983.1063361.490633-0.297404-0.6074840
    4-0.1251460.9879150.880293-0.937299-0.6268220

    分类示例

    生成数据集看上去不错,下面利用缺省超参数创建随机森林分类器。我们使用交叉验证衡量模型性能:

    from sklearn.ensemble import RandomForestClassifier
    from sklearn.model_selection import cross_validate
    
    # initialize classifier
    classifier = RandomForestClassifier() 
    
    # Run cross validation with 10 folds
    scores = cross_validate(
        classifier, X, y, cv=10, 
        # measure score for a list of classification metrics
        scoring=['accuracy', 'precision', 'recall', 'f1']
    )
    
    scores = pd.DataFrame(scores)
    scores.mean().round(4)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    输出结果如下, 模型的 Accuracy, Precision, Recall, 和 F1 Score接近88%. 没有调整任何超参数情况下,表现尚可。

    fit_time          0.1201
    score_time        0.0072
    test_accuracy     0.8820
    test_precision    0.8829
    test_recall       0.8844
    test_f1           0.8827
    dtype: float64
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    不易分类数据集

    下面尝试创建要给不容易分类的数据集。我们可以使用下面**make_classification()**函数参数控制数据集的难度级别:

    • flip_y: 通过反转少量标签增加噪声数据 . 举例,改变少量标签值0的值为1,返回改变1为0. 该值越大噪声越多,缺省值为 0.01.
    • class_sep: 类别之间的距离,默认值为1.0,表示原始特征空间中的类别之间的平均距离. 值越小分类越难.

    下面代码使用flip_y较高的值与class_sep较低的值创建有挑战性的数据集:

    X, y = make_classification(
        # same as the previous section
        n_samples=1000, n_features=5, n_informative=3, n_classes=2, 
        # flip_y - high value to add more noise
        flip_y=0.1, 
        # class_sep - low value to reduce space between classes
        class_sep=0.5
    )
    
    # Check label class distribution
    pd.DataFrame(y).value_counts()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    1    508
    0    492
    dtype: int64
    
    • 1
    • 2
    • 3

    0 和 1 标签对应的样本量几乎相当。因此分类相对平衡。

    分类较难数据集

    我们再次构建随机森林模型,并使用默认超参数。这次使用较难的数据集:

    classifier = RandomForestClassifier() 
    
    scores = cross_validate(
        classifier, X, y, cv=10, 
        scoring=['accuracy', 'precision', 'recall', 'f1']
    )
    
    scores = pd.DataFrame(scores)
    scores.mean()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    fit_time          0.138662
    score_time        0.007333
    test_accuracy     0.756000
    test_precision    0.764619
    test_recall       0.760196
    test_f1           0.759281
    dtype: float64
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    模型的Accuracy, Precision, Recall, 和F1 Score 参数值大约在75~76%.相对前面88%有了明显下降。

    flip_y 和**class_sep** 参数值起作用了,它们创建的数据集确实较难分类。

    不平衡数据集

    前面我们创建的数据集,每个分类对应样本大致相等。但有时我们需要不平衡数据集,即其中一个标签分类样本数据比较稀少。

    我们可以使用参数weights去控制每个分类的比例。下面代码利用make_classification 函数给样本0值标签分配比例97%, 剩下了的分类值1占3%:

    X, y = make_classification(
        # the usual parameters
        n_samples=1000, n_features=5, n_informative=3, n_classes=2, 
        # Set label 0 for  97% and 1 for rest 3% of observations
        weights=[0.97], 
    )
    
    pd.DataFrame(y).value_counts()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    0    964
    1     36
    dtype: int64
    
    • 1
    • 2
    • 3

    从结果看,**make_classification()**函数分配了3%比例给标签值为1的样本,确实生成了不平衡数据集。

    分类不平衡数据集

    与前节一样,仍使用缺省超参数的随机森林模型训练不平衡数据集:

    classifier = RandomForestClassifier() 
    
    scores = cross_validate(
        classifier, X, y, cv=10, 
        scoring=['accuracy', 'precision', 'recall', 'f1']
    )
    
    scores = pd.DataFrame(scores)
    scores.mean()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    fit_time          0.101848
    score_time        0.006896
    test_accuracy     0.964000
    test_precision    0.250000
    test_recall       0.083333
    test_f1           0.123333
    dtype: float64
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    我们看到有趣的现象,我们的模型准确率很高(96%),但精确率和召回率很低(25% 和 8%)。这是典型的准确率悖论,当处理不平衡数据经常会发生。

    多分类数据集

    到目前为止,我们生成的标签仅有两种可能。如果你需要多分类数据做实验,则标签需要超过2个值。n_classes参数可以实现:

    X, y = make_classification(
        # same parameters as usual 
        n_samples=1000, n_features=5, n_informative=3,
        # create target label with 3 classes
        n_classes=3, 
    )
    
    pd.DataFrame(y).value_counts()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    1    334
    2    333
    0    333
    dtype: int64
    
    • 1
    • 2
    • 3
    • 4

    从结果看,三个分类样本大致相当,数据集分类较平衡。

    多分类不平衡数据集

    我们也可以很容易创建不平衡多分类数据集,只需要使用参数 n_classes 和 weights :

    X, y = make_classification(
        # same parameters as usual 
        n_samples=1000, n_features=5, n_informative=3,
        # create target label with 3 classes
        n_classes=3, 
        # assign 4% of rows to class 0, 48% to class 1
        # and the rest to class 2
        weights=[0.04, 0.48]
    )
    
    pd.DataFrame(y).value_counts()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    0 值分类占 4%, 1 值占 48%, 剩下的给值 2 标签。查看结果:

    2    479
    1    477
    0     44
    dtype: int64
    
    • 1
    • 2
    • 3
    • 4

    1000个样本中 0 值标签仅有44个,和预期一致。

    总结

    现在你学会了使用scikit-learn的make_classification函数生成不同类型数据集了吧。包括二分类或多分类、不平衡数据集、挑战性难分类的数据集等。更多参数可以查看官方文档,本文参考:How to Generate Datasets Using make_classification | Proclus Academy

  • 相关阅读:
    基于HTML和JavaScript的会议室预约管理系统
    3D视觉 之 线激光3D相机
    数字孪生智慧场馆|智慧协同,立体可控,节省方案智能化建设投资
    大数据学习——安装hive
    线上接口流量突增,扛不住了
    通配符ssl证书的作用有哪些?为什么通配符ssl证书如此受欢迎?
    域对象共享数据
    Java设计模式之门面模式(Facade Pattern)
    TL072ACDR 丝印072AC SOP-8 双路JFET输入运算放大器芯片
    rosbag遍历数据出错:(unicode error) 'utf-8' codec can't decode byte 0xcd in position 31: invalid continuation byte
  • 原文地址:https://blog.csdn.net/neweastsun/article/details/132863930