keras 如何在2个不同的图像输入上执行相同的数据增强?

iugsix8n  于 2023-10-19  发布在  其他
关注(0)|答案(1)|浏览(129)

我想用2个图像输入构建一个多路径CNN,每个输入都输入自己的CNN,然后在最后将特征连接起来。现在我有这样的东西:
第一组图像的特征和标签:X(具有特征)y(标签)
第二组图像的特征和标签(分段):X_2(具有特征)y_2(具有标签)
我的增强代码是这样的:

  1. data_augmentation = tf.keras.Sequential()
  2. data_augmentation.add(tf.keras.layers.RandomFlip("horizontal_and_vertical"))
  3. data_augmentation.add(tf.keras.layers.RandomRotation(0.2))
  4. data_augmentation.add(tf.keras.layers.RandomZoom(height_factor=(.05),
  5. width_factor=(.05)))

我想让CNN看起来像这样:CNN model
第一和第二组图像都是相同的大小并且顺序相同。唯一的区别是第二组是分段的。我想对这两个应用相同的数据增强。有人知道怎么做吗?
我试着在网上寻找一些答案,但我发现大多数关于多输入CNNS的网站都没有使用增强层,所以我被卡住了。

xkftehaa

xkftehaa1#

(See以下为原始答案)
我猜这个Keras文档与Keras中的数据增强有关。特别是,它提到了使用数据增强层的两个选项:在Model中使用它,并在tf.data管道中使用它。
下面是一个使用第二个选项的粗略(可以将其视为伪代码)示例实现。
此外,我个人倾向于使用自定义的Model来实现问题中描述的Model,以实现灵活性,但也许有一些方法可以使用更高级别的Keras API来实现。
在下面的代码片段中,设置了一个自定义的Model,然后是训练数据集管道。它缺乏确切的加载步骤,但应该给予一个如何将数据集与自定义Model连接的粗略概念。

  1. import tensorflow as tf
  2. class TwinCNN(tf.keras.Model):
  3. def __init__(self, name="TwinCNN"):
  4. super().__init__(name=name)
  5. self.cnn_for_color = [
  6. tf.keras.layers.Conv2D(128, 3, padding="same"),
  7. tf.keras.layers.Conv2D(128, 3, padding="same"),
  8. tf.keras.layers.Conv2D(128, 3, padding="same"),
  9. ] # Some layers
  10. self.cnn_for_segment = [
  11. tf.keras.layers.Conv2D(64, 3, padding="same"),
  12. tf.keras.layers.Conv2D(64, 3, padding="same"),
  13. tf.keras.layers.Conv2D(64, 3, padding="same"),
  14. ]
  15. self.classifier = [
  16. tf.keras.layers.Flatten(),
  17. tf.keras.layers.Dense(
  18. units=4, # seems there are 4 classes
  19. activation=tf.nn.softmax)
  20. ]
  21. def call(self, inputs, training):
  22. color_image = inputs['color']
  23. segment_image = inputs['segment']
  24. color_fts = color_image
  25. for ly in self.cnn_for_color:
  26. color_fts = ly(color_fts, training=training)
  27. segment_fts = segment_image
  28. for ly in self.cnn_for_segment:
  29. segment_fts = ly(segment_fts, training=training)
  30. concat_fts = tf.concat([color_fts, segment_fts], axis=-1, name='concat_fts')
  31. net = concat_fts
  32. for ly in self.classifier:
  33. net = ly(net, training=training)
  34. return net # shape Nx4
  35. # Your data augmentation layers
  36. data_augmentation = tf.keras.Sequential()
  37. data_augmentation.add(tf.keras.layers.RandomFlip("horizontal_and_vertical"))
  38. data_augmentation.add(tf.keras.layers.RandomRotation(0.2))
  39. data_augmentation.add(tf.keras.layers.RandomZoom(height_factor=(.05),
  40. width_factor=(.05)))
  41. def apply_augment_to_zipped(color_img, segment_img):
  42. c_color = color_img.shape[-1] # Number of channels
  43. concat_img = tf.concat([color_img, segment_img], axis=-1)
  44. # **For your test/validation dataset, don't use augmentation!**
  45. img_aug = data_augmentation(concat_img, training=True)
  46. color_aug = img_aug[..., :c_color]
  47. segment_aug = img_aug[..., c_color:]
  48. return color_aug, segment_aug
  49. def turn_image_tuple_to_dict(color_img, segment_img):
  50. # Put the two images into a dict
  51. return dict(color=color_img, segment=segment_img)
  52. # Assuming ds_color and ds_segment has the *same* label, so we can take either one
  53. ds_color_images = tf.data.Dataset(...) # Set up a dataset for color images
  54. ds_labels = tf.data.Dataset(...) # Set up a dataset for labels
  55. ds_segment_images = tf.data.Dataset(...) # Set up a dataset for segment images
  56. ds_images = tf.data.Dataset.zip((ds_color_images, ds_segment_images)) # each entry will be a tuple of 2 images
  57. ds_images_augmented = ds_images.map(apply_augment_to_zipped)
  58. ds_images_augmented = ds_images_augmented.map(turn_image_tuple_to_dict)
  59. ds_train = tf.data.Dataset.zip((ds_images_augmented, ds_labels)) # The training set
  60. # NOTE: for a validation dataset, we should skip the augmentation (i.e. don't call apply_augment_to_zipped)
  61. model = TwinCNN()
  62. # TODO: select an optimizer,
  63. # TODO: model.compile(optimizer)
  64. model.fit(
  65. ds_train, # TODO: other training settings
  66. )

原始答案

由于两个数据集大小相同,因此可以使用

  1. ds = tf.data.Dataset.zip((ds1, ds2))

以创建数据集,其中每个条目是一对图像,比如(x, x2)。然后我们可以做一些事情,

  1. ds = ds.map(lambda x, x2: tf.concat([x, x2], axis=-1))

xx2合并为一个更适合增强层的Tensor。
假设对于每个x(假设3个通道)和每个x2(假设1个通道),通道的数量是恒定的,则可以在之后切片扩增结果:

  1. x_aug = input_tensor[..., :3]
  2. x2_aug = input_tensor[..., 3:4]

顺便说一下,如果问题更详细一些就更好了。例如,提供一些代码或伪代码来解释数据在“多路径CNN”中应该如何流动以及正在尝试什么样的数据增强将是有帮助的。

展开查看全部

相关问题