【问题标题】:sample X examples from each class label从每个类标签中采样 X 个示例
【发布时间】:2018-07-03 15:48:53
【问题描述】:

我有一个包含50 classes 和 9000 个训练示例的数据集(numpy 向量)。

x_train=(9000,2048)
y_train=(9000,)  # Classes are strings 
classes=list(set(y_train))

我想建立一个子数据集,这样每个类将有 5 个示例

这意味着我得到了5*50=250 训练示例。因此我的子数据集将采用这种形式:

sub_train_data=(250,2048)
sub_train_labels=(250,)

备注:我们从每个类中随机抽取 5 个样本(总类数 = 50)

谢谢

【问题讨论】:

  • 听起来不错。是什么让你不这样做?
  • 我想知道这样做是为了估计需要多少示例才能获得最高准确度。我想从每个类的 5 个示例开始,然后是 10、20、40、80、160,320 ... 并绘制精度。一旦准确率保持不变,就停止数据标注。
  • 任何 ide @kazemakase ?
  • 不,因为我不知道问题出在哪里。你有没有尝试过什么?你在哪里卡住了?真正的问题是什么?
  • @kazemakase,这是问题的答案

标签: python random scikit-learn resampling sklearn-pandas


【解决方案1】:

这是解决该问题的方法:

from collections import Counter
import numpy as np
import matplotlib.pyplot as plt

def balanced_sample_maker(X, y, sample_size, random_seed=42):
    uniq_levels = np.unique(y)
    uniq_counts = {level: sum(y == level) for level in uniq_levels}

    if not random_seed is None:
        np.random.seed(random_seed)

    # find observation index of each class levels
    groupby_levels = {}
    for ii, level in enumerate(uniq_levels):
        obs_idx = [idx for idx, val in enumerate(y) if val == level]
        groupby_levels[level] = obs_idx
    # oversampling on observations of each label
    balanced_copy_idx = []
    for gb_level, gb_idx in groupby_levels.items():
        over_sample_idx = np.random.choice(gb_idx, size=sample_size, replace=True).tolist()
        balanced_copy_idx+=over_sample_idx
    np.random.shuffle(balanced_copy_idx)

    data_train=X[balanced_copy_idx]
    labels_train=y[balanced_copy_idx]
    if  ((len(data_train)) == (sample_size*len(uniq_levels))):
        print('number of sampled example ', sample_size*len(uniq_levels), 'number of sample per class ', sample_size, ' #classes: ', len(list(set(uniq_levels))))
    else:
        print('number of samples is wrong ')

    labels, values = zip(*Counter(labels_train).items())
    print('number of classes ', len(list(set(labels_train))))
    check = all(x == values[0] for x in values)
    print(check)
    if check == True:
        print('Good all classes have the same number of examples')
    else:
        print('Repeat again your sampling your classes are not balanced')
    indexes = np.arange(len(labels))
    width = 0.5
    plt.bar(indexes, values, width)
    plt.xticks(indexes + width * 0.5, labels)
    plt.show()
    return data_train,labels_train

X_train,y_train=balanced_sample_maker(X,y,10)

灵感来自Scikit-learn balanced subsampling

【讨论】:

  • 优秀。您确定要使用replace=True 吗?这意味着同一数据点可以在子样本中出现多次。
  • 是的,如果我在给定的类中只有一个例子
  • 但实际上,我使用的是 False。我主要在我想大幅增加数据集时使用 true
  • 当我必须从每组中抽取不同数量的样本时,我该如何做同样的事情。 (或 np.unique(y))
【解决方案2】:

为此,我通常使用 scikit-learn 的技巧。我使用StratifiedShuffleSplit 函数。因此,如果我必须选择我的训练集的 1/n 部分,我将数据分成 n 个折叠并将测试数据的比例(test_size)设置为 1-1/n。这是一个示例,其中我仅使用了 1/10 的数据。

sp = StratifiedShuffleSplit(n_splits=1, test_size=0.9, random_state=seed)
  for train_index, _ in sp.split(x_train, y_train):
    x_train, y_train = x_train[train_index], y_train[train_index]

【讨论】:

    【解决方案3】:

    您可以使用数据框作为输入(如我的情况),并使用下面的简单代码:

    col = target
    nsamples = min(t4m[col].value_counts().values)
    res = pd.DataFrame()
    for val in t4m[col].unique():
      t = t4m.loc[t4m[col] == val].sample(nsamples)
      res = pd.concat([res, t], ignore_index=True).sample(frac=1)
    

    col 是包含类的列的名称。代码找到少数类,打乱数据帧,然后从每个类中抽取少数类大小的样本。

    然后你可以将结果转换回 np.array

    【讨论】:

      猜你喜欢
      • 2019-12-23
      • 2012-03-11
      • 2019-07-28
      • 2020-10-23
      • 1970-01-01
      • 2020-11-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-08
      相关资源
      最近更新 更多