tfds.load() 之后如何在 TensorFlow 2.0 中应用数据增强
How to apply data augmentation in TensorFlow 2.0 after tfds.load()
我正在关注 this guide。
它展示了如何使用 tfds.load()
方法从新的 TensorFlow 数据集中下载数据集:
import tensorflow_datasets as tfds
SPLIT_WEIGHTS = (8, 1, 1)
splits = tfds.Split.TRAIN.subsplit(weighted=SPLIT_WEIGHTS)
(raw_train, raw_validation, raw_test), metadata = tfds.load(
'cats_vs_dogs', split=list(splits),
with_info=True, as_supervised=True)
接下来的步骤展示了如何使用 map 方法将函数应用于数据集中的每个项目:
def format_example(image, label):
image = tf.cast(image, tf.float32)
image = image / 255.0
# Resize the image if required
image = tf.image.resize(image, (IMG_SIZE, IMG_SIZE))
return image, label
train = raw_train.map(format_example)
validation = raw_validation.map(format_example)
test = raw_test.map(format_example)
然后访问我们可以使用的元素:
for features in ds_train.take(1):
image, label = features["image"], features["label"]
或
for example in tfds.as_numpy(train_ds):
numpy_images, numpy_labels = example["image"], example["label"]
但是,该指南没有提及任何关于数据扩充的内容。我想使用类似于 Keras 的 ImageDataGenerator Class 的实时数据增强。我尝试使用:
if np.random.rand() > 0.5:
image = tf.image.flip_left_right(image)
和 format_example()
中的其他类似增强功能但是,我如何验证它正在执行实时增强而不是替换数据集中的原始图像?
我可以通过将 batch_size=-1
传递给 tfds.load()
然后使用 tfds.as_numpy()
将完整的数据集转换为 Numpy 数组,但是,这会将所有不需要的图像加载到内存中。我应该能够使用 train = train.prefetch(tf.data.experimental.AUTOTUNE)
为下一个训练循环加载足够的数据。
您从错误的方向来解决问题。
首先,使用tfds.load
、cifar10
下载数据(为简单起见,我们将使用默认的TRAIN
和TEST
拆分):
import tensorflow_datasets as tfds
dataloader = tfds.load("cifar10", as_supervised=True)
train, test = dataloader["train"], dataloader["test"]
(您可以使用自定义 tfds.Split
对象来创建验证数据集或其他,see documentation)
train
和 test
是 tf.data.Dataset
对象,因此您可以对每个对象使用 map
、apply
、batch
和类似函数那些。
下面是一个示例,我将在其中(主要使用 tf.image
):
- 将每个图像转换为
0-1
范围内的 tf.float64
(不要使用官方文档中的这个愚蠢的片段,这样可以确保正确的图像格式)
cache()
结果,因为这些结果可以在每个 repeat
之后重复使用
- 随机翻转
left_to_right
每张图片
- 随机改变图像的对比度
- 洗牌数据和批次
- 重要提示: 当数据集用完时,重复所有步骤。这意味着在一个纪元之后,所有上述转换都会再次应用(缓存的除外)。
这是执行上述操作的代码(您可以将 lambda
s 更改为仿函数或函数):
train = train.map(
lambda image, label: (tf.image.convert_image_dtype(image, tf.float32), label)
).cache().map(
lambda image, label: (tf.image.random_flip_left_right(image), label)
).map(
lambda image, label: (tf.image.random_contrast(image, lower=0.0, upper=1.0), label)
).shuffle(
100
).batch(
64
).repeat()
这样的tf.data.Dataset
可以直接传给Keras的fit
、evaluate
和predict
方法
验证它确实如此工作
我看你对我的解释很怀疑,我们来看个例子:
1。获取一小部分数据
这是获取单个元素的一种方法,虽然不可读且不直观,但如果您对 Tensorflow
:
做任何事情,应该没问题
# Horrible API is horrible
element = tfds.load(
# Take one percent of test and take 1 element from it
"cifar10",
as_supervised=True,
split=tfds.Split.TEST.subsplit(tfds.percent[:1]),
).take(1)
2。重复数据,检查是否相同:
使用 Tensorflow 2.0
实际上可以做到这一点,而无需愚蠢的解决方法(几乎):
element = element.repeat(2)
# You can iterate through tf.data.Dataset now, finally...
images = [image[0] for image in element]
print(f"Are the same: {tf.reduce_all(tf.equal(images[0], images[1]))}")
不出所料 returns:
Are the same: True
3。检查每次重复随机增强后数据是否不同
下面的代码片段 repeat
s 单个元素 5 次并检查哪些相等哪些不同。
element = (
tfds.load(
# Take one percent of test and take 1 element
"cifar10",
as_supervised=True,
split=tfds.Split.TEST.subsplit(tfds.percent[:1]),
)
.take(1)
.map(lambda image, label: (tf.image.random_flip_left_right(image), label))
.repeat(5)
)
images = [image[0] for image in element]
for i in range(len(images)):
for j in range(i, len(images)):
print(
f"{i} same as {j}: {tf.reduce_all(tf.equal(images[i], images[j]))}"
)
输出(在我的例子中,每个 运行 都会不同):
0 same as 0: True
0 same as 1: False
0 same as 2: True
0 same as 3: False
0 same as 4: False
1 same as 1: True
1 same as 2: False
1 same as 3: True
1 same as 4: True
2 same as 2: True
2 same as 3: False
2 same as 4: False
3 same as 3: True
3 same as 4: True
4 same as 4: True
您也可以将这些图像中的每一个投射到 numpy
,然后使用 skimage.io.imshow
, matplotlib.pyplot.imshow
或其他替代方法亲自查看这些图像。
实时数据增强可视化的另一个例子
使用 Tensorboard
和 MNIST
提供了关于数据扩充的更全面和可读的视图,可能想检查一下(是的,无耻的插件,但我想很有用).
我正在关注 this guide。
它展示了如何使用 tfds.load()
方法从新的 TensorFlow 数据集中下载数据集:
import tensorflow_datasets as tfds
SPLIT_WEIGHTS = (8, 1, 1)
splits = tfds.Split.TRAIN.subsplit(weighted=SPLIT_WEIGHTS)
(raw_train, raw_validation, raw_test), metadata = tfds.load(
'cats_vs_dogs', split=list(splits),
with_info=True, as_supervised=True)
接下来的步骤展示了如何使用 map 方法将函数应用于数据集中的每个项目:
def format_example(image, label):
image = tf.cast(image, tf.float32)
image = image / 255.0
# Resize the image if required
image = tf.image.resize(image, (IMG_SIZE, IMG_SIZE))
return image, label
train = raw_train.map(format_example)
validation = raw_validation.map(format_example)
test = raw_test.map(format_example)
然后访问我们可以使用的元素:
for features in ds_train.take(1):
image, label = features["image"], features["label"]
或
for example in tfds.as_numpy(train_ds):
numpy_images, numpy_labels = example["image"], example["label"]
但是,该指南没有提及任何关于数据扩充的内容。我想使用类似于 Keras 的 ImageDataGenerator Class 的实时数据增强。我尝试使用:
if np.random.rand() > 0.5:
image = tf.image.flip_left_right(image)
和 format_example()
中的其他类似增强功能但是,我如何验证它正在执行实时增强而不是替换数据集中的原始图像?
我可以通过将 batch_size=-1
传递给 tfds.load()
然后使用 tfds.as_numpy()
将完整的数据集转换为 Numpy 数组,但是,这会将所有不需要的图像加载到内存中。我应该能够使用 train = train.prefetch(tf.data.experimental.AUTOTUNE)
为下一个训练循环加载足够的数据。
您从错误的方向来解决问题。
首先,使用tfds.load
、cifar10
下载数据(为简单起见,我们将使用默认的TRAIN
和TEST
拆分):
import tensorflow_datasets as tfds
dataloader = tfds.load("cifar10", as_supervised=True)
train, test = dataloader["train"], dataloader["test"]
(您可以使用自定义 tfds.Split
对象来创建验证数据集或其他,see documentation)
train
和 test
是 tf.data.Dataset
对象,因此您可以对每个对象使用 map
、apply
、batch
和类似函数那些。
下面是一个示例,我将在其中(主要使用 tf.image
):
- 将每个图像转换为
0-1
范围内的tf.float64
(不要使用官方文档中的这个愚蠢的片段,这样可以确保正确的图像格式) cache()
结果,因为这些结果可以在每个repeat
之后重复使用
- 随机翻转
left_to_right
每张图片 - 随机改变图像的对比度
- 洗牌数据和批次
- 重要提示: 当数据集用完时,重复所有步骤。这意味着在一个纪元之后,所有上述转换都会再次应用(缓存的除外)。
这是执行上述操作的代码(您可以将 lambda
s 更改为仿函数或函数):
train = train.map(
lambda image, label: (tf.image.convert_image_dtype(image, tf.float32), label)
).cache().map(
lambda image, label: (tf.image.random_flip_left_right(image), label)
).map(
lambda image, label: (tf.image.random_contrast(image, lower=0.0, upper=1.0), label)
).shuffle(
100
).batch(
64
).repeat()
这样的tf.data.Dataset
可以直接传给Keras的fit
、evaluate
和predict
方法
验证它确实如此工作
我看你对我的解释很怀疑,我们来看个例子:
1。获取一小部分数据
这是获取单个元素的一种方法,虽然不可读且不直观,但如果您对 Tensorflow
:
# Horrible API is horrible
element = tfds.load(
# Take one percent of test and take 1 element from it
"cifar10",
as_supervised=True,
split=tfds.Split.TEST.subsplit(tfds.percent[:1]),
).take(1)
2。重复数据,检查是否相同:
使用 Tensorflow 2.0
实际上可以做到这一点,而无需愚蠢的解决方法(几乎):
element = element.repeat(2)
# You can iterate through tf.data.Dataset now, finally...
images = [image[0] for image in element]
print(f"Are the same: {tf.reduce_all(tf.equal(images[0], images[1]))}")
不出所料 returns:
Are the same: True
3。检查每次重复随机增强后数据是否不同
下面的代码片段 repeat
s 单个元素 5 次并检查哪些相等哪些不同。
element = (
tfds.load(
# Take one percent of test and take 1 element
"cifar10",
as_supervised=True,
split=tfds.Split.TEST.subsplit(tfds.percent[:1]),
)
.take(1)
.map(lambda image, label: (tf.image.random_flip_left_right(image), label))
.repeat(5)
)
images = [image[0] for image in element]
for i in range(len(images)):
for j in range(i, len(images)):
print(
f"{i} same as {j}: {tf.reduce_all(tf.equal(images[i], images[j]))}"
)
输出(在我的例子中,每个 运行 都会不同):
0 same as 0: True
0 same as 1: False
0 same as 2: True
0 same as 3: False
0 same as 4: False
1 same as 1: True
1 same as 2: False
1 same as 3: True
1 same as 4: True
2 same as 2: True
2 same as 3: False
2 same as 4: False
3 same as 3: True
3 same as 4: True
4 same as 4: True
您也可以将这些图像中的每一个投射到 numpy
,然后使用 skimage.io.imshow
, matplotlib.pyplot.imshow
或其他替代方法亲自查看这些图像。
实时数据增强可视化的另一个例子
Tensorboard
和 MNIST
提供了关于数据扩充的更全面和可读的视图,可能想检查一下(是的,无耻的插件,但我想很有用).