title: Keras custom loss function error "No gradients provided"
body: <h1>Problem Description</h1>
  <p>I am trying to train a network with Keras based on TensorFlow 2.3.0. The task is to create new pictures. In a first simple prototype / proof of concept I am trying to train the network to create pictures just with a given amount of non-black pixel. Therefore I need to define a custom loss function. Doing so I get the <code>ValueError: No gradients provided for any variable</code> which I have not yet been able to solve.</p>
  <p>On top I would prefer a way to code this loss function without having to run eagerly <a href="https://stackoverflow.com/questions/63869134/converting-tensorflow-tensor-into-numpy-array">(see my previous question)</a>.</p>
  <h1>Code snippet</h1>
  <pre><code>def custom_loss(y_true, y_pred):
      ndarray = y_pred.numpy()
      mse = np.zeros(ndarray.shape[0])
      for i in range(ndarray.shape[0]):
          true_area = int(y_true[i][0] * 100000).numpy()
          pic = ndarray[i, :, :, :]
          img_np = (pic * 255).astype(np.uint8)
          img = tf.keras.preprocessing.image.array_to_img(img_np)
          count_area = count_nonblack_pil(img)
          mse[i] = ((count_area - true_area) / 100000)**2
          #img.save(f&quot;custom_loss {i:03d} True {true_area:06d} Count {count_area:06d} MSE {mse:0.4f}.jpg&quot;)
      return mse
  
  if __name__ == '__main__':
      tf.config.run_functions_eagerly(True)
      ...
      model.compile(loss=custom_loss, optimizer=&quot;adam&quot;, run_eagerly=True)
      model.fit(x=train_data, y=train_data, batch_size=16, epochs=10)
  </code></pre>
  <p>Running this code gives me the error message:</p>
  <pre><code>ValueError: No gradients provided for any variable: ['dense/kernel:0', 'dense/bias:0', 'conv2d/kernel:0', 'conv2d/bias:0', 'conv2d_1/kernel:0', 'conv2d_1/bias:0', 'conv2d_2/kernel:0', 'conv2d_2/bias:0', 'conv2d_3/kernel:0', 'conv2d_3/bias:0'].
  </code></pre>
  <h1>What I have tried so far</h1>
  <p>The error sounds like the loss function is not differentiable, but why shouldn't it be?</p>
  <p>Googling for a solution I found the suggestion, that I might have <a href="https://stackoverflow.com/questions/61570051/valueerror-no-gradients-provided-for-any-variable-conv2d-kernel0-conv2d">missed to pass the labels</a>, same <a href="https://stackoverflow.com/questions/62845878/tensorflow-valueerror-no-gradients-provided-for-any-variable">here</a>, but I already checked this by saving some pics with labels (see line commented out in the code above). This works just fine!</p>
  <p>Other than that I was not able to find any useful hint, all in all not too many google hits anyway ... (seems to be exotic what I am trying to do?). Any thoughts?</p>
  <h1>Edit</h1>
  <p>Thank you for your quick feedback and sorry for not describing the task of the loss function very clearly, let me give it another try:</p>
  <p>I have a model that creates a full 533x800 RGB picture based on a single float input, which is passed on to the loss function as <code>y_true</code>. The picture created by the model is also passed on to the loss function as <code>y_pred</code>. The loss function now calls a small function <code>count_nonblack_pil</code> to count the number of non-black pixels in <code>y_pred</code>. The loss is then calculated as the squared difference between <code>y_true</code> and the counted pixels. By minimizing this difference I expect to train the model so that is able to create a picture with a number of non-black pixels close to the input value. Not really useful, but a simple proof of concept of what I plan to do later with different loss function (where I want to use other already trained models to calculate the loss for more useful and sophisticated tasks).</p>
  <p>Hope that makes sense. To make it more clear:</p>
  <pre><code>y_true size : 16
  y_pred size : 20467200
  </code></pre>
  <p><code>y_pred</code> contains 16 pictures of 533x800 with 3 colors, i.e. 20467200.
  <code>y_true</code> contains just the 16 target values of pixels.</p>
  <h1>Edit: Solution</h1>
  <p>I have now understood the problem, nicely summarized by <a href="https://github.com/keras-team/keras/issues/4075" rel="nofollow noreferrer">JimBiardCics</a>: &quot;Keep in mind that the python function you write (custom_loss) is called to generate and compile a C function. The compiled function is what is called during training. When your python custom_loss function is called, the arguments are tensor objects that don't have data attached to them. The K.eval call will fail, as will the K.shape call.&quot;</p>