Search code examples
pythontensorflowkerastf.kerasautoencoder

No Gradients Provided Keras Tensorflow when nesting Models


Im started to work with Keras a little bit but i run in to this issue where it tells me that no gradients are provided. I know that this question was posted like 100 times before but the solutions are always talking about using GradientTape but i don't see why i should do this (also i don't even understand what it does)


import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import matplotlib.pyplot as plt

physical_devices = tf.config.list_physical_devices('GPU')
tf.config.experimental.set_memory_growth(physical_devices[0], True)

class AutoEncoder:

    def create_encoder(self):
        encoder_input = keras.Input(shape=self.input_shape, name="original_img")
        encoder_output = layers.Conv2D(3, 3, activation="relu")(encoder_input)
        encoder = keras.Model(encoder_input, encoder_output)
        return encoder_input, encoder_output, encoder

    def create_decoder(self, eager_execution=False):
        decoder_input = keras.Input(shape=self.encoder_output.type_spec.shape[1:], batch_size=self.batch_size, name="encoded_img")
        decoder_output = layers.Conv2DTranspose(3, 3, activation="relu")(decoder_input)
        decoder = keras.Model(decoder_input, decoder_output)
        return decoder_input, decoder_output, decoder


    def create_autoencoder(self):
        auto_input = keras.Input(shape=self.input_shape, batch_size=self.batch_size, name="AutoEncoder Input")
        encoded = self.encoder(auto_input)
        auto_output = self.decoder(encoded)
        autoencoder = keras.Model(auto_input, auto_output, name="AutoEncoder")
        return auto_input, auto_output, autoencoder

    def __init__(self, input_shape=(256, 256, 3), batch_size=32, eager_execution=False):
        self.input_shape = input_shape
        self.batch_size = batch_size
        self.encoder_input, self.encoder_output, self.encoder = self.create_encoder()
        self.decoder_input, self.decoder_output, self.decoder = self.create_decoder()
        self.autoencoder_input, self.autoencoder_output, self.autoencoder = self.create_autoencoder()
        self.__call__ = self.autoencoder.predict
        self.fit = self.autoencoder.fit
        self.fit_generator = self.autoencoder.fit_generator

        # Compiling models

        self.autoencoder.compile(
            optimizer=keras.optimizers.Adagrad(),
            loss=keras.losses.SparseCategoricalCrossentropy(),
            metrics=keras.metrics.Accuracy(),
            run_eagerly=True,
        )


autoenc = AutoEncoder()
autoenc.autoencoder.fit(train_x)

For the Training i use some Dataset from Microsoft with PetImages. But that shouldnt matter too much.

I already tried rearranging everything but the error pops up everytime when i call a model and then create another model with the output of that model.

