我在创建一个CNN,第一隐藏层的尺寸为80,其余卷积层的尺寸为160,最后一隐藏层的尺寸为128。但是我一直遇到一个错误信息,我不太明白它的意思。输入数据的形状是(80, 80, 1),这是我输入到神经网络中的数据。
以下是创建CNN的代码:
if start_model is not None: model = load_model(start_model) else: def res_net_block(input_layers, conv_size, hm_filters, hm_strides): x = Conv2D(conv_size, kernel_size=hm_filters, strides=hm_strides, activation="relu", padding="same")(input_layers) x = BatchNormalization()(x) x = Conv2D(conv_size, kernel_size=hm_filters, strides=hm_strides, activation=None, padding="same")(x) x = Add()([x, input_layers]) # Creates resnet block x = Activation("relu")(x) return x input = keras.Input(i_shape) x = Conv2D(80, kernel_size=8, strides=4, activation="relu")(input) x = BatchNormalization()(x) for i in range(3): x = res_net_block(x, 160, 4, 2) x = Conv2D(160, kernel_size=4, strides=2, activation="relu")(x) x = BatchNormalization()(x) x = Flatten(input_shape=(np.prod(window_size), 1, 1))(x) x = Dense(128, activation="relu")(x) output = Dense(action_space_size, activation="linear")(x) model = keras.Model(input, output) model.compile(optimizer=Adam(lr=0.01), loss="mse", metrics=["accuracy"])
顺便提一下,错误信息出现在代码中的 x = Add()([x, input_layers])
处
回答:
如果你应用一个 kernel_size
大于1 且 strides
大于1 的卷积,输出将比输入的维度小。
例如:
Conv2D(filters=6, kernel_size=5, stride=2)
会将维度为 (32,32,1)
的输入转换为维度为 (28,28,6)
的输出。这在尝试将此输出添加到 ResNet 风格的快捷块时会引起问题,因为不清楚如何将不同维度的张量相加。
有几种方法可以处理这个问题。
- 不通过卷积减小维度(保持stride=1)
- 通过使用与
Conv2D
中使用的相同步长的1×1卷积核来减小快捷块的尺寸 - 将快捷块的输出通道数更改为与
Conv2D
中的过滤器数量相同