Tensorflow + Keras + Convolution2d:ValueError:Filter不得大于输入:Filter:(5,5)输入:(3,350)

时间:2016-10-04 09:14:49

标签: python-2.7 tensorflow convolution keras

我一直在尝试运行我从here得到的代码,尽管我几乎没有改变图像大小(350,350而不是150,150),但仍然无法使其工作。我得到上面的过滤器错误(标题中),我理解但我没有做错,所以我不明白这一点。它基本上说我不能拥有比输入更多的节点,对吗?

我最终通过改变这一行来破解我的解决方案:

model.add(Convolution2D(32, 5, 5, border_mode='valid', input_shape=(3, IMG_WIDTH, IMG_HEIGHT)))

用这个:

model.add(Convolution2D(32, 5, 5, border_mode='valid', input_shape=(IMG_WIDTH, IMG_HEIGHT, 3)))

但我仍然想知道为什么会这样。

下面的代码以及我得到的错误。非常感谢一些帮助(我正在使用Python Anaconda 2.7.11)。

# IMPORT LIBRARIES --------------------------------------------------------------------------------#
import glob
import tensorflow
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Convolution2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from settings import RAW_DATA_ROOT

# GLOBAL VARIABLES --------------------------------------------------------------------------------#
TRAIN_PATH = RAW_DATA_ROOT + "/train/"
TEST_PATH = RAW_DATA_ROOT + "/test/"

IMG_WIDTH, IMG_HEIGHT = 350, 350

NB_TRAIN_SAMPLES = len(glob.glob(TRAIN_PATH + "*"))
NB_VALIDATION_SAMPLES = len(glob.glob(TEST_PATH + "*"))
NB_EPOCH = 50

