title: ValueError: No gradients provided for any variable - Tensorflow 2.0/Keras
body: <p>I am trying to implement a simple sequence-to-sequence model using Keras. However, I keep seeing the following <code>ValueError</code>:</p>
  
  <pre><code>ValueError: No gradients provided for any variable: ['simple_model/time_distributed/kernel:0', 'simple_model/time_distributed/bias:0', 'simple_model/embedding/embeddings:0', 'simple_model/conv2d/kernel:0', 'simple_model/conv2d/bias:0', 'simple_model/dense_1/kernel:0', 'simple_model/dense_1/bias:0'].
  </code></pre>
  
  <p>Other questions like <a href="https://stackoverflow.com/questions/41689451/valueerror-no-gradients-provided-for-any-variable">this</a> or looking at <a href="https://github.com/tensorflow/tensorflow/issues/1511" rel="noreferrer">this issue</a> on Github suggests that this might have something to do with the cross-entropy loss function; but I fail to see what I am doing wrong here.</p>
  
  <p>I do not think that this is the problem, but I want to mention that I am on a nightly build of TensorFlow, <code>tf-nightly==2.2.0.dev20200410</code> to be precise.</p>
  
  <p>This following code is a standalone example and should reproduce the exception from above:</p>
  
  <pre><code>import random
  from functools import partial
  
  import tensorflow as tf
  from tensorflow import keras
  from tensorflow_datasets.core.features.text import SubwordTextEncoder
  
  EOS = '&lt;eos&gt;'
  PAD = '&lt;pad&gt;'
  
  RESERVED_TOKENS = [EOS, PAD]
  EOS_ID = RESERVED_TOKENS.index(EOS)
  PAD_ID = RESERVED_TOKENS.index(PAD)
  
  dictionary = [
      'verstehen',
      'verstanden',
      'vergessen',
      'verlegen',
      'verlernen',
      'vertun',
      'vertan',
      'verloren',
      'verlieren',
      'verlassen',
      'verhandeln',
  ]
  
  dictionary = [word.lower() for word in dictionary]
  
  
  class SimpleModel(keras.models.Model):
  
      def __init__(self, params, *args, **kwargs):
          super().__init__(*args, **kwargs)
  
          self.params = params
          self.out_layer = keras.layers.Dense(1, activation='softmax')
  
          self.model_layers = [
              keras.layers.Embedding(params['vocab_size'], params['vocab_size']),
              keras.layers.Lambda(lambda l: tf.expand_dims(l, -1)),
              keras.layers.Conv2D(1, 4),
              keras.layers.MaxPooling2D(1),
              keras.layers.Dense(1, activation='relu'),
              keras.layers.TimeDistributed(self.out_layer)
          ]
  
      def call(self, example, training=None, mask=None):
          x = example['inputs']
          for layer in self.model_layers:
              x = layer(x)
          return x
  
  
  def sample_generator(text_encoder: SubwordTextEncoder, max_sample: int = None):
      count = 0
  
      while True:
          random.shuffle(dictionary)
  
          for word in dictionary:
  
              for i in range(1, len(word)):
  
                  inputs = word[:i]
                  targets = word
  
                  example = dict(
                      inputs=text_encoder.encode(inputs) + [EOS_ID],
                      targets=text_encoder.encode(targets) + [EOS_ID],
                  )
                  count += 1
  
                  yield example
  
                  if max_sample is not None and count &gt;= max_sample:
                      print('Reached max_samples (%d)' % max_sample)
                      return
  
  
  def make_dataset(generator_fn, params, training):
  
      dataset = tf.data.Dataset.from_generator(
          generator_fn,
          output_types={
              'inputs': tf.int64,
              'targets': tf.int64,
          }
      ).padded_batch(
          params['batch_size'],
          padded_shapes={
              'inputs': (None,),
              'targets': (None,)
          },
      )
  
      if training:
          dataset = dataset.map(partial(prepare_example, params=params)).repeat()
  
      return dataset
  
  
  def prepare_example(example: dict, params: dict):
      # Make sure targets are one-hot encoded
      example['targets'] = tf.one_hot(example['targets'], depth=params['vocab_size'])
      return example
  
  
  def main():
  
      text_encoder = SubwordTextEncoder.build_from_corpus(
          iter(dictionary),
          target_vocab_size=1000,
          max_subword_length=6,
          reserved_tokens=RESERVED_TOKENS
      )
  
      generator_fn = partial(sample_generator, text_encoder=text_encoder, max_sample=10)
  
      params = dict(
          batch_size=20,
          vocab_size=text_encoder.vocab_size,
          hidden_size=32,
          max_input_length=30,
          max_target_length=30
      )
  
      model = SimpleModel(params)
  
      model.compile(
          optimizer='adam',
          loss='categorical_crossentropy',
      )
  
      train_dataset = make_dataset(generator_fn, params, training=True)
      dev_dataset = make_dataset(generator_fn, params, training=False)
  
      # Peek data
      for train_batch, dev_batch in zip(train_dataset, dev_dataset):
          print(train_batch)
          print(dev_batch)
          break
  
      model.fit(
          train_dataset,
          epochs=1000,
          steps_per_epoch=100,
          validation_data=dev_dataset,
          validation_steps=100,
      )
  
  
  if __name__ == '__main__':
      main()
  
  </code></pre>
  
  <h3>Update</h3>
  
  <ul>
  <li>Gist <a href="https://gist.github.com/stefan-falk/42ef89c6636fd9f91fc471584659512f" rel="noreferrer">link</a></li>
  <li>Github issue <a href="https://github.com/tensorflow/tensorflow/issues/38631" rel="noreferrer">link</a></li>
  </ul>