【问题标题】:Tensorflow + Keras training: InvalidArgumentError: Incompatible shapes: [7,128,2,2] vs [7,128,3,3]Tensorflow + Keras 训练:InvalidArgumentError:不兼容的形状:[7,128,2,2] vs [7,128,3,3]
【发布时间】:2019-10-20 02:04:04
【问题描述】:

在 tensorflow + keras 上实现和训练 Tiny-DSOD 网络。开始第一个 epoch 时,训练因错误而终止:tensorflow.python.framework.errors_impl.InvalidArgumentError: Incompatible shapes: [7,128,2,2] vs. [7,128,3,3]

批量大小为 8,图像大小为 (300,300),用于训练的数据集为 PASCAL VOC 2007+2012。错误发生在预测层的输出之一(非常类似于 SSD)和损失之间: [[{{节点 add_fpn_0_/add}}]] [[{{node loss/add_50}}]]

目前tensorflow的版本是1.13,keras是2.2.4。 Python 版本是 3.6。我已经检查了模型本身的所有内容(形状符合预期),为批次生成的图像(每个图像都符合预期),改变损失计算(当前使用 Adam,但也尝试使用 SGD,它完全一样问题。)并检查张量板是否可以提供任何信息(在终止点之前一切顺利)。

history = model.fit_generator(generator=train_generator,
                   steps_per_epoch=math.ceil(n_train_samples/batch_size),
                          epochs=epochs,
                          callbacks=[tf.keras.callbacks.ModelCheckpoint('tinydsod300_weights_epoch--{epoch:02d}_loss--{loss:.4f}_val_loss--{val_loss:.4f}.h5',
                                                                        monitor='val_loss',
                                                                        verbose=1,
                                                                        save_best_only=True,
                                                                        save_weights_only=True,
                                                                        mode='auto', period=1),
                                     tf.keras.callbacks.LearningRateScheduler(lr_schedule),
                                     tf.keras.callbacks.EarlyStopping(monitor='val_loss',
                                                                      min_delta=0.001,
                                                                      patience=2),
                                     tf.keras.callbacks.TerminateOnNaN(),
                                     tf.keras.callbacks.TensorBoard(log_dir='./logs'),
                                     tf.keras.callbacks.BaseLogger()],
                          validation_data=val_generator,
                          validation_steps=math.ceil(n_val_samples/batch_size)

完全错误:

WARNING:tensorflow:From /home/alexandre.pires/.conda/envs/neural_network/lib/python3.6/site-packages/tensorflow/python/ops/math_grad.py:102: div (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Deprecated in favor of operator or tf.math.divide.
2019-06-04 15:45:59.614299: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1512] Adding visible gpu devices: 0
2019-06-04 15:45:59.614330: I tensorflow/core/common_runtime/gpu/gpu_device.cc:984] Device interconnect StreamExecutor with strength 1 edge matrix:
2019-06-04 15:45:59.614337: I tensorflow/core/common_runtime/gpu/gpu_device.cc:990]      0 
2019-06-04 15:45:59.614341: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1003] 0:   N 
2019-06-04 15:45:59.614513: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1115] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 2998 MB memory) -> physical GPU (device: 0, name: GeForce GTX 1050 Ti, pci bus id: 0000:01:00.0, compute capability: 6.1)
Epoch 1/10
2019-06-04 15:46:28.296307: W tensorflow/core/common_runtime/bfc_allocator.cc:211] Allocator (GPU_0_bfc) ran out of memory trying to allocate 1.77GiB. The caller indicates that this is not a failure, but may mean that there could be performance gains if more memory were available.
Traceback (most recent call last):
  File "/home/alexandre.pires/PycharmProjects/neural_networks/tiny-dsod.py", line 830, in <module>
    validation_steps=math.ceil(n_val_samples/batch_size)
  File "/home/alexandre.pires/.conda/envs/neural_network/lib/python3.6/site-packages/tensorflow/python/keras/engine/training.py", line 1426, in fit_generator
    initial_epoch=initial_epoch)
  File "/home/alexandre.pires/.conda/envs/neural_network/lib/python3.6/site-packages/tensorflow/python/keras/engine/training_generator.py", line 191, in model_iteration
    batch_outs = batch_function(*batch_data)
  File "/home/alexandre.pires/.conda/envs/neural_network/lib/python3.6/site-packages/tensorflow/python/keras/engine/training.py", line 1191, in train_on_batch
    outputs = self._fit_function(ins)  # pylint: disable=not-callable
  File "/home/alexandre.pires/.conda/envs/neural_network/lib/python3.6/site-packages/tensorflow/python/keras/backend.py", line 3076, in __call__
    run_metadata=self.run_metadata)
  File "/home/alexandre.pires/.conda/envs/neural_network/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 1439, in __call__
    run_metadata_ptr)
  File "/home/alexandre.pires/.conda/envs/neural_network/lib/python3.6/site-packages/tensorflow/python/framework/errors_impl.py", line 528, in __exit__
    c_api.TF_GetCode(self.status.status))
tensorflow.python.framework.errors_impl.InvalidArgumentError: Incompatible shapes: [7,128,2,2] vs. [7,128,3,3]
     [[{{node add_fpn_0_/add}}]]
     [[{{node loss/add_50}}]]

最后要补充的是,预测层的先前输出确实具有形状 [7,128,2,2],但这从未产生任何错误。关于下一步我应该在哪里调试的任何提示?或者这个错误究竟来自哪里?

EDIT1 - 更正

在模型中进行了一些更正并出现了一个新错误,但仍然具有相同的不兼容形状:

