title: How to use InceptionV3 bottlenecks as input in Keras 2.0
body: <p>I want to use bottlenecks for transfer learning using InceptionV3 in Keras.
  I've used some of the tips on creating, loading and using bottlenecks from
  <a href="https://blog.keras.io/building-powerful-image-classification-models-using-very-little-data.html" rel="nofollow noreferrer">https://blog.keras.io/building-powerful-image-classification-models-using-very-little-data.html</a></p>
  
  <p>My problem is that I don't know how to use a bottleneck (numpy array) as input to an InceptionV3 with a new top layer.</p>
  
  <p><strong>I get the following error:</strong></p>
  
  <blockquote>
    <p>ValueError: Error when checking input: expected input_3 to have shape
    (None, None, None, 3) but got array with shape (248, 8, 8, 2048)</p>
  </blockquote>
  
  <p>248 refers to the total number of images in this case.</p>
  
  <p>I know that this line is wrong, but I dont't know how to correct it:</p>
  
  <blockquote>
    <p>model = Model(inputs=base_model.input, outputs=predictions)</p>
  </blockquote>
  
  <p>What is the correct way to input the bottleneck into InceptionV3?</p>
  
  <p><strong>Creating the InceptionV3 bottlenecks:</strong></p>
  
  <pre><code>def create_bottlenecks():
  datagen = ImageDataGenerator(rescale=1. / 255)
  
  model = InceptionV3(include_top=False, weights='imagenet')
  
  # Generate bottlenecks for all training images
  generator = datagen.flow_from_directory(
      train_data_dir,
      target_size=(img_width, img_height),
      batch_size=batch_size,
      class_mode=None,
      shuffle=False)
  
  nb_train_samples = len(generator.filenames)
  bottlenecks_train = model.predict_generator(generator, int(math.ceil(nb_train_samples / float(batch_size))), verbose=1)
  np.save(open(train_bottlenecks_file, 'w'), bottlenecks_train)
  
  # Generate bottlenecks for all validation images
  generator = datagen.flow_from_directory(
      validation_data_dir,
      target_size=(img_width, img_height),
      batch_size=batch_size,
      class_mode=None,
      shuffle=False)
  
  nb_validation_samples = len(generator.filenames)
  
  bottlenecks_validation = model.predict_generator(generator, int(math.ceil(nb_validation_samples / float(batch_size))), verbose=1)
  np.save(open(validation_bottlenecks_file, 'w'), bottlenecks_validation)
  </code></pre>
  
  <p><strong>Loading the bottlenecks:</strong></p>
  
  <pre><code>def load_bottlenecks(src_dir, bottleneck_file):
      datagen = ImageDataGenerator(rescale=1. / 255)
      generator = datagen.flow_from_directory(
          src_dir,
          target_size=(img_width, img_height),
          batch_size=batch_size,
          class_mode='categorical',
          shuffle=False)
  
      num_classes = len(generator.class_indices)
  
      # load the bottleneck features saved earlier
      bottleneck_data = np.load(bottleneck_file)
  
      # get the class lebels for the training data, in the original order
      bottleneck_class_labels = generator.classes
  
      # convert the training labels to categorical vectors
      bottleneck_class_labels = to_categorical(bottleneck_class_labels, num_classes=num_classes)
  
      return bottleneck_data, bottleneck_class_labels
  </code></pre>
  
  <p><strong>Starting training:</strong></p>
  
  <pre><code>def start_training():
  global nb_train_samples, nb_validation_samples
  
  create_bottlenecks()
  
  train_data, train_labels = load_bottlenecks(train_data_dir, train_bottlenecks_file)
  validation_data, validation_labels = load_bottlenecks(validation_data_dir, validation_bottlenecks_file)
  
  nb_train_samples = len(train_data)
  nb_validation_samples = len(validation_data)
  
  base_model = InceptionV3(weights='imagenet', include_top=False)
  
  # add a global spatial average pooling layer
  x = base_model.output
  x = GlobalAveragePooling2D()(x)
  
  # let's add a fully-connected layer
  x = Dense(1024, activation='relu')(x)
  
  # and a logistic layer -- let's say we have 2 classes
  predictions = Dense(2, activation='softmax')(x)
  
  # What is the correct input? Obviously not base_model.input.
  model = Model(inputs=base_model.input, outputs=predictions)
  
  # first: train only the top layers (which were randomly initialized)
  # i.e. freeze all convolutional InceptionV3 layers
  for layer in base_model.layers:
      layer.trainable = False
  
  model.compile(optimizer=optimizers.SGD(lr=0.01, momentum=0.9), loss='categorical_crossentropy', metrics=['accuracy'])
  
  # train the model on the new data for a few epochs
  history = model.fit(train_data, train_labels,
                      epochs=epochs,
                      batch_size=batch_size,
                      validation_data=(validation_data, validation_labels),
  )
  </code></pre>
  
  <p>Any help would be appreciated!</p>