TF2.0数据API从每个类标签获取n_i个样本

3

我需要使用TF2 Keras模型将形状为32x32的输入分为3个类别。我的训练集有7000个示例。

>>> X_train.shape # (7000, 32, 32)
>>> Y_train.shape # (7000, 3)

每个类别的示例数量不同(例如,class_0有约2500个示例,而class_1有约800个示例等)。
我想使用tf.data API创建一个数据集对象,该对象返回训练数据的批次,并且每个类别的示例数由[n_0,n_1,n_2]指定。
我希望这些n_i来自每个类别的样本均从X_train、Y_train中随机抽取(且放回)。
例如,如果我调用get_batch([100, 150, 125]),它应该返回100个来自class_0的X_batch随机样本,150个来自class_1,以及125个来自class_2。
如何使用TF2.0 Data API实现这一点,以便可以将其用于训练Keras模型?
2个回答

2
一种可能的方法如下:
  1. 将数据从X_trainY_train加载到单个tf.data数据集中,以确保每个X与正确的Y匹配
  2. .shuffle()然后使用filter()将数据集拆分成每个n_i
  3. 编写我们的get_batch函数,以从每个数据集返回正确数量的样本,shuffle()样本,然后将其拆分回XY
类似于这样:
# 1: Load the data into a Dataset
raw_data = tf.data.Dataset.zip(
    (
        tf.data.Dataset.from_tensor_slices(X_train),
        tf.data.Dataset.from_tensor_slices(Y_train)
    )
  ).shuffle(7000)


# 2: Split for each category
def get_filter_fn(n):
  def filter_fn(x, y):
    return tf.equal(1.0, y[n])
  return filter_fn

n_0s = raw_data.filter(get_filter_fn(0))
n_1s = raw_data.filter(get_filter_fn(1))
n_2s = raw_data.filter(get_filter_fn(2))

# 3:
def get_batch(n_0,n_1,n_2):
  sample = n_0s.take(n_0).concatenate(n_1s.take(n_1)).concatenate(n_2s.take(n_2))
  shuffled = sample.shuffle(n_0 + n_1 + n_2)
  return shuffled.map(lambda x,y: x),shuffled.map(lambda x,y: y) 

So now we can do:

x_batch, y_batch = get_batch(100, 150, 125)

请注意,我在追求一种我认为直观和简单的方法时使用了一些可能浪费的操作(具体来说是读取raw_data数据集3次进行过滤操作),因此我不声称这是实现所需的最有效方法,但对于像您描述的适合内存的数据集,我相信这种低效将是可以忽略的。"最初的回答"

1
Keras的 train_test_split实际上有一个参数可以做到这一点。虽然它不允许您选择确切数量的样本,但它会从类中均匀地选择它们。
X_train_stratified, X_test_stratified, y_train_strat, y_test_strat = train_test_split(X_train, y_train, test_size=0.2, stratify=y)

如果您想进行交叉验证,您也可以使用分层随机划分
我希望我正确理解了您的问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接