title: input_shape with image_generator in Tensorflow
body: <p>I'm trying to use this approach in Tensorflow 2.X to load large dataset that does not fit in memory.</p>
  
  <p>I have a folder with X sub-folders that contains images. Each sub-folder is a class.</p>
  
  <pre><code>\dataset
      -\class1
          -img1_1.jpg
          -img1_2.jpg
          -...
      -\classe2
          -img2_1.jpg
          -img2_2.jpg
          -...
  </code></pre>
  
  <p>I create my data generator from my folder like this:</p>
  
  <pre><code>train_data_gen = image_generator.flow_from_directory(directory="path\\to\\dataset",
                                                       batch_size=100,
                                                       shuffle=True,
                                                       target_size=(100, 100), # Image H x W
                                                       classes=list(CLASS_NAMES)) # list of folder/class names ["class1", "class2", ...., "classX"]
  </code></pre>
  
  <blockquote>
    <p>Found 629 images belonging to 2 classes.</p>
  </blockquote>
  
  <p>I've did a smaller dataset to test the pipeline. Only 629 images in 2 classes.
  Now I can create a dummy model like this:</p>
  
  <pre><code>model = tf.keras.Sequential()
  model.add(Dense(1, activation=activation, input_shape=(100, 100, 3))) # only 1 layer of 1 neuron
  model.add(Dense(2)) # 2classes
  model.compile(optimizer="adam", loss="categorical_crossentropy", metrics=['categorical_accuracy'])
  </code></pre>
  
  <p>Once compile I try to fit this dummy model:</p>
  
  <pre><code>STEPS_PER_EPOCH = np.ceil(image_count / batch_size) # 629 / 100
  model.fit_generator(generator=train_data_gen , steps_per_epoch=STEPS_PER_EPOCH, epochs=2, verbose=1)
  
  1/7 [===&gt;..........................] - ETA: 2s - loss: 1.1921e-07 - categorical_accuracy: 0.9948
  2/7 [=======&gt;......................] - ETA: 1s - loss: 1.1921e-07 - categorical_accuracy: 0.5124
  3/7 [===========&gt;..................] - ETA: 0s - loss: 1.1921e-07 - categorical_accuracy: 0.3449
  4/7 [================&gt;.............] - ETA: 0s - loss: 1.1921e-07 - categorical_accuracy: 0.2662
  5/7 [====================&gt;.........] - ETA: 0s - loss: 1.1921e-07 - categorical_accuracy: 0.2130
  6/7 [========================&gt;.....] - ETA: 0s - loss: 1.1921e-07 - categorical_accuracy: 0.1808
  </code></pre>
  
  <blockquote>
    <p>2020-04-14 20:39:48.629203: W tensorflow/core/framework/op_kernel.cc:1610] Invalid argument: ValueError: <code>generator</code> yielded an element of shape (29, 100, 100, 3) where an element of shape (100, 100, 100, 3) was expected.</p>
  </blockquote>
  
  <p>From what i understand, the last batch doesn't has the same shape has the previous batches. So it crashes. I've tried to specify a <code>batch_input_shape</code>.</p>
  
  <pre><code>model.add(Dense(1, activation=activation, batch_input_shape=(None, 100, 100, 3)))
  </code></pre>
  
  <p>I've found <a href="https://stackoverflow.com/a/52126464/5462743">here</a> that I should put <code>None</code> to not specify the number of elements in the batch so it can be dynamic. But no success.</p>
  
  <p>Edit: From the comment I had 2 mistakes:</p>
  
  <ul>
  <li>The output shape was bad. I missed the flatten layer in the model.</li>
  <li>The previous link does work with the correction of the flatten layer</li>
  <li>Missing some code, I actually feed the <code>fit_generator</code> with a <code>tf.data.Dataset.from_generator</code> but I gave here a <code>image_generator.flow_from_directory</code>.</li>
  </ul>
  
  <p>Here is the final code:</p>
  
  <pre><code>train_data_gen = image_generator.flow_from_directory(directory="path\\to\\dataset",
      batch_size=1000,
      shuffle=True,
      target_size=(100, 100),
      classes=list(CLASS_NAMES))
  
  train_dataset = tf.data.Dataset.from_generator(
      lambda: train_data_gen,
      output_types=(tf.float32, tf.float32),
      output_shapes=([None, x, y, 3],
      [None, len(CLASS_NAMES)]))
  
  model = tf.keras.Sequential()
  model.add(Flatten(batch_input_shape=(None, 100, 100, 3)))
  model.add(Dense(1, activation=activation))
  model.add(Dense(2))
  model.compile(optimizer="adam", loss="categorical_crossentropy", metrics=['categorical_accuracy'])
  
  STEPS_PER_EPOCH = np.ceil(image_count / batch_size) # 629 / 100
  model.fit_generator(generator=train_data_gen , steps_per_epoch=STEPS_PER_EPOCH, epochs=2, verbose=1)
  </code></pre>