【问题标题】:How to perform up-sampling using sample() function(py-spark)如何使用 sample() 函数(pyspark)执行上采样
【发布时间】:2019-04-15 19:43:06
【问题描述】:

我正在研究二元分类机器学习问题,我正在尝试平衡训练集,因为我有一个不平衡的目标类变量。我正在使用 Py-Spark 构建模型。

下面是平衡数据的代码

train_initial, test = new_data.randomSplit([0.7, 0.3], seed = 2018)
train_initial.groupby('label').count().toPandas()
   label   count                                                                
0    0.0  712980
1    1.0    2926
train_new = train_initial.sampleBy('label', fractions={0: 2926./712980, 1: 1.0}).cache()

上面的代码执行了欠采样,但我认为这可能会导致信息丢失。但是,我不确定如何执行上采样。我还尝试使用如下示例函数:

train_up = train_initial.sample(True, 10.0, seed = 2018)

虽然它在我的数据集中增加了 1 的计数,但它也增加了 0 的计数并给出了以下结果。

   label    count                                                               
0    0.0  7128722
1    1.0    29024

有人可以帮我在 py-spark 中实现上采样吗?

非常感谢提前!

【问题讨论】:

    标签: machine-learning pyspark random-forest sampling


    【解决方案1】:

    适用于任何试图在 pyspark 中对不平衡数据集进行随机过采样的人。以下代码将帮助您入门(在此 sn-p 中,0 是市长类,1 是要过采样的类):

    df_a = df.filter(df['label'] == 0)
    df_b = df.filter(df['label'] == 1)
    
    a_count = df_a.count()
    b_count = df_b.count() 
    ratio = a_count / b_count
    
    df_b_overampled = df_b.sample(withReplacement=True, fraction=ratio, seed=1)
    df = df_a.unionAll(df_b_oversampled)
    

    【讨论】:

    • 此解决方案不起作用,因为 df_b_oversampled 的大小将仅包含原始数据集的比例分数
    • @Spandyie 如果 A 有 1000 条记录,B 有 100 条记录,则比率为 10。B 将被过采样 10 的一小部分,因此将是 1000。我已经对其进行了测试,它可以工作。
    • 这行得通。您可以像这样将“比率”与 .sampleBy() 一起使用:fractions = {0:ratio, 1:1} df_sampled = df.sampleBy('label', fractions)
    【解决方案2】:

    我在这里救援可能已经很晚了。但这是我的建议:

    第 1 步。仅用于 label = 1 的示例

    train_1= train_initial.where(col('label')==1).sample(True, 10.0, seed = 2018)
    

    第 2 步。将此数据与 label = 0 数据合并

    train_0=train_initial.where(col('label')==0)
    train_final = train_0.union(train_1)
    

    PS:请用

    导入col
    from pyspark.sql.functions import col
    

    【讨论】:

      【解决方案3】:

      问题是您对整个数据框进行了过采样。您应该过滤来自这两个类的数据

      df_class_0 = df_train[df_train['label'] == 0]
      df_class_1 = df_train[df_train['label'] == 1]
      df_class_1_over = df_class_1.sample(count_class_0, replace=True)
      df_test_over = pd.concat([df_class_0, df_class_1_over], axis=0)
      

      示例来自:https://www.kaggle.com/rafjaa/resampling-strategies-for-imbalanced-datasets

      请注意,有更好的方法来执行过采样(例如 SMOTE)

      【讨论】:

      • 非常感谢您的回复,pyspark中的sample函数不会对class进行计数。我可以用class 0在整个数据集中的比例来sample class 1吗?给出相同的结果。另外,我不确定是否可以在 pyspark 中使用 SMOTE。我在 py-spark 文档中找不到任何库来导入 SMOTE。任何想法,我如何在 py-spark 中使用 SMOTE。
      • @TusharMehta 只是为了清楚我不是 pyspark 用户。我想您可以使用百分比进行抽样。您不能使用标准样本函数进行重采样并将结果传递给 Py-spark 函数吗?
      猜你喜欢
      • 1970-01-01
      • 2018-05-18
      • 1970-01-01
      • 2020-12-28
      • 2018-08-21
      • 2017-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多