预期 conv2d_7 的形状为 (4, 268, 1) 但得到的数组形状为 (1, 270, 480)

Posted

技术标签:

【中文标题】预期 conv2d_7 的形状为 (4, 268, 1) 但得到的数组形状为 (1, 270, 480)【英文标题】:expected conv2d_7 to have shape (4, 268, 1) but got array with shape (1, 270, 480) 【发布时间】:2019-08-10 11:24:36 【问题描述】:

我在使用 Keras 构建的自动编码器时遇到问题。输入的形状取决于屏幕尺寸,输出将是对下一个屏幕尺寸的预测......但是似乎有一个我无法弄清楚的错误......请原谅我在这个网站上的糟糕格式...

代码:

def model_build():
input_img = InputLayer(shape=(1, env_size()[1], env_size()[0]))
x = Conv2D(32, (3, 3), activation='relu', padding='same')(input_img)
x = MaxPooling2D((2, 2), padding='same')(x)
x = Conv2D(16, (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)
x = Conv2D(8, (3, 3), activation='relu', padding='same')(encoded)
x = UpSampling2D((2, 2))(x)
x = Conv2D(16, (3, 3), activation='relu', padding='same')(x)
x = UpSampling2D((2, 2))(x)
x = Conv2D(32, (3, 3), activation='relu')(x)
x = UpSampling2D((2, 2))(x)
decoded = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(x)
model = Model(input_img, decoded)
return model
if __name__ == '__main__':
    model = model_build()
    model.compile('adam', 'mean_squared_error')
    y = np.array([env()])
    print(y.shape)
    print(y.ndim)
    debug = model.fit(np.array([[env()]]), np.array([[env()]]))

错误:

Traceback(最近一次调用最后一次): 文件“/home/ai/Desktop/algernon-test/rewarders.py”,第 46 行,在 调试 = model.fit(np.array([[env()]]), np.array([[env()]])) 文件“/home/ai/.local/lib/python3.6/site-packages/keras/engine/training.py”,第 952 行,适合 批次大小=批次大小) _standardize_user_data 中的文件“/home/ai/.local/lib/python3.6/site-packages/keras/engine/training.py”,第 789 行 exception_prefix='目标') 文件“/home/ai/.local/lib/python3.6/site-packages/keras/engine/training_utils.py”,第 138 行,位于standardize_input_data str(数据形状)) ValueError: 检查目标时出错:预期 conv2d_7 的形状为 (4, 268, 1) 但得到的数组的形状为 (1, 270, 480)

编辑:

作为 env() 导入的 get_screen 代码:

def get_screen():
    img = screen.grab()
    img = img.resize(screen_size())
    img = img.convert('L')
    img = np.array(img)
    return img

【问题讨论】:

数据的原始形状是什么?为env()添加代码decoded = 行发生错误? @Sharky。没有所谓的“数据的原始形状”......基本上我只是想要自动编码器的损失(作为对我的 rl 代理的奖励......)当前屏幕及其分辨率除以 4 是我猜数据的形状,以及变成灰度...... 【参考方案1】:

您有三个 2x 下采样步骤和三个 x2 上采样步骤。这些步骤不知道原始图像的大小,因此它们会将大小四舍五入到最接近的 8 = 2^3 的倍数。

cropX = 7 - ((size[0]+7) % 8)
cropY = 7 - ((size[1]+7) % 8)

cropX = 7 - ((npix+7) % 8)
cropY = 7 - ((nlin+7) % 8)

如果你添加一个新的最终层应该可以工作......

decoded = layers.Cropping2D(((0,cropY),(0,cropX)))(x)

【讨论】:

【参考方案2】:

看起来像 env_size()env() 以某种方式混淆图像尺寸。考虑这个例子:

image1 = np.random.rand(1, 1, 270, 480) #First dimension is batch size for test purpose
image2 = np.random.rand(1, 4, 268, 1) #Or any other arbitrary dimensions

