【问题标题】:Partially random elements in batch after Dataset.shuffle()在 Dataset.shuffle() 之后批量部分随机元素
【发布时间】:2020-03-02 13:38:30
【问题描述】:

我在 TF2.1 中使用 tf.data.Dataset 和 tf.keras 对数据集进行训练。但是我看到了奇怪的行为,即生成的批次并没有像我预期的那样完全随机显示。我的意思是,即使我的数据集有 4 个类,我通常也会在一批中只看到 2 个类的元素。我的代码如下:

def process_train_sample(file_path):
  sp = tf.strings.regex_replace(file_path, train_data_dir, '')
  cls = tf.math.argmax(tf.cast(tf.math.equal(tf.strings.split(sp, os.path.sep)[0],['A','B','C','D']), tf.int64))

  img = tf.io.read_file(file_path)
  img = tf.image.decode_jpeg(img, channels=3)  # RGB
  img = tf.image.resize(img, (224, 224))
  img = tf.cast(img, tf.float32)
  img = img - np.array([123.68, 116.779, 103.939])
  img = img / 255.0
  cls = tf.expand_dims(cls, 0)
  return img, cls

train_data_list = glob.glob(os.path.join(train_data_dir, '**', '*.jpg'), recursive=True)
train_data_list = tf.data.Dataset.from_tensor_slices(train_data_list)
train_ds = train_data_list.map(process_train_sample, num_parallel_calls=tf.data.experimental.AUTOTUNE)
train_ds = train_ds.shuffle(10000)
train_ds = train_ds.batch(batch_size)

for img,  cls in train_ds.take(10):
  print('img: ', img.numpy().shape,  'cls: ', cls.numpy())

model.compile(loss='categorical_crossentropy',  
      optimizer=optimizers.SGD(lr=0.0001, momentum=0.9),
      metrics=['categorical_accuracy', 'categorical_crossentropy'])
model.fit(train_ds, epochs=50)

当我在一个包含 4 个类别(A、B、C、D)的数据集上进行训练时,我发现训练准确度并没有稳定地增加,而是上下波动。然后我通过在for循环中逐批显示标签来检查我的数据输入管道,发现每个批次只包含来自2个类的元素,而不是4个。似乎数据集没有像我预期的那样被打乱,这可能会导致准确性不会稳步增加。但我看不出我的代码有什么问题。

【问题讨论】:

  • 你有多少张图片? >10 000?在将其转换为 tf.data.Dataset 之前,您可能会先 random.shuffle(train_data_list)
  • @FrederikBode 数据集约为 30,000。我认为缓冲区大小在这里不是问题,因为我尝试了更大的缓冲区大小但没有得到更好的结果。我实际上尝试按照您的建议在 train_data_list 上使用 random.shuffle 。当然它会变得更好,但是如果 dataset.shuffle 不能很好地工作,生成的批次仍然会相对于曾经混洗过的 train_data_list 进行某种修复。
  • @FrederikBode 似乎不同运行的结果可能不同。有时我可以批量获得相当随机的表示。如果我设置更大的缓冲区大小,它更有可能获得更好的随机性。

标签: tensorflow keras tensorflow2.0 tensorflow-datasets


【解决方案1】:

.shuffle(10 000) 中,10 000 是缓冲区大小,这意味着它将从前 10 000 个图像中采样。由于您有大约 30 000 张图像,因此这只会产生第一批中第一类和第二类的图像。当您继续训练时,您将从 (1,2,3) 类开始采样,然后仅 (2,3),然后是 (2,3,4),然后是 (3,4),然后是 (3,4, 1),然后是 (4,1),然后是 (4,1,2),然后是 (1,2),然后是 (1,2,3),以此类推。如果您有内存,请尝试将 shuffle 缓冲区大小设置为 30 000,或者如果您没有,请先打乱您的路径列表,然后使用大批量大小。

【讨论】:

    猜你喜欢
    • 2013-03-22
    • 2015-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-15
    • 1970-01-01
    • 1970-01-01
    • 2021-04-28
    相关资源
    最近更新 更多