如何使用 tensorflow_datasets (tfds) 实施和理解预处理和数据扩充?

How to implement and understand Pre-processing and Data augmentation with tensorflow_datasets (tfds)?

我正在学习基于这个 TF 2.0 tutorial 的分割和数据增强,它使用 Oxford-IIIT Pets.

对于 pre-processing/data 扩充,他们向特定管道提供了一组函数:

# Import dataset
dataset, info = tfds.load('oxford_iiit_pet:3.*.*', with_info=True)

def normalize(input_image, input_mask):
  input_image = tf.cast(input_image, tf.float32) / 255.0
  input_mask -= 1
  return input_image, input_mask

@tf.function
def load_image_train(datapoint):
  input_image = tf.image.resize(datapoint['image'], (128, 128))
  input_mask = tf.image.resize(datapoint['segmentation_mask'], (128, 128))

  if tf.random.uniform(()) > 0.5:
    input_image = tf.image.flip_left_right(input_image)
    input_mask = tf.image.flip_left_right(input_mask)

  input_image, input_mask = normalize(input_image, input_mask)

  return input_image, input_mask

TRAIN_LENGTH = info.splits['train'].num_examples
BATCH_SIZE = 64
BUFFER_SIZE = 1000
STEPS_PER_EPOCH = TRAIN_LENGTH // BATCH_SIZE

train = dataset['train'].map(load_image_train, num_parallel_calls=tf.data.experimental.AUTOTUNE)

train_dataset = train.cache().shuffle(BUFFER_SIZE).batch(BATCH_SIZE).repeat()
train_dataset = train_dataset.prefetch(buffer_size=tf.data.experimental.AUTOTUNE)

考虑到 tf 语法,这段代码给我带来了一些疑问。为了防止我只是执行 ctrl C ctrl V 并真正了解 tensorflow 的工作原理,我想问一些问题:

1) 在normalize函数中,tf.cast(input_image, tf.float32) / 255.0行可以通过tf.image.convert_image_dtype(input_image, tf.float32)?

改变

2) 在 normalize 函数中可以更改 tf.tensor 格式的 segmentation_mask 值而不用更改为 numpy?我想要做的是只使用两个可能的掩码(0 和 1)而不是(0、1 和 2)。使用 numpy 我做了这样的事情:

segmentation_mask_numpy = segmentation_mask.numpy()
segmentation_mask_numpy[(segmentation_mask_numpy == 2) | (segmentation_mask_numpy == 3)] = 0

是否可以在没有 numpy 转换的情况下做到这一点?

3) 在 load_image_train 函数中他们说这个函数正在做数据扩充,但是 怎么做?在我看来,他们正在通过给定随机数的翻转来更改原始图像,而不是向基于原始图像的数据集提供另一个图像。那么,功能目标是更改图像而不是将 aug_image 保留原始图像添加到我的数据集中?如果我是正确的,我该如何更改此函数以提供 aug_image 并将我的原始图像保留在数据集中?

4) 在其他问题中,例如 and 他们使用了很多 .map() 顺序调用或 .map().map().cache().batch().repeat()。我的问题是:有这个必要吗?存在更简单的方法来做到这一点?我尝试阅读 tf 文档,但没有成功。

5) 您建议使用来自 keras 的 ImageDataGenerator,如前所述 here 或者这种 tf 方法更好?

4 - 这些顺序调用的作用是它们 简化了 我们 操纵数据集 应用的工作转换,他们还声称这是一种更高效加载和处理数据的方式。关于 modularization/simplicity 我想它完成了它的工作,因为 你可以轻松加载 ,将它传递到整个 预处理管道 随机播放,并迭代批次数据几行代码.

train_dataset =tf.data.TFRecordDataset(filenames=train_records_paths).map(parsing_fn)
train_dataset = train_dataset.shuffle(buffer_size=12000)
train_dataset = train_dataset.batch(batch_size)
train_dataset = train_dataset.repeat()
# Create a test dataset
test_dataset = tf.data.TFRecordDataset(filenames=test_records_paths).map(parsing_fn)
test_dataset = test_dataset.batch(batch_size)
test_dataset = test_dataset.repeat(1)
# 
validation_steps = test_size / batch_size 
history = transferred_resnet50.fit(x=train_dataset,
                        epochs=epochs,
                        steps_per_epoch=steps_per_epoch,                        
                        validation_data=test_dataset,
                        validation_steps=validation_steps)

例如,为了加载我的数据集并为我的模型提供预处理数据,我只需要做这些。

3 - 他们定义了一个预处理函数,他们的数据集映射到该函数,这意味着每次请求样本时都会应用映射函数,就像我使用解析函数一样为了在使用之前从 TFRecord 格式解析我的数据:

def parsing_fn(serialized):
    features = \
        {
            'image': tf.io.FixedLenFeature([], tf.string),
            'label': tf.io.FixedLenFeature([], tf.int64)            
        }

    # Parse the serialized data so we get a dict with our data.
    parsed_example = tf.io.parse_single_example(serialized=serialized,
                                             features=features)

    # Get the image as raw bytes.
    image_raw = parsed_example['image']

    # Decode the raw bytes so it becomes a tensor with type.
    image = tf.io.decode_jpeg(image_raw)
    
    image = tf.image.resize(image,size=[224,224])
    
    # Get the label associated with the image.
    label = parsed_example['label']
    
    # The image and label are now correct TensorFlow types.
    return image, label

(另一个例子) - 从上面的解析函数我可以使用下面的代码 为了创建数据集,遍历我的测试集图像 并绘制它们。

records_path = DATA_DIR+'/'+'TFRecords'+'/test/'+'test_0.tfrecord'
# Create a dataset
dataset = tf.data.TFRecordDataset(filenames=records_path)
# Parse the dataset using a parsing function 
parsed_dataset = dataset.map(parsing_fn)
# Gets a sample from the iterator
iterator = tf.compat.v1.data.make_one_shot_iterator(parsed_dataset) 

for i in range(100):
    image,label = iterator.get_next()
    img_array = image.numpy()
    img_array = img_array.astype(np.uint8)
    plt.imshow(img_array)
    plt.show()