“conv2d_2/convolution”由于将1减去3导致负的尺寸大小。

21

在Keras中声明输入层时我遇到了以下错误信息。

ValueError: 由于从[?,1,28,28]维度中减去3导致 'conv2d_2/convolution'(op:'Conv2D')出现负维度。 [3,3,28,32]

我的代码如下所示

model.add(Convolution2D(32, 3, 3, activation='relu', input_shape=(1,28,28)))

示例应用程序:https://github.com/IntellijSys/tensorflow/blob/master/Keras.ipynb


2
我认为你想使用一个3x3的内核。在这种情况下,你应该写(3, 3)而不是3, 3 - ml4294
如何找出使用 (3,3)、(4,4) 或 (5,5) 有什么不同?@ml4294 - kRazzy R
6个回答

45

默认情况下,Convolution2D (https://keras.io/layers/convolutional/) 期望输入数据的格式是(samples, rows, cols, channels),也就是“channels-last”的格式。但你的数据似乎是(samples, channels, rows, cols)的格式。在声明Convolution2D层时,使用可选关键字data_format = 'channels_first',可以解决这个问题。

model.add(Convolution2D(32, (3, 3), activation='relu', input_shape=(1,28,28), data_format='channels_first'))

我会先尝试一下。 - Nurdin
4
请注意,它可以在 ~/.keras/keras.json 中全局设置:"image_data_format": "channels_first"。 - Shaohua Li

41

我遇到了同样的问题,但是在这个帖子中提供的解决方法并没有帮助我。

在我的情况下,导致这个错误的是另一个不同的问题:


代码

imageSize=32
classifier=Sequential() 

classifier.add(Conv2D(64, (3, 3), input_shape = (imageSize, imageSize, 3), activation = 'relu'))
classifier.add(MaxPooling2D(pool_size = (2, 2)))

classifier.add(Conv2D(64, (3, 3), activation = 'relu'))
classifier.add(MaxPooling2D(pool_size = (2, 2)))

classifier.add(Conv2D(64, (3, 3), activation = 'relu')) 
classifier.add(MaxPooling2D(pool_size = (2, 2)))

classifier.add(Conv2D(64, (3, 3), activation = 'relu')) 
classifier.add(MaxPooling2D(pool_size = (2, 2)))

classifier.add(Conv2D(64, (3, 3), activation = 'relu')) 
classifier.add(MaxPooling2D(pool_size = (2, 2)))

classifier.add(Flatten())

Error

图像大小为32x32。在第一层卷积后,它被缩小到30x30。(如果我正确理解了卷积的话)

然后池化层会将其分成15x15。

接下来又有一层卷积将其缩小至13x13...

我希望你能看到这样做的结果:最终,我的特征图如此之小,以至于我的池化层(或卷积层)过不去,导致出现错误。


Solution

解决此问题的简单方法是要么使图像大小更大,要么使用较少的卷积层或池化层。


7
非常重要!我曾经处于同样的情况。 - Eduardo G.R.
1
太棒了!我遇到了同样的问题,现在我知道原因了! - Vasanth Nag K V

5
Keras提供以下后端兼容性:

TensorFlow:由Google开发, Theano:由LISA实验室开发, CNTK:由Microsoft开发

如果您看到[?,X,X,X],[X,Y,Z,X]等错误,这是通道问题。为了解决这个问题,请使用Keras的自动模式:

导入

from keras import backend as K
K.set_image_dim_ordering('th')

"tf"格式表示卷积核的形状为(rows, cols, input_depth, depth)。
这种方式总是有效的...

最简单的解决方案几乎总是最好的。 - nino_701
这个答案让我在自己的环境中找到了解决方案,但似乎在后来的Keras版本中有一些东西被重命名了:https://github.com/keras-team/keras/issues/12649 - Dave Seidman

0

你可以通过设置值为“same”来保留体积的空间尺寸,以便输出体积的大小与输入体积的大小相匹配。

使用padding='same'


0
    # define the model as a class
class LeNet:

  '''
      In a sequential model, we stack layers sequentially. 
      So, each layer has unique input and output, and those inputs and outputs 
      then also come with a unique input shape and output shape.

  '''

  @staticmethod                ## class can instantiated only once 
  def init(numChannels, imgRows, imgCols , numClasses, weightsPath=None):

    # if we are using channel first we have update the input size
    if backend.image_data_format() == "channels_first":
      inputShape = (numChannels , imgRows , imgCols)
    else: 
      inputShape = (imgRows , imgCols , numChannels)

    # initilize the model
    model = models.Sequential()

    # Define the first set of CONV => ACTIVATION => POOL LAYERS

    model.add(layers.Conv2D(  filters=6,kernel_size=(5,5),strides=(1,1), 
                              padding="valid",activation='relu',kernel_initializer='he_uniform',input_shape=inputShape))
    model.add(layers.AveragePooling2D(pool_size=(2,2),strides=(2,2)))

希望能对您有所帮助 :)

查看代码:Fashion_Mnist_Using_LeNet_CNN


0
请使用以下内容:
from keras import backend
backend.set_image_data_format('channels_last')

根据您的偏好,您可以使用'channels_first''channels_last'来设置图像数据格式。(源代码)
如果这不起作用且您的图像尺寸较小,请尝试减少CNN的结构,正如之前的帖子所提到的。
希望对您有所帮助!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接