keras 形状而 UpSampling 不匹配

Posted

技术标签:

【中文标题】keras 形状而 UpSampling 不匹配【英文标题】:keras shapes while UpSampling mismatch 【发布时间】:2018-11-04 00:56:34 【问题描述】:

我正在尝试使用我自己的数据运行此convolutional auto encoder 示例,因此我根据我的图像修改了它的 InputLayer。但是,在输出层上存在尺寸问题。我确定问题出在 UpSampling 上,但我不确定为什么会这样:代码如下。

N, H, W = X_train.shape
input_img = Input(shape=(H,W,1))  # adapt this if using `channels_first` image data format

x = Conv2D(16, (3, 3), activation='relu', padding='same')(input_img)
x = MaxPooling2D((2, 2), padding='same')(x)
x = Conv2D(8, (3, 3), activation='relu', padding='same')(x)
x = MaxPooling2D((2, 2), padding='same')(x)
x = Conv2D(8, (3, 3), activation='relu', padding='same')(x)
encoded = MaxPooling2D((2, 2), padding='same')(x)

# at this point the representation is (4, 4, 8) i.e. 128-dimensional

x = Conv2D(8, (3, 3), activation='relu', padding='same')(encoded)
x = UpSampling2D((2, 2))(x)
x = Conv2D(8, (3, 3), activation='relu', padding='same')(x)
x = UpSampling2D((2, 2))(x)
x = Conv2D(16, (3, 3), activation='relu')(x)
x = UpSampling2D((2, 2))(x)
decoded = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(x)

autoencoder = Model(input_img, decoded)
autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy')

autoencoder.summary()

然后,当我运行 fit 时,会引发此错误:

i+=1
autoencoder.fit(x_train, x_train,
            epochs=50,
            batch_size=128,
            shuffle=True,
            validation_data=(x_test, x_test),
            callbacks= [TensorBoard(log_dir='/tmp/autoencoder/'.format(i))])

ValueError: Error when checking target: expected conv2d_23 to have shape (148, 84, 1) but got array with shape (150, 81, 1)

我回到教程代码,并尝试查看其模型的摘要,它显示如下:

我确定在解码器上重建输出时存在问题,但我不确定为什么会这样,为什么它适用于 128x28 图像但不适用于 150x81 的地雷

我想我可以稍微改变一下我的图像尺寸来解决这个问题,但我想了解正在发生的事情以及如何避免它

【问题讨论】:

【参考方案1】:

您可以使用 ZeroPadding2D 填充输入图像为 32X32,然后使用 Cropping2D 裁剪解码图像。

from keras.layers import ZeroPadding2D, Cropping2D


input_img = Input(shape=(28,28,1))  # adapt this if using `channels_first` image data format
input_img_padding = ZeroPadding2D((2,2))(input_img)  #zero padding image to shape 32X32
x = Conv2D(16, (3, 3), activation='relu', padding='same')(input_img_padding)
x = MaxPooling2D((2, 2), padding='same')(x)
x = Conv2D(8, (3, 3), activation='relu', padding='same')(x)
x = MaxPooling2D((2, 2), padding='same')(x)
x = Conv2D(8, (3, 3), activation='relu', padding='same')(x)
encoded = MaxPooling2D((2, 2), padding='same')(x)

# at this point the representation is (4, 4, 8) i.e. 128-dimensional

x = Conv2D(8, (3, 3), activation='relu', padding='same')(encoded)
x = UpSampling2D((2, 2))(x)
x = Conv2D(8, (3, 3), activation='relu', padding='same')(x)
x = UpSampling2D((2, 2))(x)
x = Conv2D(16, (3, 3), activation='relu', padding='same')(x)
x = UpSampling2D((2, 2))(x)
decoded = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(x)
decoded_cropping = Cropping2D((2,2))(decoded)

autoencoder = Model(input_img, decoded_cropping) #cropping image from 32X32 to 28X28
autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy')

autoencoder.summary()

【讨论】:

【参考方案2】:

解码器的最后一层不使用任何填充。您可以通过将解码器中的最后一层更改为:

x = Conv2D(16, (3, 3), activation='relu', padding='same')(x)

您会看到输出暗淡现在将与输入暗淡匹配。

【讨论】:

【参考方案3】:

这是您在处理解码器或某种形式的上采样时面临的典型问题。

 您可能不知道的是,上采样或反卷积通常会导致高度和宽度增加,从而超出您的预期尺寸。

更准确地说: 在您的情况下,您期望和输出形状为(148, 84, 1),但是,由于上采样,您最终得到了(150, 81, 1)

这里的解决方案是在上采样后使用裁剪层裁剪输出:

tf.keras.layers.Cropping2D(cropping=(top_crop, bottom_crop), (left_crop, right_crop)) 

因此以你的情况为例:

tf.keras.layers.Cropping2D(cropping=(1, 1), (1, 2)) 
# or
tf.keras.layers.Cropping2D(cropping=(0, 2), (2, 1)) 
# or 
tf.keras.layers.Cropping2D(cropping=(2, 0), (1, 2)) 

这会将输出裁剪为从 (150, 81, 1) 到 (148, 84, 1) 的预期形状。

更多详情请参考: tf.keras.layers.Cropping2D

【讨论】:

以上是关于keras 形状而 UpSampling 不匹配的主要内容,如果未能解决你的问题,请参考以下文章

为啥我得到 Keras 形状不匹配?

Python:keras 形状不匹配错误

Keras:密集层和激活层之间的形状不匹配

Recurrentshop 和 Keras:多维 RNN 导致维度不匹配错误

Keras 功能 api 输入形状错误,lstm 层收到 2d 而不是 3d 形状

Tensorflow Keras 修改 Iris 示例时形状不兼容