# FUNCTIONS ---------------------------------------------------------------------------------------#
def baseline_model():
    """
    The Keras library provides wrapper classes to allow you to use neural network models developed
    with Keras in scikit-learn. The code snippet below is used to construct a simple stack of 3
    convolution layers with a ReLU activation and followed by max-pooling layers. This is very
    similar to the architectures that Yann LeCun advocated in the 1990s for image classification
    (with the exception of ReLU).
    :return: The training model.
    """
    model = Sequential()
    model.add(Convolution2D(32, 5, 5, border_mode='valid', input_shape=(3, IMG_WIDTH, IMG_HEIGHT)))
    model.add(Activation('relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))

    model.add(Convolution2D(32, 5, 5, border_mode='valid'))
    model.add(Activation('relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))

    model.add(Convolution2D(64, 5, 5, border_mode='valid'))
    model.add(Activation('relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))

    # Add a  fully connected layer layer that converts our 3D feature maps to 1D feature vectors
    model.add(Flatten())
    model.add(Dense(64))
    model.add(Activation('relu'))

    # Use a dropout layer to reduce over-fitting, by preventing a layer from seeing twice the exact
    # same pattern (works by switching off a node once in a while in different epochs...). This
    # will also serve as out output layer.
    model.add(Dropout(0.5))
    model.add(Dense(8))
    model.add(Activation('softmax'))

    # Compile model
    model.compile(loss='categorical_crossentropy',
                  optimizer='adam',
                  metrics=['accuracy'])

    return model

def train_model(model):
    """
    Simple script that uses the baseline model and returns a trained model.
    :param model: model
    :return: model
    """

    # Define the augmentation configuration we will use for training
    TRAIN_DATAGEN = ImageDataGenerator(
            rescale=1. / 255,
            shear_range=0.2,
            zoom_range=0.2,
            horizontal_flip=True)

    # Build the train generator
    TRAIN_GENERATOR = TRAIN_DATAGEN.flow_from_directory(
            TRAIN_PATH,
            target_size=(IMG_WIDTH, IMG_HEIGHT),
            batch_size=32,
            class_mode='categorical')

    TEST_DATAGEN = ImageDataGenerator(rescale=1. / 255)

    # Build the validation generator
    TEST_GENERATOR = TEST_DATAGEN.flow_from_directory(
            TEST_PATH,
            target_size=(IMG_WIDTH, IMG_HEIGHT),
            batch_size=32,
            class_mode='categorical')

    # Train model
    model.fit_generator(
            TRAIN_GENERATOR,
            samples_per_epoch=NB_TRAIN_SAMPLES,
            nb_epoch=NB_EPOCH,
            validation_data=TEST_GENERATOR,
            nb_val_samples=NB_VALIDATION_SAMPLES)

    # Always save your weights after training or during training
    model.save_weights('first_try.h5') 

# END OF FILE -------------------------------------------------------------------------------------#

和错误:

Using TensorFlow backend.
Training set: 0 files.
Test set: 0 files.
Traceback (most recent call last):
  File "/Users/christoshadjinikolis/GitHub_repos/datareplyuk/ODSC_Facial_Sentiment_Analysis/src/model/__init__.py", line 79, in <module>
    model = baseline_model()
  File "/Users/christoshadjinikolis/GitHub_repos/datareplyuk/ODSC_Facial_Sentiment_Analysis/src/model/training_module.py", line 31, in baseline_model
    model.add(Convolution2D(32, 5, 5, border_mode='valid', input_shape=(3, IMG_WIDTH, IMG_HEIGHT)))
  File "/Users/christoshadjinikolis/anaconda/lib/python2.7/site-packages/keras/models.py", line 276, in add
    layer.create_input_layer(batch_input_shape, input_dtype)
  File "/Users/christoshadjinikolis/anaconda/lib/python2.7/site-packages/keras/engine/topology.py", line 370, in create_input_layer
    self(x)
  File "/Users/christoshadjinikolis/anaconda/lib/python2.7/site-packages/keras/engine/topology.py", line 514, in __call__
    self.add_inbound_node(inbound_layers, node_indices, tensor_indices)
  File "/Users/christoshadjinikolis/anaconda/lib/python2.7/site-packages/keras/engine/topology.py", line 572, in add_inbound_node
    Node.create_node(self, inbound_layers, node_indices, tensor_indices)
  File "/Users/christoshadjinikolis/anaconda/lib/python2.7/site-packages/keras/engine/topology.py", line 149, in create_node
    output_tensors = to_list(outbound_layer.call(input_tensors[0], mask=input_masks[0]))
  File "/Users/christoshadjinikolis/anaconda/lib/python2.7/site-packages/keras/layers/convolutional.py", line 466, in call
    filter_shape=self.W_shape)
  File "/Users/christoshadjinikolis/anaconda/lib/python2.7/site-packages/keras/backend/tensorflow_backend.py", line 1579, in conv2d
    x = tf.nn.conv2d(x, kernel, strides, padding=padding)
  File "/Users/christoshadjinikolis/anaconda/lib/python2.7/site-packages/tensorflow/python/ops/gen_nn_ops.py", line 394, in conv2d
    data_format=data_format, name=name)
  File "/Users/christoshadjinikolis/anaconda/lib/python2.7/site-packages/tensorflow/python/framework/op_def_library.py", line 703, in apply_op
    op_def=op_def)
  File "/Users/christoshadjinikolis/anaconda/lib/python2.7/site-packages/tensorflow/python/framework/ops.py", line 2319, in create_op
    set_shapes_for_outputs(ret)
  File "/Users/christoshadjinikolis/anaconda/lib/python2.7/site-packages/tensorflow/python/framework/ops.py", line 1711, in set_shapes_for_outputs
    shapes = shape_func(op)
  File "/Users/christoshadjinikolis/anaconda/lib/python2.7/site-packages/tensorflow/python/framework/common_shapes.py", line 246, in conv2d_shape
    padding)
  File "/Users/christoshadjinikolis/anaconda/lib/python2.7/site-packages/tensorflow/python/framework/common_shapes.py", line 184, in get2d_conv_output_size
    (row_stride, col_stride), padding_type)
  File "/Users/christoshadjinikolis/anaconda/lib/python2.7/site-packages/tensorflow/python/framework/common_shapes.py", line 149, in get_conv_output_size
    "Filter: %r Input: %r" % (filter_size, input_size))
ValueError: Filter must not be larger than the input: Filter: (5, 5) Input: (3, 350)

2 个答案:

答案 0 :(得分:7)

问题是input_shape()的顺序会根据您使用的后端(tensorflow或theano)而改变。

我找到的最佳解决方案是在文件~/.keras/keras.json中定义此订单。

Try to use the theano order with tensorflow backend, or theano order with theano backend.

在家中创建keras目录并创建keras json:mkdir ~/.keras && touch ~/.keras/keras.json

{
    "image_dim_ordering": "th", 
    "epsilon": 1e-07, 
    "floatx": "float32", 
    "backend": "tensorflow"
}

答案 1 :(得分:5)

当我关注教程时,我自己遇到了同样的问题。正如@Yao Zhang所指出的那样,错误是由input_shape中的顺序引起的。有多种方法可以解决这个问题。

  • 选项1:更改input_shape
  • 中的顺序

代码行

model.add(Convolution2D(32, 5, 5, border_mode='valid', input_shape=(3, IMG_WIDTH, IMG_HEIGHT)))

应改为

model.add(Convolution2D(32, 5, 5, border_mode='valid', input_shape=(IMG_WIDTH, IMG_HEIGHT, 3)))
那应该没问题。

  • 选项2:在图层中指定image_dim_ordering

  • 选项3:通过在〜/ .keras / keras.json中将'tf'更改为'th'来修改keras配置文件