Dataset.shuffle() 后批次中的部分随机元素
Partially random elements in batch after Dataset.shuffle()
我在 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。似乎数据集没有像我预期的那样被洗牌可能会导致精度不会稳定增加。但是我看不出我的代码有什么问题。
在.shuffle(10 000)
中,10 000
是缓冲区大小,这意味着它将从前10 000张图像中采样。由于您有大约 30 000 张图像,因此这只会产生第一批和第二批 classes 中的图像。随着你继续训练,你将从 class (1,2,3) 开始采样,然后只有 (2,3),然后 (2,3,4),然后 (3,4),然后 ( 3,4,1),然后 (4,1),然后 (4,1,2),然后 (1,2),然后 (1,2,3),依此类推。如果有内存,请尝试将洗牌缓冲区大小设置为 30 000,或者如果没有,请先洗牌路径列表,然后使用大批量大小。
我在 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。似乎数据集没有像我预期的那样被洗牌可能会导致精度不会稳定增加。但是我看不出我的代码有什么问题。
在.shuffle(10 000)
中,10 000
是缓冲区大小,这意味着它将从前10 000张图像中采样。由于您有大约 30 000 张图像,因此这只会产生第一批和第二批 classes 中的图像。随着你继续训练,你将从 class (1,2,3) 开始采样,然后只有 (2,3),然后 (2,3,4),然后 (3,4),然后 ( 3,4,1),然后 (4,1),然后 (4,1,2),然后 (1,2),然后 (1,2,3),依此类推。如果有内存,请尝试将洗牌缓冲区大小设置为 30 000,或者如果没有,请先洗牌路径列表,然后使用大批量大小。