tensorflow.python.framework.errors_impl.InvalidArgumentError: Incompatible shapes: [8,128,2,2] vs. [8,128,3,3]
     [[{{node add_fpn_0_/add}}]]
     [[{{node loss/predictions_loss/broadcast_weights/assert_broadcastable/is_valid_shape/has_valid_nonscalar_shape/has_invalid_dims/concat}}]]

对深度卷积进行了修正,以按照原始模型(在 caffe 中制作)中的预期行为。

卷积

        layer_name = "conv_" + name
        output = tf.keras.layers.Conv2D(filters=filter, kernel_size=kernel, padding=pad,
                                        strides=stride, kernel_initializer=self.kernel_initializer,
                                        kernel_regularizer=self.regularize, name=layer_name)(input)
        output = tf.keras.layers.BatchNormalization(name=layer_name + "batch_")(output)
        output = tf.keras.layers.Activation('relu', name=layer_name + "relu_")(output)

        return output

深度分析

        if stride == 2:
            output = tf.keras.layers.ZeroPadding2D(padding=self.correct_pad(input, kernel[0]),
                                                   name='zeropad_' + layer_name)(input)
            output = tf.keras.layers.DepthwiseConv2D(kernel_size=kernel, padding='SAME' if stride == 1 else 'VALID',
                                                     strides=stride, kernel_initializer=self.kernel_initializer,
                                                     kernel_regularizer=self.regularize, name=layer_name)(output)
        else:
            output = tf.keras.layers.DepthwiseConv2D(kernel_size=kernel, padding='SAME' if stride == 1 else 'VALID',
                                                     strides=stride, kernel_initializer=self.kernel_initializer,
                                                     kernel_regularizer=self.regularize, name=layer_name)(input)
        if use_batch_norm:
            output = tf.keras.layers.BatchNormalization(center=True, scale=True, trainable=True,
                                                        name=layer_name + "batch_")(output)
            output = tf.keras.layers.Activation('relu', name=layer_name + "relu_")(output)

上采样(简单双线性)

        layer_name = "upsample_" + name
        output = tf.keras.layers.UpSampling2D(size=(input_shape[0], input_shape[1]), interpolation='bilinear',
                                               name=layer_name)(input)
        output = self._depthwise_conv_2d(output, filter=128, kernel=(3, 3), pad='SAME', stride=1, name=layer_name)

        return output

【问题讨论】:

  • 您能分享一下您是如何定义模型的吗?
  • @AndrewXia 我添加了一些我目前已经实现的操作。由于工作原因,我不能透露更多。有关网络本身的更多信息,请查看bmvc2018.org/contents/papers/0145.pdf

标签: python tensorflow keras


【解决方案1】:

我认为问题在于网络内部的图像尺寸。

尝试改变这部分:

 output = self._depthwise_conv_2d(output, filter=128, kernel=(3, 3), pad='SAME', stride=1, name=layer_name)

为此。

 output = self._depthwise_conv_2d(output, filter=128, kernel=(2, 2), pad='SAME', stride=1, name=layer_name)

如果您看到输出,则表明您有一个包含 7 个元素的输出,即 128 个维度为 2 x 2 的过滤器,而您的网络有一个包含 7 个元素和 128 个维度为 3 x 3 的过滤器的输出。

如果我有帮助,请告诉我。

【讨论】:

  • 试试看你的网络输出的形状。不要只看网络的输出。问题可能是图像形状或相同层的输出。当我在“晦涩”的网络中遇到这个问题时,我会逐层查找并尝试找到输出形状。
  • 我做了一些更正并更新了帖子。我猜 caffe 在 tensorflow/keras 行为方面确实有一些变化。你有什么额外的建议吗?谢谢!
【解决方案2】:

我设法解决了这个问题。问题出在上采样层。我基于的模型是在 caffe 上使用双线性上采样 x2。 Caffe 的实现与 tensorflow/keras 中的不同。我制作了一个自定义测试层来检查这个假设并设法解决了这个问题。我现在使用的上采样层是这样的:

    def UpSampling2DBilinear(self, stride, **kwargs):
        def layer(x):
            input_shape = tf.keras.backend.int_shape(x)
            output_shape = (stride * (input_shape[1] - 1) + 1, stride * (input_shape[2] - 1) + 1)
            if output_shape[0] == 9:
                output_shape = (10,10)
            if output_shape[0] == 37:
                output_shape = (38,38)

            return tf.image.resize_bilinear(x, output_shape, align_corners=True)

        return tf.keras.layers.Lambda(layer, **kwargs)

显然,它不是最终的自定义图层解决方案,但目前它适用于 (300,300) 的输入图像大小。

因此,对于以后遇到类似问题的任何人,这里有一个对调试非常有帮助的步骤清单:

  • 预测中的不兼容形状错误,大多数情况下与您的模型有关。这意味着,在某些步骤中,您做错了什么。 Double/Triple/Quadruple 在每一层检查模型的每个输出(在这种情况下,keras 有一个 model.summary() 函数可以提供帮助)。

  • 如果您正在实现的模型,它的构造是基于 Caffe(或任何其他与您正在使用的框架不同的框架),请检查该层的实现细节。就我而言,我必须更改深度卷积、最大池化和上采样以适应所需的行为。

  • 确保损失函数、批处理生成器等也完全正确,以避免进一步的问题。

希望这对未来的许多人有所帮助,以对抗此类错误。感谢所有试图帮助我的人!

【讨论】:

    猜你喜欢
    • 2021-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-29
    • 1970-01-01
    • 2019-02-14
    • 1970-01-01
    • 2021-03-07
    相关资源
    最近更新 更多