input_img = layers.Input(shape=image1[0].shape)
x = layers.Conv2D(32, (3, 3), activation='relu', padding='same')(input_img)
x = layers.MaxPooling2D((2, 2), padding='same')(x)
x = layers.Conv2D(16, (3, 3), activation='relu', padding='same')(x)
x = layers.MaxPooling2D((2, 2), padding='same')(x)
x = layers.Conv2D(8, (3, 3), activation='relu', padding='same')(x)
encoded = layers.MaxPooling2D((2, 2), padding='same')(x)
x = layers.Conv2D(8, (3, 3), activation='relu', padding='same')(encoded)
x = layers.UpSampling2D((2, 2))(x)
x = layers.Conv2D(16, (3, 3), activation='relu', padding='same')(x)
x = layers.UpSampling2D((2, 2))(x)
x = layers.Conv2D(32, (3, 3), activation='relu')(x)
x = layers.UpSampling2D((2, 2))(x)
decoded = layers.Conv2D(1, (3, 3), activation='sigmoid', padding='same')(x)
model = tf.keras.Model(input_img, decoded)
model.compile('adam', 'mean_squared_error')
model.summary()

这条线会起作用:

model.fit(image1, nb_epoch=1, batch_size=1)

但这不是

model.fit(image2, nb_epoch=1, batch_size=1)

编辑: 为了获得与输入大小相同的输出,您需要仔细计算卷积核大小。 image1 = np.random.rand(1, 1920, 1080, 1)

input_img = layers.Input(shape=image1[0].shape)
x = layers.Conv2D(32, 3, activation='relu', padding='same')(input_img)
x = layers.MaxPooling2D((2, 2), padding='same')(x)
x = layers.Conv2D(16, 3, activation='relu', padding='same')(x)
x = layers.MaxPooling2D((2, 2), padding='same')(x)
x = layers.Conv2D(8, 3, activation='relu', padding='same')(x)
encoded = layers.MaxPooling2D((2, 2), padding='same')(x)
x = layers.Conv2D(8, 3, activation='relu', padding='same')(encoded)
x = layers.UpSampling2D((2, 2))(x)
x = layers.Conv2D(16, 3, activation='relu', padding='same')(x)
x = layers.UpSampling2D((2, 2))(x)
x = layers.Conv2D(32, 1, activation='relu')(x) # set kernel size to 1 for example
x = layers.UpSampling2D((2, 2))(x)
decoded = layers.Conv2D(1, 3, activation='sigmoid', padding='same')(x)
model = tf.keras.Model(input_img, decoded)
model.compile('adam', 'mean_squared_error')
model.summary()

这将输出相同的尺寸。

根据本指南http://cs231n.github.io/convolutional-networks/

我们可以将输出体积的空间大小计算为 输入体积大小(W),Conv层的感受野大小 神经元 (F)、它们所应用的步幅 (S) 以及 边框上使用的零填充量 (P)。你可以说服 自己认为计算多少神经元的正确公式 “适合”由 (W−F+2P)/S+1 给出。例如对于 7x7 输入和 3x3 使用步幅 1 和填充 0 进行过滤,我们将得到 5x5 的输出。迈着大步 2 我们会得到一个 3x3 的输出。

【讨论】:

(1920, 高度) ? 一直不小心按回车键,抱歉。嗯,真的不明白这个...假设屏幕是 1920 x 1080...忽略任何先前的调整大小,并将屏幕灰度输入网络...网络应该期望相同的形状作为输入和输出的形状......预期的输出应该与输入的形状相同。希望这是有道理的...... 所以你需要你的网络返回以下形状(1920、1080、num_cov_filters)? 已更新答案,希望对您有所帮助 如何计算其他屏幕尺寸的卷积核尺寸?

以上是关于预期 conv2d_7 的形状为 (4, 268, 1) 但得到的数组形状为 (1, 270, 480)的主要内容,如果未能解决你的问题,请参考以下文章

Python | Keras:ValueError:检查目标时出错:预期conv2d_3有4个维度,但得到了有形状的数组(1006,5)

检查目标时出错:预期density_3具有2维,但数组的形状为(5,200,200,1)

ValueError:conv2d 层的输入 0 与层不兼容::预期 min_ndim=4,发现 ndim=3。收到的完整形状:(256、256、256)

model.fit 给出 ValueError :检查输入时出错:预期的 conv2d 得到了形状为 () 的数组

conv2d 层的输入 0 与层不兼容:输入形状的预期轴 -1 具有值 1,但接收到形状为 [None, 64, 64, 3] 的输入

ValueError:输入 0 与层 conv2d_1 不兼容:预期 ndim=4,发现 ndim=3