【问题标题】:Dimensions Don't Match for Decoder in Tensorflow TutorialTensorflow 教程中的解码器尺寸不匹配
【发布时间】:2021-02-18 00:20:23
【问题描述】:

我正在关注 tensorflow 的卷积自动编码器教程,使用 tensorflow 2.0 和 keras,发现 here

使用提供的代码构建 CNN,但在编码器和解码器中再添加一个卷积层会导致代码中断:

class Denoise(Model):
  def __init__(self):
    super(Denoise, self).__init__()
    self.encoder = tf.keras.Sequential([
      layers.Input(shape=(28, 28, 1)), 
      layers.Conv2D(16, (3,3), activation='relu', padding='same', strides=2),
      layers.Conv2D(8, (3,3), activation='relu', padding='same', strides=2),
      ## New Layer ##
      layers.Conv2D(4, (3,3), activation='relu', padding='same', strides=2)
      ## --------- ##
      ])

    self.decoder = tf.keras.Sequential([
      ## New Layer ##
      layers.Conv2DTranspose(4, kernel_size=3, strides=2, activation='relu', padding='same'),
      ## --------- ##
      layers.Conv2DTranspose(8, kernel_size=3, strides=2, activation='relu', padding='same'),
      layers.Conv2DTranspose(16, kernel_size=3, strides=2, activation='relu', padding='same'),
      layers.Conv2D(1, kernel_size=(3,3), activation='sigmoid', padding='same')
      ])

  def call(self, x):
    encoded = self.encoder(x)
    decoded = self.decoder(encoded)
    return decoded

autoencoder = Denoise()

运行autoencoder.encoder.summary()autoencoder.decoder.summary(),我可以看到这是一个形状问题:

Encoder:
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_124 (Conv2D)          (None, 14, 14, 16)        160       
_________________________________________________________________
conv2d_125 (Conv2D)          (None, 7, 7, 8)           1160      
_________________________________________________________________
conv2d_126 (Conv2D)          (None, 4, 4, 4)           292       
=================================================================
Total params: 1,612
Trainable params: 1,612
Non-trainable params: 0
_________________________________________________________________

Decoder:
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_transpose_77 (Conv2DT (32, 8, 8, 4)             148       
_________________________________________________________________
conv2d_transpose_78 (Conv2DT (32, 16, 16, 8)           296       
_________________________________________________________________
conv2d_transpose_79 (Conv2DT (32, 32, 32, 16)          1168      
_________________________________________________________________
conv2d_127 (Conv2D)          (32, 32, 32, 1)           145       
=================================================================
Total params: 1,757
Trainable params: 1,757
Non-trainable params: 0
_________________________________________________________________

为什么解码端的前导维度是32?如果输入是从编码器传递的,为什么输入层的维度不是None, 4, 4, 4?我该如何解决这个问题?

提前感谢您对此的帮助!

【问题讨论】:

    标签: python tensorflow keras autoencoder dimensions


    【解决方案1】:

    在最后一个编码器层中删除stride=2,并在最后一个解码器层中添加stride=2

    from tensorflow.keras import layers
    from tensorflow.keras import Model
    
    class Denoise(Model):
      def __init__(self):
        super(Denoise, self).__init__()
        self.encoder = tf.keras.Sequential([
          layers.Input(shape=(28, 28, 1)), 
          layers.Conv2D(16, (3,3), activation='relu', padding='same', strides=2),
          layers.Conv2D(8, (3,3), activation='relu', padding='same', strides=2),
          ## New Layer ##
          layers.Conv2D(4, (3,3), activation='relu', padding='same')
          ## --------- ##
          ])
    
        self.decoder = tf.keras.Sequential([
          ## New Layer ##
          layers.Conv2DTranspose(4, kernel_size=3, strides=2, activation='relu', padding='same'),
          ## --------- ##
          layers.Conv2DTranspose(8, kernel_size=3, strides=2, activation='relu', padding='same'),
          layers.Conv2DTranspose(16, kernel_size=3, strides=2, activation='relu', padding='same'),
          layers.Conv2D(1, kernel_size=(3,3), activation='sigmoid', padding='same', strides=2)
          ])
    
      def call(self, x):
        encoded = self.encoder(x)
        decoded = self.decoder(encoded)
        return decoded
    
    autoencoder = Denoise()
    autoencoder.build(input_shape=(1, 28, 28, 1))
    autoencoder.summary()
    

    【讨论】:

    • 感谢@Nicolas Gervais!这对我有用!
    【解决方案2】:

    Keras 使用 32 作为默认的 batch_size。这可能与此有关。但要解决此问题,您可以在解码器中包含 input_shape 参数。

    self.decoder = tf.keras.models.Sequential([
          ## New Layer ##
          layers.Conv2DTranspose(4, kernel_size=3, strides=2, activation='relu', padding='same', input_shape=(4,4,4)),
          ## --------- ##
          layers.Conv2DTranspose(8, kernel_size=3, strides=2, activation='relu', padding='same'),
          layers.Conv2DTranspose(16, kernel_size=3, strides=2, activation='relu', padding='same'),
          layers.Conv2D(1, kernel_size=(3,3), activation='sigmoid', padding='same')
          ])
    

    另外,为了避免潜在的问题和一致性,我将tf.keras.models 用于模型(而不是tf.keras.Model)和tf.keras.layers 用于层。这可能不是问题..但可能会导致问题。

    【讨论】:

    • 感谢您对 @thushv89 的帮助!在将input_shape=(4,4,4)tf.keras.layerslayers 一起使用时,我仍然遇到一个问题,即我的解码器尺寸与编码器尺寸略有不同,即使我已经镜像了这些步骤。抛出以下错误:ValueError: Dimensions must be equal, but are 32 and 28 for '{{node mean_squared_error/SquaredDifference}} = SquaredDifference[T=DT_FLOAT](denoise_42/sequential_71/conv2d_147/Sigmoid, IteratorGetNext:1)' with input shapes: [32,32,32,1], [32,28,28,1].
    • 那是因为解码器的最终输出尺寸是 32x32。不是 28x28。您需要将输出大小调整为 32x32,或者需要使用更合适的输入/输出大小来调整编码器和解码器,这些输入/输出大小可以连续被 2 整除(这是步幅)
    • 非常感谢@thushv89!
    猜你喜欢
    • 2021-10-17
    • 1970-01-01
    • 2018-09-18
    • 1970-01-01
    • 2012-09-11
    • 2014-12-14
    • 2022-09-27
    • 1970-01-01
    • 2016-11-01
    相关资源
    最近更新 更多