Traceback (most recent call last):
  File "/home/user/PycharmProjects/pythonProject1/main.py", line 148, in <module>
    autoenc.autoencoder.fit(train_x)
  File "/home/user/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/keras/engine/training.py", line 1100, in fit
    tmp_logs = self.train_function(iterator)
  File "/home/user/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/keras/engine/training.py", line 805, in train_function
    return step_function(self, iterator)
  File "/home/user/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/keras/engine/training.py", line 795, in step_function
    outputs = model.distribute_strategy.run(run_step, args=(data,))
  File "/home/user/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/distribute/distribute_lib.py", line 1259, in run
    return self._extended.call_for_each_replica(fn, args=args, kwargs=kwargs)
  File "/home/user/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/distribute/distribute_lib.py", line 2730, in call_for_each_replica
    return self._call_for_each_replica(fn, args, kwargs)
  File "/home/user/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/distribute/distribute_lib.py", line 3417, in _call_for_each_replica
    return fn(*args, **kwargs)
  File "/home/user/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/autograph/impl/api.py", line 572, in wrapper
    return func(*args, **kwargs)
  File "/home/user/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/keras/engine/training.py", line 788, in run_step
    outputs = model.train_step(data)
  File "/home/user/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/keras/engine/training.py", line 757, in train_step
    self.optimizer.minimize(loss, self.trainable_variables, tape=tape)
  File "/home/user/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/keras/optimizer_v2/optimizer_v2.py", line 498, in minimize
    return self.apply_gradients(grads_and_vars, name=name)
  File "/home/user/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/keras/optimizer_v2/optimizer_v2.py", line 598, in apply_gradients
    grads_and_vars = optimizer_utils.filter_empty_gradients(grads_and_vars)
  File "/home/user/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/keras/optimizer_v2/utils.py", line 78, in filter_empty_gradients
    raise ValueError("No gradients provided for any variable: %s." %
ValueError: No gradients provided for any variable: ['conv2d/kernel:0', 'conv2d/bias:0', 'conv2d_transpose/kernel:0', 'conv2d_transpose/bias:0'].

Process finished with exit code 1

Versions of everything

# Name                    Version                   Build  Channel
tensorflow                2.2.0           gpu_py38hb782248_0  
tensorflow-base           2.2.0           gpu_py38h83e3d50_0  
tensorflow-datasets       4.1.0                    pypi_0    pypi
tensorflow-estimator      2.4.0                    pypi_0    pypi
tensorflow-gpu            2.4.0                    pypi_0    pypi
tensorflow-metadata       0.26.0                   pypi_0    pypi
tensorflow-probability    0.12.0                   pypi_0    pypi
tensorflow-serving-api    2.3.0                    pypi_0    pypi

System 
    Archlinux 
    linux-5.10.3.arch1-1
    cuda-11.2.0-2
    cudnn-8.0.5.39-1

I hope someone has an idea on what i should change to get this to work.

Best Regards, MrDiver


Solution

  • I fixed your code. When you get that error, there is not path in the graph between your loss function and your trainable variables, which was true in your case.

    1. You don't have labels to train your autoencoder. I added train_x as your labels.
    2. I don't think SparseCategoricalCrossentropy would work for the architecture you have defined. So, I changed it to BinaryCrossEntropy
    3. When you assigned a name to a vector, spaces are not allowed, so I changed "AutoEncoder Input" to "AutoEncoder_Input"

    Here is the code

    import tensorflow as tf
    from tensorflow import keras
    from tensorflow.keras import layers
    import matplotlib.pyplot as plt
    from tensorflow.keras.preprocessing.image import ImageDataGenerator
    
    #physical_devices = tf.config.list_physical_devices('GPU')
    #tf.config.experimental.set_memory_growth(physical_devices[0], True)
    
    class AutoEncoder:
    
        def create_encoder(self):
            encoder_input = keras.Input(shape=self.input_shape, name="original_img")
            encoder_output = layers.Conv2D(3, 3, activation="relu")(encoder_input)
            encoder = keras.Model(encoder_input, encoder_output)
            return encoder_input, encoder_output, encoder
    
        def create_decoder(self, eager_execution=False):
            decoder_input = keras.Input(shape=self.encoder_output.shape[1:], batch_size=self.batch_size, name="encoded_img")
            decoder_output = layers.Conv2DTranspose(3, 3, activation="relu")(decoder_input)
            decoder = keras.Model(decoder_input, decoder_output)
            return decoder_input, decoder_output, decoder
    
    
        def create_autoencoder(self):
            auto_input = keras.Input(shape=self.input_shape, batch_size=self.batch_size, name="AutoEncoder_Input")
            encoded = self.encoder(auto_input)
            auto_output = self.decoder(encoded)
            autoencoder = keras.Model(auto_input, auto_output, name="AutoEncoder")
            return auto_input, auto_output, autoencoder
    
        def __init__(self, input_shape=(256, 256, 3), batch_size=32, eager_execution=False):
            self.input_shape = input_shape
            self.batch_size = batch_size
            self.encoder_input, self.encoder_output, self.encoder = self.create_encoder()
            self.decoder_input, self.decoder_output, self.decoder = self.create_decoder()
            self.autoencoder_input, self.autoencoder_output, self.autoencoder = self.create_autoencoder()
            self.__call__ = self.autoencoder.predict
            self.fit = self.autoencoder.fit
            self.fit_generator = self.autoencoder.fit_generator
    
            # Compiling models
    
            self.autoencoder.compile(
                optimizer=keras.optimizers.Adagrad(),
                loss=keras.losses.BinaryCrossentropy(),
                metrics=keras.metrics.Accuracy(),
                run_eagerly=True,
            )
            
    
    
    
    train_x = tf.random.normal(shape=(100,256,256,3),dtype=tf.float32)
    autoenc = AutoEncoder()
    print(autoenc.autoencoder.summary())
    autoenc.autoencoder.fit(train_x,train_x)